1 #ifndef __SWAPPY_ITEMS_HPP__
2 #define __SWAPPY_ITEMS_HPP__ 1
14 #include <unordered_set>
15 #include <unordered_map>
20 #define __STDC_FORMAT_MACROS
23 #include <experimental/filesystem>
24 namespace filesys = std::experimental::filesystem;
46 class TKEY,
class TVALUE,
47 int EACHFILE = 16384,
int OLDIES = 5,
int RAMSIZE = 3,
int BLOOMBITS = 4,
int MASKLENGTH = (2* 4*16384)
52 typedef std::pair<TVALUE, std::vector<TKEY> >
Data;
62 uint64_t bloomSaysNotIn = 0;
63 uint64_t bloomFails = 0;
65 uint64_t rangeSaysNo = 0;
66 uint64_t rangeFails = 0;
69 uint64_t fileLoads = 0;
94 typedef std::unordered_map<TKEY,Data>
Ram;
96 typedef std::deque<Qentry>
Order;
110 const char _prefix[7] =
"./temp";
111 char _swappypath[256];
123 bool set (TKEY key, TVALUE value) {
127 auto it = std::find_if(std::execution::par, _mru.rbegin(), _mru.rend(),
128 [key] (
const Qentry & qe) {
129 return (qe.key == key) && (qe.deleted == false);
133 _mru.push_back(
Qentry{key,
false});
134 _ramList[key] = std::make_pair(value, _ramList[key].second);
141 _mru.push_back(
Qentry{key,
false});
142 _ramList[key] = std::make_pair(value, std::vector<TKEY>(0));
144 if (key > _ramMaximum) _ramMaximum = key;
145 if (key < _ramMinimum) _ramMinimum = key;
155 bool set (TKEY key, TVALUE value, std::vector<TKEY> refs) {
159 auto it = std::find_if(std::execution::par, _mru.rbegin(), _mru.rend(),
160 [key] (
const Qentry & qe) {
161 return (qe.key == key) && (qe.deleted == false);
165 _mru.push_back(
Qentry{key,
false});
166 _ramList[key] = std::make_pair(value, refs);
173 _mru.push_back(
Qentry{key,
false});
174 _ramList[key] = std::make_pair(value, refs);
176 if (key > _ramMaximum) _ramMaximum = key;
177 if (key < _ramMinimum) _ramMinimum = key;
191 auto it = std::find_if(std::execution::par, _mru.rbegin(), _mru.rend(),
192 [key] (
const Qentry & qe) {
193 return (qe.key == key) && (qe.deleted == false);
198 _mru.push_back(
Qentry{key,
false});
199 return &(_ramList[key]);
211 bool del (
const TKEY & key) {
214 auto it = std::find_if(std::execution::par, _mru.rbegin(), _mru.rend(),
215 [key] (
const Qentry & qe) {
216 return (qe.key == key) && (qe.deleted == false);
226 if (key == _ramMaximum || key == _ramMinimum) ramMinMax();
257 TKEY val = std::numeric_limits<TKEY>::max();
259 std::for_each (_buckets.begin(), _buckets.end(), [&](
Detail finfo) {
260 if ( finfo.minimum != finfo.maximum ) {
261 if (finfo.minimum < val) val = finfo.minimum;
265 if (_ramMinimum < val) val = _ramMinimum;
273 TKEY val = std::numeric_limits<TKEY>::min();
275 std::for_each (_buckets.begin(), _buckets.end(), [&](
Detail finfo) {
276 if ( finfo.minimum != finfo.maximum ) {
277 if (finfo.maximum > val) val = finfo.maximum;
281 if (_ramMaximum > val) val = _ramMaximum;
288 struct statistic_s getStatistic (void) {
289 statistic.fileKB = (_buckets.size() * EACHFILE * (
sizeof(TKEY) +
sizeof(TVALUE))/1000);
290 statistic.queue = _mru.size();
291 statistic.maxKey = this->max();
292 statistic.minKey = this->min();
305 statistic.fileKB = 0;
308 statistic.updates = 0;
309 statistic.deletes = 0;
311 statistic.bloomSaysNotIn = 0;
312 statistic.rangeSaysNo = 0;
313 statistic.rangeFails = 0;
316 statistic.fileLoads = 0;
318 _ramMinimum = std::numeric_limits<TKEY>::max();
319 _ramMaximum = std::numeric_limits<TKEY>::min();
321 statistic.minKey = _ramMinimum;
322 statistic.maxKey = _ramMaximum;
332 EACHFILE, OLDIES, RAMSIZE, BLOOMBITS, MASKLENGTH
335 if (filesys::exists(_swappypath)) {
337 if (
false == wakeup()) {
338 fprintf(stderr,
"folder '%s' still exists without hibernate data! Please delete or rename it!\n", _swappypath);
342 "# wakeup on items, updates, deletes: "
343 "%10ld %10" PRId64
" %10" PRId64
"\n",
350 filesys::create_directory(_swappypath);
375 snprintf(filename, 512,
"%s/hibernate.ramlist", _swappypath);
376 file.open(filename, std::ios::in | std::ios::binary);
379 file.read((
char *) &length,
sizeof(
Id));
380 for (
Id c = 0;
c < length; ++
c) {
381 std::vector<TKEY> vecdata(0);
382 file.read((
char *) &loadedKey,
sizeof(TKEY));
383 file.read((
char *) &loadedValue,
sizeof(TVALUE));
385 file.read((
char *) &lengthVec,
sizeof(
Id));
386 for (
Id j=0; j<lengthVec; ++j) {
387 file.read((
char *) &loadedKey2,
sizeof(TKEY));
388 vecdata.push_back(loadedKey2);
390 _ramList[loadedKey] = std::make_pair(loadedValue, vecdata);
394 snprintf(filename, 512,
"%s/hibernate.statistic", _swappypath);
395 file.open(filename, std::ios::in | std::ios::binary);
396 file.read((
char *) &statistic,
sizeof(
statistic_s));
397 file.read((
char *) &_ramMinimum,
sizeof(TKEY));
398 file.read((
char *) &_ramMaximum,
sizeof(TKEY));
401 snprintf(filename, 512,
"%s/hibernate.mru", _swappypath);
402 file.open(filename, std::ios::in | std::ios::binary);
403 file.read((
char *) &length,
sizeof(
Id));
405 for (
Id c = 0;
c < length; ++
c) {
406 file.read((
char *) &(qe.
key),
sizeof(TKEY));
407 file.read((
char *) &(qe.
deleted),
sizeof(Qentry::deleted));
412 snprintf(filename, 512,
"%s/hibernate.buckets", _swappypath);
413 file.open(filename, std::ios::in | std::ios::binary);
414 file.read((
char *) &length,
sizeof(
Id));
417 for (
Fid c = 0;
c < length; ++
c) {
418 file.read((
char *) &(detail.
minimum),
sizeof(TKEY));
419 file.read((
char *) &(detail.
maximum),
sizeof(TKEY));
421 detail.
bloomMask = std::vector<bool>(MASKLENGTH,
true);
423 for (
Bid b=0; b < MASKLENGTH; ++b) {
425 if (cbit ==
'o') detail.
bloomMask[b] =
false;
427 file.read((
char *) &(detail.
fid),
sizeof(
Fid));
429 _buckets.push_back(detail);
444 snprintf(filename, 512,
"%s/hibernate.ramlist", _swappypath);
445 std::ofstream file(filename, std::ios::out | std::ios::binary);
446 Id length = _ramList.size();
447 file.write((
char *) &length,
sizeof(
Id));
448 for (
auto it = _ramList.begin(); it != _ramList.end(); ++it) {
449 file.write((
char *) &(it->first),
sizeof(TKEY));
450 file.write((
char *) &(it->second.first),
sizeof(TVALUE));
452 length = it->second.second.size();
453 file.write((
char *) &length,
sizeof(
Id));
454 for (
Id j=0; j<length; ++j) {
455 file.write((
char *) &(it->second.second[j]),
sizeof(TKEY));
460 snprintf(filename, 512,
"%s/hibernate.statistic", _swappypath);
461 file.open(filename, std::ios::out | std::ios::binary);
462 file.write((
char *) &statistic,
sizeof(
statistic_s));
463 file.write((
char *) &_ramMinimum,
sizeof(TKEY));
464 file.write((
char *) &_ramMaximum,
sizeof(TKEY));
467 snprintf(filename, 512,
"%s/hibernate.mru", _swappypath);
468 file.open(filename, std::ios::out | std::ios::binary);
469 length = _mru.size();
470 file.write((
char *) &length,
sizeof(
Id));
471 for (
auto it = _mru.begin(); it != _mru.end(); ++it) {
472 file.write((
char *) &(it->key),
sizeof(TKEY));
473 file.write((
char *) &(it->deleted),
sizeof(Qentry::deleted));
477 snprintf(filename, 512,
"%s/hibernate.buckets", _swappypath);
478 file.open(filename, std::ios::out | std::ios::binary);
479 length = _buckets.size();
480 file.write((
char *) &length,
sizeof(
Id));
481 for (
auto it = _buckets.begin(); it != _buckets.end(); ++it) {
482 file.write((
char *) &(it->minimum),
sizeof(TKEY));
483 file.write((
char *) &(it->maximum),
sizeof(TKEY));
484 for (
bool b : it->bloomMask) {
491 file.write((
char *) &(it->fid),
sizeof(
Fid));
499 for(
int i=0; i < BLOOMBITS; ++i) {
500 fp.insert( rand()%(MASKLENGTH) );
514 }
catch (
const std::out_of_range & oor) {
515 return loadFromFiles(key);
525 std::vector<Fid> candidates;
528 fsearchSuccess =
false;
530 std::for_each (std::execution::par, _buckets.begin(), _buckets.end(), [&](
Detail finfo) {
531 if ( finfo.minimum != finfo.maximum ) {
533 if ( (key < finfo.minimum) || (key > finfo.maximum) ) {
536 ++statistic.rangeSaysNo;
542 if (finfo.bloomMask[b] == false) {
545 ++statistic.bloomSaysNotIn;
552 candidates.push_back(finfo.fid);
560 if (candidates.size() > 0) {
562 std::vector<std::thread *> workers;
563 for (
unsigned i = 0; i < candidates.size(); ++i) {
567 for (
auto w : workers)
if (w->joinable()) w->join();
569 for (
auto w : workers)
delete w;
572 if (fsearchSuccess)
return true;
574 if (!fsearchSuccess && candidates.size() > 0) {
576 ++statistic.rangeFails;
601 snprintf(filename, 512,
"%s/%" PRId32
".bucket", _swappypath, fid);
602 std::ifstream file(filename, std::ios::in | std::ios::binary);
604 for (
Id c = 0;
c < EACHFILE; ++
c) {
605 std::vector<TKEY> vecdata(0);
606 file.read((
char *) &loadedKey,
sizeof(TKEY));
607 file.read((
char *) &loadedValue,
sizeof(TVALUE));
609 file.read((
char *) &length,
sizeof(
Id));
610 for (
Id j=0; j<length; ++j) {
611 file.read((
char *) &loadedKey2,
sizeof(TKEY));
612 vecdata.push_back(loadedKey2);
614 temp[loadedKey] = std::make_pair(loadedValue, vecdata);
616 if (loadedKey == key) {
618 mu_FsearchSuccess.lock();
619 fsearchSuccess =
true;
620 ++statistic.fileLoads;
621 mu_FsearchSuccess.unlock();
623 if ((result ==
false) && fsearchSuccess) {
632 TKEY omin = _buckets[fid].minimum;
633 TKEY omax = _buckets[fid].maximum;
637 _buckets[fid].minimum = 0;
638 _buckets[fid].maximum = 0;
644 for (
auto key_val : temp) {
645 _ramList[key_val.first] = key_val.second;
646 _mru.push_back(
Qentry{key_val.first,
false});
649 if (omax > _ramMaximum) _ramMaximum = omax;
650 if (omin < _ramMinimum) _ramMinimum = omin;
663 Id needed = reload? EACHFILE : 0;
667 if ( (_ramList.size() + needed) < (RAMSIZE * EACHFILE * OLDIES) ) {
669 if ( _mru.size() > ( (RAMSIZE+2) * EACHFILE*OLDIES) ) {
672 for (
auto it = _mru.begin(); it != _mru.end(); ++it) {
673 if (it->deleted ==
false) newMRU.push_back(*it);
683 std::map<TKEY,Data> temp;
689 for (
pos = 0;
pos < (EACHFILE*OLDIES); ) {
693 temp[qe.
key] = _ramList[qe.
key];
694 _ramList.erase(qe.
key);
702 typename std::map<TKEY,Data>::iterator it;
704 for (it=temp.begin(); it!=temp.end(); ++it) {
707 if ((written%(EACHFILE)) == 0) {
711 for (
Fid fid = 0; fid < _buckets.size(); ++fid) {
712 if (_buckets[fid].minimum == _buckets[fid].maximum) {
719 if (success ==
false) {
720 pos = _buckets.size();
722 _buckets.push_back(detail);
726 snprintf(filename, 512,
"%s/%" PRId32
".bucket", _swappypath,
pos);
727 file.open(filename, std::ios::out | std::ios::binary);
728 detail.minimum = it->first;
729 detail.bloomMask = std::vector<bool>(MASKLENGTH,
false);
733 file.write((
char *) &(it->first),
sizeof(TKEY));
734 file.write((
char *) &(it->second.first),
sizeof(TVALUE));
737 Id length = it->second.second.size();
738 file.write((
char *) &length,
sizeof(
Id));
739 for (
Id j=0; j<length; ++j) {
740 file.write((
char *) &(it->second.second[j]),
sizeof(TKEY));
744 fp = getFingerprint(it->first);
746 detail.bloomMask[b] =
true;
752 if ((written%(EACHFILE)) == 0) {
755 detail.maximum = it->first;
756 _buckets[
pos] = detail;
767 auto result = std::minmax_element(std::execution::par, _ramList.begin(), _ramList.end(), [](
auto lhs,
auto rhs) {
768 return (lhs.first < rhs.first);
772 _ramMinimum = result.first->first;
774 _ramMaximum = result.second->first;
791 typename Ram::iterator it;
792 std::set<Fid> important;
796 for (it = _ramList.begin(); it != _ramList.end(); ++it) {
797 if (foo(it->first, it->second)) {
803 std::for_each (_buckets.begin(), _buckets.end(), [&](
Detail finfo) {
804 if ( finfo.minimum != finfo.maximum ) {
805 important.insert(finfo.fid);
809 for (Fid fid : important) {
812 std::unordered_set<TKEY> keys;
819 snprintf(filename, 512,
"%s/%" PRId32
".bucket", _swappypath, fid);
820 std::ifstream file(filename, std::ios::in | std::ios::binary);
822 for (Id
c = 0;
c < EACHFILE; ++
c) {
823 std::vector<TKEY> vecdata(0);
824 file.read((
char *) &loadedKey,
sizeof(TKEY));
825 file.read((
char *) &loadedValue,
sizeof(TVALUE));
826 keys.insert(loadedKey);
828 file.read((
char *) &length,
sizeof(Id));
830 for (Id j=0; j<length; ++j) {
831 file.read((
char *) &loadedKey2,
sizeof(TKEY));
832 vecdata.push_back(loadedKey2);
835 temp[loadedKey] = std::make_pair(loadedValue, vecdata);
839 TKEY omin = _buckets[fid].minimum;
840 TKEY omax = _buckets[fid].maximum;
842 _buckets[fid].minimum = 0;
843 _buckets[fid].maximum = 0;
847 for (
auto key_val : temp) {
848 _ramList[key_val.first] = key_val.second;
849 _mru.push_back(Qentry{key_val.first,
false});
852 if (omax > _ramMaximum) _ramMaximum = omax;
853 if (omin < _ramMinimum) _ramMinimum = omin;
856 for (
auto k : keys) {
857 if (foo(k, _ramList[k])) {
879 bool apply (
Data & back,
const TKEY & key, std::function<
void(
Data *)> foo) {
882 back = _ramList.at(key);
884 _ramList[key] = back;
887 }
catch (
const std::out_of_range & oor) {
889 std::set<Fid> candidates;
893 std::for_each (std::execution::par, _buckets.begin(), _buckets.end(), [&](
Detail finfo) {
894 if ( finfo.minimum != finfo.maximum ) {
896 if ( (key < finfo.minimum) || (key > finfo.maximum) ) {
899 ++statistic.rangeSaysNo;
905 if (finfo.bloomMask[b] == false) {
908 ++statistic.bloomSaysNotIn;
915 candidates.insert(finfo.fid);
922 bool success =
false;
924 std::streampos startpos;
925 std::map<TKEY,Data> temp;
928 for (
auto fid : candidates) {
935 snprintf(filename, 512,
"%s/%" PRId32
".bucket", _swappypath, fid);
936 std::ifstream file(filename, std::ios::in | std::ios::binary);
938 for (
Id c = 0;
c < EACHFILE; ++
c) {
939 if(!success) startpos = file.tellg();
940 file.read((
char *) &loadedKey,
sizeof(TKEY));
942 if (loadedKey == key) {
946 std::vector<TKEY> vecdata(0);
947 file.read((
char *) &loadedValue,
sizeof(TVALUE));
949 file.read((
char *) &length,
sizeof(
Id));
950 for (
Id j=0; j<length; ++j) {
951 file.read((
char *) &loadedKey2,
sizeof(TKEY));
952 vecdata.push_back(loadedKey2);
955 back = std::make_pair(loadedValue, vecdata);
959 std::vector<TKEY> vecdata(0);
960 file.read((
char *) &loadedValue,
sizeof(TVALUE));
962 file.read((
char *) &length,
sizeof(
Id));
963 for (
Id j=0; j<length; ++j) {
964 file.read((
char *) &loadedKey2,
sizeof(TKEY));
965 vecdata.push_back(loadedKey2);
968 temp[loadedKey] = std::make_pair(loadedValue, vecdata);
972 file.read((
char *) &loadedValue,
sizeof(TVALUE));
974 file.read((
char *) &length,
sizeof(
Id));
975 for (
Id j=0; j<length; ++j) file.read((
char *) &loadedKey2,
sizeof(TKEY));
990 snprintf(filename, 512,
"%s/%" PRId32
".bucket", _swappypath, successFid);
992 std::fstream file(filename, std::ios::in | std::ios::out | std::ios::binary);
995 file.seekg(startpos);
998 typename std::map<TKEY,Data>::iterator it;
1000 for (it=temp.begin(); it!=temp.end(); ++it) {
1002 file.write((
char *) &(it->first),
sizeof(TKEY));
1003 file.write((
char *) &(it->second.first),
sizeof(TVALUE));
1006 Id le = it->second.second.size();
1007 file.write((
char *) &le,
sizeof(
Id));
1008 for (
Id j=0; j<le; ++j) {
1009 file.write((
char *) &(it->second.second[j]),
sizeof(TKEY));
1014 ++statistic.fileLoads;
1017 if (candidates.size() > 0) {
1019 ++statistic.rangeFails;
Definition: SwappyItems.hpp:49
void maySwap(bool reload=false)
Definition: SwappyItems.hpp:662
bool wakeup(void)
Definition: SwappyItems.hpp:368
std::mutex mu_FsearchSuccess
Definition: SwappyItems.hpp:113
bool fsearchSuccess
Definition: SwappyItems.hpp:114
void loadFromFile(Fid fid, TKEY key)
Definition: SwappyItems.hpp:591
TKEY _ramMinimum
Definition: SwappyItems.hpp:100
TKEY _ramMaximum
Definition: SwappyItems.hpp:101
uint32_t Bid
Definition: SwappyItems.hpp:91
Order _mru
Definition: SwappyItems.hpp:104
SwappyItems(int swappyId)
Definition: SwappyItems.hpp:302
Ram _ramList
Definition: SwappyItems.hpp:99
void ramMinMax(void)
Definition: SwappyItems.hpp:766
std::set< Bid > Fingerprint
Definition: SwappyItems.hpp:92
std::vector< Detail > Buckets
Definition: SwappyItems.hpp:95
std::deque< Qentry > Order
Definition: SwappyItems.hpp:96
std::unordered_map< TKEY, Data > Ram
Definition: SwappyItems.hpp:94
std::pair< TVALUE, std::vector< TKEY > > Data
Definition: SwappyItems.hpp:52
uint32_t Fid
Definition: SwappyItems.hpp:77
bool apply(Data &back, const TKEY &key, std::function< void(Data *)> foo)
Definition: SwappyItems.hpp:879
Fingerprint getFingerprint(const TKEY &key)
Definition: SwappyItems.hpp:496
void hibernate(void)
Definition: SwappyItems.hpp:441
Buckets _buckets
Definition: SwappyItems.hpp:107
bool set(TKEY key, TVALUE value, std::vector< TKEY > refs)
Definition: SwappyItems.hpp:155
TKEY min(void)
Definition: SwappyItems.hpp:256
Data * get(const TKEY &key)
Definition: SwappyItems.hpp:188
bool loadFromFiles(const TKEY &key)
Definition: SwappyItems.hpp:524
bool each(Data &back, std::function< bool(TKEY, Data &)> foo)
Definition: SwappyItems.hpp:790
bool load(const TKEY &key)
Definition: SwappyItems.hpp:510
bool del(const TKEY &key)
Definition: SwappyItems.hpp:211
~SwappyItems(void)
Definition: SwappyItems.hpp:357
bool set(TKEY key, TVALUE value)
Definition: SwappyItems.hpp:123
uint32_t Id
Definition: SwappyItems.hpp:76
Color c
Definition: osm2graph_bitmap.cpp:123
double pos
Definition: osm2graph_bitmap.cpp:125
Definition: SwappyItems.hpp:79
Fid fid
Definition: SwappyItems.hpp:83
std::vector< bool > bloomMask
Definition: SwappyItems.hpp:82
TKEY maximum
Definition: SwappyItems.hpp:81
TKEY minimum
Definition: SwappyItems.hpp:80
Definition: SwappyItems.hpp:86
bool deleted
Definition: SwappyItems.hpp:88
TKEY key
Definition: SwappyItems.hpp:87
Definition: SwappyItems.hpp:54
TKEY minKey
Definition: SwappyItems.hpp:72
TKEY maxKey
Definition: SwappyItems.hpp:71