24 #include "../common.hpp"
28 using namespace swarm::log;
30 namespace swarm {
namespace query {
38 const char* UNSORTED_HEADER_FULL =
"unsorted_output // Unsorted output file";
39 const char* UNSORTED_HEADER_CHECK =
"unsorted_output";
40 const char* SORTED_HEADER_FULL =
"T_sorted_output // Output file sorted by time";
41 const char* SORTED_HEADER_CHECK =
"T_sorted_output";
42 const char* T_INDEX_CHECK =
"T_sorted_index";
43 const char* SYS_INDEX_CHECK =
"sys_sorted_index";
46 void get_Tsys(gpulog::logrecord &lr,
double &T,
int &sys)
66 void gethdr(
double &T,
int &sys)
const
68 gpulog::logrecord lr(ptr);
72 bool operator< (
const idx_t &a)
const
76 this->gethdr(Tt, syst);
80 Tt == Ta && syst < sysa || (
81 syst == sysa && this->ptr < a.ptr
88 struct index_entry_time_cmp
94 struct index_entry_sys_cmp
96 bool operator()(
const swarmdb::index_entry &a,
const swarmdb::index_entry &b)
const {
return a.sys < b.sys || (a.sys == b.sys && a.T < b.T) || (a.T == b.T && a.offs < b.offs); }
100 struct index_entry_bod_cmp
102 bool operator()(
const swarmdb::index_entry &a,
const swarmdb::index_entry &b)
const {
return a.body < b.body || (a.sys == b.sys && a.body == b.body && a.T < b.T ) || (a.T == b.T && a.sys == b.sys && a.offs < b.offs); }
107 bool get_file_info(uint64_t ×tamp, uint64_t &filesize,
const std::string &fn)
110 if(stat(fn.c_str(), &sb) == -1)
112 ERROR(strerror(errno));
115 timestamp = sb.st_mtime;
117 timestamp = (uint64_t(sb.st_mtim.tv_sec) << 32) + uint64_t(sb.st_mtim.tv_nsec);
119 filesize = sb.st_size;
125 template<
typename Cmp>
129 std::string suffix, filetype;
131 std::string filename;
136 index_creator(
const std::string &suffix_,
const std::string &filetype_) : suffix(suffix_), filetype(filetype_), nentries(0) {}
139 virtual bool start(
const std::string &datafile)
141 filename = datafile + suffix;
142 out.open(filename.c_str());
146 uint64_t timestamp, filesize;
147 get_file_info(timestamp, filesize, datafile);
150 swarm::swarm_index_header fh(filetype, timestamp, filesize);
151 out.write((
char*)&fh,
sizeof(fh));
155 virtual bool add_entry(uint64_t offs, gpulog::logrecord lr)
159 get_Tsys(lr, ie.
T, ie.
sys);
160 out.write((
const char *)&ie,
sizeof(ie));
167 virtual bool finish()
172 mmapped_swarm_index_file mm(filename, filetype, MemoryMap::rw);
173 swarmdb::index_entry *begin = (swarmdb::index_entry *)mm.data(), *end = begin + mm.size()/
sizeof(swarmdb::index_entry);
174 assert((end - begin) == nentries);
176 std::sort(begin, end, Cmp());
179 for(
int i=1; i < nentries; i++)
181 bool ok = cmp(begin[i-1], begin[i]);
182 if(!ok) { ok = !cmp(begin[i], begin[i-1]); }
191 void swarmdb::index_binary_log_file(std::vector<boost::shared_ptr<index_creator_base> > &ic,
const std::string &datafile)
194 gpulog::ilogstream ils(mmdata.data(), mmdata.size());
195 gpulog::logrecord lr;
198 for(
int i=0; i != ic.size(); i++)
200 ic[i]->start(datafile);
204 while(lr = ils.next())
206 for(
int i=0; i != ic.size(); i++)
208 ic[i]->add_entry(lr.ptr - mmdata.data(), lr);
213 for(
int i=0; i != ic.size(); i++)
229 gpulog::ilogstream ils(mm.
data(), mm.
size());
230 std::vector<idx_t> idx;
231 gpulog::logrecord lr;
234 uint64_t datalen = 0;
235 for(
int i=0; lr = ils.next(); i++)
244 assert(datalen == mm.
size());
247 std::sort(idx.begin(), idx.end());
250 std::ofstream out(outfn.c_str());
251 swarm_header fh(SORTED_HEADER_FULL, 0, datalen);
252 out.write((
char*)&fh,
sizeof(fh));
255 for(
int i = 0; i != idx.size(); i++)
257 out.write(idx[i].ptr, idx[i].len);
259 size_t tp = out.tellp();
260 assert(tp ==
sizeof(fh) + datalen);
273 bool operator <(
const sysinfo &a)
const
283 int nbod = -1, sysmax = -1;
double Tsnapend;
284 gpulog::logrecord lr;
285 std::set<sysinfo> systems;
292 double T;
int nbod_tmp;
sysinfo si;
293 lr >> T >> si.sys >> si.flags >> nbod_tmp;
296 Tsnapend = T*(1+Trelerr) + Tabserr;
299 assert(nbod == nbod_tmp);
309 if(systems.count(si))
318 sysmax = std::max(si.sys, sysmax);
322 if(!systems.size()) {
return false; }
327 for(
int sys = 0; sys != ens.
nsys(); sys++)
329 ens.set_inactive(sys);
333 for(std::set<sysinfo>::iterator i = systems.begin(); i != systems.end(); i++)
336 assert(si.sys >= 0 && si.sys < ens.
nsys());
339 ens.flags(si.sys) = si.flags;
342 for(
int bod = 0; bod != nbod; bod++)
344 const body &b = si.bodies[bod];
345 ens.set_body(si.sys, bod, b.mass, b.x, b.y, b.z, b.vx, b.vy, b.vz);
346 ens.time(si.sys) = Tsnapend;
354 swarmdb::snapshots::snapshots(
const swarmdb &db_,
time_range_t T,
double Tabserr_,
double Trelerr_)
355 : db(db_), Tabserr(Tabserr_), Trelerr(Trelerr_), r(db.query(ALL, T))
361 : db(db_), sys(sys_), T(T_)
363 using namespace boost;
365 if(sys.first == sys.last || !T)
375 swarmdb::index_entry dummy;
376 dummy.
T = T.first; begin = std::lower_bound(db.idx_time.begin, db.idx_time.end, dummy, bind( &
index_entry::T, _1 ) < bind( &
index_entry::T, _2 ));
377 dummy.T = T.last; end = std::upper_bound(db.idx_time.begin, db.idx_time.end, dummy, bind( &
index_entry::T, _1 ) < bind( &
index_entry::T, _2 ));
382 begin = db.idx_time.begin;
383 end = db.idx_time.end;
392 swarmdb::result::result(
const swarmdb &db_,
const sys_range_t &sys_,
const body_range_t &body_,
const time_range_t &T_) : db(db_), sys(sys_), body(body_), T(T_)
394 using namespace boost;
396 if(sys.first == sys.last || !T)
399 swarmdb::index_entry dummy;
406 swarmdb::index_entry dummy;
407 dummy.T = T.first; begin = std::lower_bound(db.idx_time.begin, db.idx_time.end, dummy, bind( &
index_entry::T, _1 ) < bind( &
index_entry::T, _2 ));
408 dummy.T = T.last; end = std::upper_bound(db.idx_time.begin, db.idx_time.end, dummy, bind( &
index_entry::T, _1 ) < bind( &
index_entry::T, _2 ));
413 begin = db.idx_time.begin;
414 end = db.idx_time.end;
432 if(!T.in(at->T)) { at++;
continue; }
433 if(!sys.in(at->sys)) { at++;
continue; }
436 return gpulog::logrecord(db.mmdata.
data() + (at++)->offs);
439 static gpulog::header hend(-1, 0);
440 static gpulog::logrecord eof((
char *)&hend);
444 void swarmdb::result::unget()
458 if(access(datafile.c_str(), 04) != 0)
460 ERROR(
"Cannot open output file '" + datafile +
"'");
462 this->datafile = datafile;
465 mmdata.open(datafile, SORTED_HEADER_CHECK);
474 std::vector<boost::shared_ptr<index_creator_base> > ic;
478 bool tidx_open = !force_recreate &&
open_index(idx_time, datafile,
".time.idx",
"T_sorted_index");
484 bool sysidx_open = !force_recreate &&
open_index(idx_sys, datafile,
".sys.idx",
"sys_sorted_index");
494 index_binary_log_file(ic, datafile);
498 if(!tidx_open && !
open_index(idx_time, datafile,
".time.idx", T_INDEX_CHECK ))
500 ERROR(
"Cannot open index file '" + datafile +
".time.idx'");
502 if(!sysidx_open && !
open_index(idx_sys, datafile,
".sys.idx", SYS_INDEX_CHECK))
504 ERROR(
"Cannot open index file '" + datafile +
".sys.idx'");
509 bool swarmdb::open_index(index_handle &h,
const std::string &datafile,
const std::string &suffix,
const std::string &filetype)
511 std::string filename = datafile + suffix;
514 if(access(filename.c_str(), 04) != 0) {
return false; }
519 h.mm.open(filename.c_str(), filetype);
520 uint64_t timestamp, filesize;
521 get_file_info(timestamp, filesize, datafile);
524 timestamp = h.mm.hdr().timestamp;
526 if(h.mm.hdr().datafile_size != filesize || h.mm.hdr().timestamp != timestamp)
528 std::cerr <<
"Index " << filename <<
" not up to date. Will regenerate.\n";