#ifndef _Data_Files #define _Data_Files /* This class holds the Online data files all in one place * so the streams are easy to pass around and access */ #include "Math/field_types.h" #include "Tools/Buffer.h" #include "Processor/InputTuple.h" #include "Tools/Lock.h" #include "Networking/Player.h" #include #include using namespace std; class DataTag { int t[4]; public: // assume that tag is three integers DataTag(const int* tag) { strncpy((char*)t, (char*)tag, 3 * sizeof(int)); t[3] = 0; } string get_string() const { return string((char*)t); } bool operator<(const DataTag& other) const { for (int i = 0; i < 3; i++) if (t[i] != other.t[i]) return t[i] < other.t[i]; return false; } }; class DataPositions { void process_line(long long items_used, const char* name, ifstream& file, bool print_verbose, double& total_cost, bool& reading_field, string suffix = "") const; public: static const char* dtype_names[]; static const char* field_names[N_DATA_FIELD_TYPE]; static const int tuple_size[N_DTYPE]; vector< vector > files; vector< vector > inputs; map extended[N_DATA_FIELD_TYPE]; map, long long> edabits; DataPositions(int num_players = 0) { set_num_players(num_players); } void reset() { *this = DataPositions(inputs.size()); } void set_num_players(int num_players); int num_players() { return inputs.size(); } void increase(const DataPositions& delta); DataPositions& operator-=(const DataPositions& delta); DataPositions operator-(const DataPositions& delta) const; void print_cost() const; }; template class Processor; template class Data_Files; template class Machine; template class SubProcessor; template class Preprocessing { DataPositions& usage; protected: void count(Dtype dtype) { usage.files[T::field_type()][dtype]++; } void count(DataTag tag, int n = 1) { usage.extended[T::field_type()][tag] += n; } void count_input(int player) { usage.inputs[player][T::field_type()]++; } void count_edabit(bool strict, int n_bits) { usage.edabits[{strict, n_bits}]++; } public: template static Preprocessing* get_new(Machine& machine, DataPositions& usage, SubProcessor* proc); static Preprocessing* get_live_prep(SubProcessor* proc, DataPositions& usage); Preprocessing(DataPositions& usage) : usage(usage) {} virtual ~Preprocessing() {} virtual void set_protocol(typename T::Protocol& protocol) = 0; virtual void set_proc(SubProcessor* proc) { (void) proc; } virtual void seekg(DataPositions& pos) { (void) pos; } virtual void prune() {} virtual void purge() {} virtual size_t data_sent() { return 0; } virtual NamedCommStats comm_stats() { return {}; } virtual void get_three_no_count(Dtype dtype, T& a, T& b, T& c) = 0; virtual void get_two_no_count(Dtype dtype, T& a, T& b) = 0; virtual void get_one_no_count(Dtype dtype, T& a) = 0; virtual void get_input_no_count(T& a, typename T::open_type& x, int i) = 0; virtual void get_no_count(vector& S, DataTag tag, const vector& regs, int vector_size) = 0; void get(Dtype dtype, T* a); void get_three(Dtype dtype, T& a, T& b, T& c); void get_two(Dtype dtype, T& a, T& b); void get_one(Dtype dtype, T& a); void get_input(T& a, typename T::open_type& x, int i); void get(vector& S, DataTag tag, const vector& regs, int vector_size); virtual array get_triple(int n_bits); virtual T get_bit(); virtual void get_dabit(T&, typename T::bit_type&) { throw runtime_error("no daBit"); } virtual void get_edabits(bool, size_t, T*, vector&, const vector&) { throw runtime_error("no edaBit"); } virtual void push_triples(const vector>&) { throw runtime_error("no pushing"); } virtual void buffer_triples() {} virtual void buffer_inverses() {} virtual Preprocessing& get_part() { throw runtime_error("no part"); } }; template class Sub_Data_Files : public Preprocessing { template friend class Sub_Data_Files; static map tuple_lengths; static Lock tuple_lengths_lock; static int tuple_length(int dtype); BufferOwner buffers[N_DTYPE]; vector> input_buffers; BufferOwner, RefInputTuple> my_input_buffers; map > extended; int my_num,num_players; const string prep_data_dir; public: static string get_suffix(int thread_num); Sub_Data_Files(int my_num, int num_players, const string& prep_data_dir, DataPositions& usage, int thread_num = -1); Sub_Data_Files(const Names& N, const string& prep_data_dir, DataPositions& usage, int thread_num = -1) : Sub_Data_Files(N.my_num(), N.num_players(), prep_data_dir, usage, thread_num) { } ~Sub_Data_Files(); void set_protocol(typename T::Protocol& protocol) { (void) protocol; } void seekg(DataPositions& pos); void prune(); void purge(); bool eof(Dtype dtype); bool input_eof(int player); void get_no_count(Dtype dtype, T* a); void get_three_no_count(Dtype dtype, T& a, T& b, T& c) { buffers[dtype].input(a); buffers[dtype].input(b); buffers[dtype].input(c); } void get_two_no_count(Dtype dtype, T& a, T& b) { buffers[dtype].input(a); buffers[dtype].input(b); } void get_one_no_count(Dtype dtype, T& a) { buffers[dtype].input(a); } void get_input_no_count(T& a,typename T::open_type& x,int i) { RefInputTuple tuple(a, x); if (i==my_num) my_input_buffers.input(tuple); else input_buffers[i].input(a); } void setup_extended(const DataTag& tag, int tuple_size = 0); void get_no_count(vector& S, DataTag tag, const vector& regs, int vector_size); }; template class Data_Files { friend class Processor; DataPositions usage, skipped; public: Preprocessing& DataFp; Preprocessing& DataF2; Data_Files(Machine& machine, SubProcessor* procp = 0, SubProcessor* proc2 = 0); ~Data_Files(); DataPositions tellg(); void seekg(DataPositions& pos); void skip(const DataPositions& pos); void prune(); void purge(); DataPositions get_usage() { return usage - skipped; } void reset_usage() { usage.reset(); skipped.reset(); } size_t data_sent() { return DataFp.data_sent() + DataF2.data_sent(); } }; template inline bool Sub_Data_Files::eof(Dtype dtype) { return buffers[dtype].eof; } template inline bool Sub_Data_Files::input_eof(int player) { if (player == my_num) return my_input_buffers.eof; else return input_buffers[player].eof; } template inline void Sub_Data_Files::get_no_count(Dtype dtype, T* a) { for (int i = 0; i < DataPositions::tuple_size[dtype]; i++) buffers[dtype].input(a[i]); } template inline void Preprocessing::get(Dtype dtype, T* a) { switch (dtype) { case DATA_TRIPLE: get_three(dtype, a[0], a[1], a[2]); break; case DATA_SQUARE: case DATA_INVERSE: get_two(dtype, a[0], a[1]); break; case DATA_BIT: get_one(dtype, a[0]); break; default: throw runtime_error("unsupported data type: " + to_string(dtype)); } } template inline void Preprocessing::get_three(Dtype dtype, T& a, T& b, T& c) { count(dtype); get_three_no_count(dtype, a, b, c); } template inline void Preprocessing::get_two(Dtype dtype, T& a, T& b) { count(dtype); get_two_no_count(dtype, a, b); } template inline void Preprocessing::get_one(Dtype dtype, T& a) { count(dtype); get_one_no_count(dtype, a); } template inline void Preprocessing::get_input(T& a, typename T::open_type& x, int i) { count_input(i); get_input_no_count(a, x, i); } template inline void Preprocessing::get(vector& S, DataTag tag, const vector& regs, int vector_size) { count(tag, vector_size); get_no_count(S, tag, regs, vector_size); } template array Preprocessing::get_triple(int n_bits) { (void) n_bits; array res; get(DATA_TRIPLE, res.data()); return res; } template T Preprocessing::get_bit() { T res; get_one(DATA_BIT, res); return res; } template inline void Data_Files::purge() { DataFp.purge(); DataF2.purge(); } #endif