Derecho  0.9
Distributed systems toolkit for RDMA
Persistent_impl.hpp
Go to the documentation of this file.
1 #ifndef PERSISTENT_IMPL_HPP
2 #define PERSISTENT_IMPL_HPP
3 
4 namespace persistent {
5 
6 template <typename int_type>
7 version_t combine_int32s(const int_type high_bits, const int_type low_bits) {
8  return static_cast<version_t>((static_cast<uint64_t>(high_bits) << 32) | (0xffffffffll & low_bits));
9 }
10 
11 template <typename int_type>
12 std::pair<int_type, int_type> unpack_version(const version_t packed_int) {
13  return std::make_pair(static_cast<int_type>(packed_int >> 32), static_cast<int_type>(0xffffffffll & packed_int));
14 }
15 
16 //===========================================
17 // PersistentRegistry
18 //===========================================
19 
20 template <int funcIdx, typename... Args>
21 void PersistentRegistry::callFunc(Args... args) {
22  for(auto itr = this->_registry.begin();
23  itr != this->_registry.end(); ++itr) {
24  std::get<funcIdx>(itr->second)(args...);
25  }
26 };
27 
28 template <int funcIdx, typename ReturnType, typename... Args>
29 ReturnType PersistentRegistry::callFuncMin(Args... args) {
30  ReturnType min_ret = -1; // -1 means invalid value.
31  for(auto itr = this->_registry.begin();
32  itr != this->_registry.end(); ++itr) {
33  ReturnType ret = std::get<funcIdx>(itr->second)(args...);
34  if(itr == this->_registry.begin()) {
35  min_ret = ret;
36  } else if(min_ret > ret) {
37  min_ret = ret;
38  }
39  }
40  return min_ret;
41 }
42 
43 //===========================================
44 // _NameMaker
45 //===========================================
46 template <typename ObjectType, StorageType storageType>
47 _NameMaker<ObjectType, storageType>::_NameMaker() noexcept(false) : m_sObjectTypeName(typeid(ObjectType).name()) {
48  this->m_iCounter = 0;
49  if(pthread_spin_init(&this->m_oLck, PTHREAD_PROCESS_SHARED) != 0) {
50  throw PERSIST_EXP_SPIN_INIT(errno);
51  }
52 }
53 
54 template <typename ObjectType, StorageType storageType>
56  pthread_spin_destroy(&this->m_oLck);
57 }
58 
59 template <typename ObjectType, StorageType storageType>
60 std::unique_ptr<std::string> _NameMaker<ObjectType, storageType>::make(const char* prefix) noexcept(false) {
61  int cnt;
62  if(pthread_spin_lock(&this->m_oLck) != 0) {
63  throw PERSIST_EXP_SPIN_LOCK(errno);
64  }
65  cnt = this->m_iCounter++;
66  if(pthread_spin_unlock(&this->m_oLck) != 0) {
67  throw PERSIST_EXP_SPIN_UNLOCK(errno);
68  }
69  std::unique_ptr<std::string> ret = std::make_unique<std::string>();
70  //char * buf = (char *)malloc((strlen(this->m_sObjectTypeName)+13)/8*8);
71  char buf[256];
72  sprintf(buf, "%s-%d-%s-%d", (prefix) ? prefix : "none", storageType, this->m_sObjectTypeName, cnt);
73  // return std::make_shared<const char *>((const char*)buf);
74  *ret = buf;
75  return ret;
76 }
77 
78 //===========================================
79 // Persistent
80 //===========================================
81 template <typename ObjectType,
82  StorageType storageType>
83 inline void Persistent<ObjectType, storageType>::initialize_log(const char* object_name) noexcept(false) {
84  // STEP 1: initialize log
85  this->m_pLog = nullptr;
86  switch(storageType) {
87  // file system
88  case ST_FILE:
89  this->m_pLog = std::make_unique<FilePersistLog>(object_name);
90  if(this->m_pLog == nullptr) {
92  }
93  break;
94  // volatile
95  case ST_MEM: {
96  // const std::string tmpfsPath = "/dev/shm/volatile_t";
97  this->m_pLog = std::make_unique<FilePersistLog>(object_name, getPersRamdiskPath());
98  if(this->m_pLog == nullptr) {
100  }
101  break;
102  }
103  //default
104  default:
105  throw PERSIST_EXP_STORAGE_TYPE_UNKNOWN(storageType);
106  }
107 }
108 
109 template <typename ObjectType,
110  StorageType storageType>
111 inline void Persistent<ObjectType, storageType>::initialize_object_from_log(const std::function<std::unique_ptr<ObjectType>(void)>& object_factory,
113  if(this->getNumOfVersions() > 0) {
114  // load the object from log.
115  this->m_pWrappedObject = this->getByIndex(this->getLatestIndex(), dm);
116  } else { // create a new one;
117  this->m_pWrappedObject = object_factory();
118  }
119 }
120 
121 template <typename ObjectType,
122  StorageType storageType>
124  if(this->m_pRegistry != nullptr) {
125  this->m_pRegistry->registerPersist(
126  this->m_pLog->m_sName.c_str(),
127  std::bind(&Persistent<ObjectType, storageType>::version, this, std::placeholders::_1),
129  std::bind(&Persistent<ObjectType, storageType>::trim<const int64_t>, this, std::placeholders::_1), //trim by version:(const int64_t)
130  std::bind(&Persistent<ObjectType, storageType>::getLatestVersion, this), //get the latest persisted versions
131  std::bind(&Persistent<ObjectType, storageType>::truncate, this, std::placeholders::_1) // truncate persistent versions.
132  );
133  }
134 }
135 
136 template <typename ObjectType,
137  StorageType storageType>
139  if(this->m_pRegistry != nullptr && this->m_pLog != nullptr) {
140  this->m_pRegistry->unregisterPersist(this->m_pLog->m_sName.c_str());
141  }
142 }
143 
144 template <typename ObjectType,
145  StorageType storageType>
147  const std::function<std::unique_ptr<ObjectType>(void)>& object_factory,
148  const char* object_name,
149  PersistentRegistry* persistent_registry,
150  mutils::DeserializationManager dm) noexcept(false)
151  : m_pRegistry(persistent_registry) {
152  // Initialize log
153  initialize_log((object_name == nullptr) ? (*Persistent::getNameMaker().make(persistent_registry ? persistent_registry->get_subgroup_prefix() : nullptr)).c_str() : object_name);
154  // Initialize object
155  initialize_object_from_log(object_factory, &dm);
156  // Register Callbacks
157  register_callbacks();
158 }
159 
160 template <typename ObjectType,
161  StorageType storageType>
163  this->m_pWrappedObject = std::move(other.m_pWrappedObject);
164  this->m_pLog = std::move(other.m_pLog);
165  this->m_pRegistry = other.m_pRegistry;
166  register_callbacks(); // this callback will override the previous registry entry.
167 }
168 
169 template <typename ObjectType,
170  StorageType storageType>
172  const char* object_name,
173  std::unique_ptr<ObjectType>& wrapped_obj_ptr,
174  const char* log_tail,
175  PersistentRegistry* persistent_registry,
176  mutils::DeserializationManager) noexcept(false)
177  : m_pRegistry(persistent_registry) {
178  // Initialize log
179  initialize_log(object_name);
180  // patch it
181  if(log_tail != nullptr) {
182  this->m_pLog->applyLogTail(log_tail);
183  }
184  // Initialize Wrapped Object
185  assert(wrapped_obj_ptr != nullptr);
186  this->m_pWrappedObject = std::move(wrapped_obj_ptr);
187  // Register callbacks
188  register_callbacks();
189 }
190 
191 template <typename ObjectType,
192  StorageType storageType>
194  // destroy the in-memory log:
195  // We don't need this anymore. m_pLog is managed by smart pointer
196  // automatically.
197  // if(this->m_pLog != NULL){
198  // delete this->m_pLog;
199  // }
200  // unregister the version creator and persist callback,
201  // if the Persistent<T> is added to the pool dynamically.
202  unregister_callbacks();
203 };
204 
205 template <typename ObjectType,
206  StorageType storageType>
208  return *this->m_pWrappedObject;
209 }
210 
211 template <typename ObjectType,
212  StorageType storageType>
214  return this->m_pWrappedObject.get();
215 }
216 
217 template <typename ObjectType,
218  StorageType storageType>
220  return *this->m_pWrappedObject;
221 }
222 
223 template <typename ObjectType,
224  StorageType storageType>
226  return this->m_pLog->m_sName;
227 }
228 
229 template <typename ObjectType,
230  StorageType storageType>
231 template <typename Func>
233  const Func& fun,
234  mutils::DeserializationManager* dm) noexcept(false) {
235  return this->getByIndex(-1L, fun, dm);
236 }
237 
238 template <typename ObjectType,
239  StorageType storageType>
240 std::unique_ptr<ObjectType> Persistent<ObjectType, storageType>::get(
241  mutils::DeserializationManager* dm) noexcept(false) {
242  return this->getByIndex(-1L, dm);
243 }
244 
245 template <typename ObjectType,
246  StorageType storageType>
247 template <typename Func>
249  int64_t idx,
250  const Func& fun,
251  mutils::DeserializationManager* dm) noexcept(false) {
252  if
253  constexpr(std::is_base_of<IDeltaSupport<ObjectType>, ObjectType>::value) {
254  return f(*this->getByIndex(idx, dm));
255  }
256  else {
257  return mutils::deserialize_and_run<ObjectType>(dm, (char*)this->m_pLog->getEntryByIndex(idx), fun);
258  }
259 };
260 
261 template <typename ObjectType,
262  StorageType storageType>
264  int64_t idx,
265  mutils::DeserializationManager* dm) noexcept(false) {
266  if
267  constexpr(std::is_base_of<IDeltaSupport<ObjectType>, ObjectType>::value) {
268  // ObjectType* ot = new ObjectType{};
269  std::unique_ptr<ObjectType> p = ObjectType::create(dm);
270  // TODO: accelerate this by checkpointing
271  for(int64_t i = this->m_pLog->getEarliestIndex(); i <= idx; i++) {
272  const char* entry_data = (const char*)this->m_pLog->getEntryByIndex(i);
273  p->applyDelta(entry_data);
274  }
275 
276  return p;
277  }
278  else {
279  return mutils::from_bytes<ObjectType>(dm, (char const*)this->m_pLog->getEntryByIndex(idx));
280  }
281 };
282 
283 template <typename ObjectType,
284  StorageType storageType>
285 template <typename Func>
287  const int64_t& ver,
288  const Func& fun,
289  mutils::DeserializationManager* dm) noexcept(false) {
290  char* pdat = (char*)this->m_pLog->getEntry(ver);
291  if(pdat == nullptr) {
293  }
294  if
295  constexpr(std::is_base_of<IDeltaSupport<ObjectType>, ObjectType>::value) {
296  // "So far, the IDeltaSupport does not work with zero-copy 'Persistent::get()'. Emulate with the copy version."
297  return f(*this->get(ver, dm));
298  }
299  else {
300  return mutils::deserialize_and_run<ObjectType>(dm, pdat, fun);
301  }
302 };
303 
304 template <typename ObjectType,
305  StorageType storageType>
306 std::unique_ptr<ObjectType> Persistent<ObjectType, storageType>::get(
307  const int64_t& ver,
308  mutils::DeserializationManager* dm) noexcept(false) {
309  int64_t idx = this->m_pLog->getVersionIndex(ver);
310  if(idx == INVALID_INDEX) {
312  }
313 
314  if
315  constexpr(std::is_base_of<IDeltaSupport<ObjectType>, ObjectType>::value) {
316  return getByIndex(idx, dm);
317  }
318  else {
319  return mutils::from_bytes<ObjectType>(dm, (const char*)this->m_pLog->getEntryByIndex(idx));
320  }
321 }
322 
323 template <typename ObjectType,
324  StorageType storageType>
325 template <typename TKey>
326 void Persistent<ObjectType, storageType>::trim(const TKey& k) noexcept(false) {
327  dbg_default_trace("trim.");
328  this->m_pLog->trim(k);
329  dbg_default_trace("trim...done");
330 }
331 
332 template <typename ObjectType,
333  StorageType storageType>
335  dbg_default_trace("truncate.");
336  this->m_pLog->truncate(ver);
337  dbg_default_trace("truncate...done");
338 }
339 
340 template <typename ObjectType,
341  StorageType storageType>
342 template <typename Func>
344  const HLC& hlc,
345  const Func& fun,
346  mutils::DeserializationManager* dm) noexcept(false) {
347  // global stability frontier test
348  if(m_pRegistry != nullptr && m_pRegistry->getFrontier() <= hlc) {
350  }
351 
352  if
353  constexpr(std::is_base_of<IDeltaSupport<ObjectType>, ObjectType>::value) {
354  int64_t idx = this->m_pLog->getHLCIndex(hlc);
355  if(idx == INVALID_INDEX) {
356  throw PERSIST_EXP_INV_HLC;
357  }
358  return getByIndex(idx, fun, dm);
359  }
360  else {
361  char* pdat = (char*)this->m_pLog->getEntry(hlc);
362  if(pdat == nullptr) {
363  throw PERSIST_EXP_INV_HLC;
364  }
365  return mutils::deserialize_and_run<ObjectType>(dm, pdat, fun);
366  }
367 };
368 
369 template <typename ObjectType,
370  StorageType storageType>
371 std::unique_ptr<ObjectType> Persistent<ObjectType, storageType>::get(
372  const HLC& hlc,
373  mutils::DeserializationManager* dm) noexcept(false) {
374  // global stability frontier test
375  if(m_pRegistry != nullptr && m_pRegistry->getFrontier() <= hlc) {
377  }
378  if
379  constexpr(std::is_base_of<IDeltaSupport<ObjectType>, ObjectType>::value) {
380  int64_t idx = this->m_pLog->getHLCIndex(hlc);
381  if(idx == INVALID_INDEX) {
382  throw PERSIST_EXP_INV_HLC;
383  }
384  return getByIndex(idx, dm);
385  }
386  else {
387  char const* pdat = (char const*)this->m_pLog->getEntry(hlc);
388  if(pdat == nullptr) {
389  throw PERSIST_EXP_INV_HLC;
390  }
391  return mutils::from_bytes<ObjectType>(dm, pdat);
392  }
393 }
394 
395 template <typename ObjectType,
396  StorageType storageType>
398  return this->m_pLog->getLength();
399 };
400 
401 template <typename ObjectType,
402  StorageType storageType>
404  return this->m_pLog->getEarliestIndex();
405 }
406 
407 template <typename ObjectType,
408  StorageType storageType>
410  return this->m_pLog->getEarliestVersion();
411 }
412 
413 template <typename ObjectType,
414  StorageType storageType>
416  return this->m_pLog->getLatestIndex();
417 }
418 
419 template <typename ObjectType,
420  StorageType storageType>
422  return this->m_pLog->getLatestVersion();
423 }
424 
425 template <typename ObjectType,
426  StorageType storageType>
428  return this->m_pLog->getLastPersisted();
429 }
430 
431 template <typename ObjectType,
432  StorageType storageType>
433 void Persistent<ObjectType, storageType>::set(ObjectType& v, const version_t& ver, const HLC& mhlc) noexcept(false) {
434  dbg_default_trace("append to log with ver({}),hlc({},{})", ver, mhlc.m_rtc_us, mhlc.m_logic);
435  if
436  constexpr(std::is_base_of<IDeltaSupport<ObjectType>, ObjectType>::value) {
437  v.finalizeCurrentDelta([&](char const* const buf, size_t len) {
438  this->m_pLog->append((const void* const)buf, len, ver, mhlc);
439  });
440  }
441  else {
442  // ObjectType does not support Delta, logging the whole current state.
443  auto size = mutils::bytes_size(v);
444  char* buf = new char[size];
445  bzero(buf, size);
446  mutils::to_bytes(v, buf);
447  this->m_pLog->append((void*)buf, size, ver, mhlc);
448  delete[] buf;
449  }
450 }
451 
452 template <typename ObjectType,
453  StorageType storageType>
454 void Persistent<ObjectType, storageType>::set(ObjectType& v, const version_t& ver) noexcept(false) {
455  HLC mhlc; // generate a default timestamp for it.
456 #if defined(_PERFORMANCE_DEBUG) || defined(DERECHO_DEBUG)
457  struct timespec t1, t2;
458  clock_gettime(CLOCK_REALTIME, &t1);
459 #endif
460  this->set(v, ver, mhlc);
461 
462 #if defined(_PERFORMANCE_DEBUG) || defined(DERECHO_DEBUG)
463  clock_gettime(CLOCK_REALTIME, &t2);
464  cnt_in_set++;
465  ns_in_set += ((t2.tv_sec - t1.tv_sec) * 1000000000ul + t2.tv_nsec - t1.tv_nsec);
466 #endif
467 }
468 
469 template <typename ObjectType,
470  StorageType storageType>
471 void Persistent<ObjectType, storageType>::version(const version_t& ver) noexcept(false) {
472  dbg_default_trace("In Persistent<T>: make version {}.", ver);
473  this->set(*this->m_pWrappedObject, ver);
474 }
475 
476 template <typename ObjectType,
477  StorageType storageType>
478 const int64_t Persistent<ObjectType, storageType>::persist() noexcept(false) {
479 #if defined(_PERFORMANCE_DEBUG) || defined(DERECHO_DEBUG)
480  struct timespec t1, t2;
481  clock_gettime(CLOCK_REALTIME, &t1);
482  const int64_t ret = this->m_pLog->persist();
483  clock_gettime(CLOCK_REALTIME, &t2);
484  cnt_in_persist++;
485  ns_in_persist += ((t2.tv_sec - t1.tv_sec) * 1000000000ul + t2.tv_nsec - t1.tv_nsec);
486  return ret;
487 #else
488  return this->m_pLog->persist();
489 #endif //_PERFORMANCE_DEBUG
490 }
491 
492 template <typename ObjectType,
493  StorageType storageType>
494 std::size_t Persistent<ObjectType, storageType>::to_bytes(char* ret) const {
495  std::size_t sz = 0;
496  // object name
497  dbg_default_trace("{0}[{1}] object_name starts at {2}", this->m_pLog->m_sName, __func__, sz);
498  sz += mutils::to_bytes(this->m_pLog->m_sName, ret + sz);
499  // wrapped object
500  dbg_default_trace("{0}[{1}] wrapped_object starts at {2}", this->m_pLog->m_sName, __func__, sz);
501  sz += mutils::to_bytes(*this->m_pWrappedObject, ret + sz);
502  // and the log
503  dbg_default_trace("{0}[{1}] log starts at {2}", this->m_pLog->m_sName, __func__, sz);
504  sz += this->m_pLog->to_bytes(ret + sz, PersistentRegistry::getEarliestVersionToSerialize());
505  return sz;
506 }
507 
508 template <typename ObjectType,
509  StorageType storageType>
511  return mutils::bytes_size(this->m_pLog->m_sName) + mutils::bytes_size(*this->m_pWrappedObject) + this->m_pLog->bytes_size(PersistentRegistry::getEarliestVersionToSerialize());
512 }
513 
514 template <typename ObjectType,
515  StorageType storageType>
516 void Persistent<ObjectType, storageType>::post_object(const std::function<void(char const* const, std::size_t)>& f)
517  const {
518  mutils::post_object(f, this->m_pLog->m_sName);
519  mutils::post_object(f, *this->m_pWrappedObject);
520  this->m_pLog->post_object(f, PersistentRegistry::getEarliestVersionToSerialize());
521 }
522 
523 template <typename ObjectType,
524  StorageType storageType>
525 std::unique_ptr<Persistent<ObjectType, storageType>> Persistent<ObjectType, storageType>::from_bytes(mutils::DeserializationManager* dsm, char const* v) {
526  size_t ofst = 0;
527  dbg_default_trace("{0} object_name is loaded at {1}", __func__, ofst);
528  auto obj_name = mutils::from_bytes<std::string>(dsm, v);
529  ofst += mutils::bytes_size(*obj_name);
530 
531  dbg_default_trace("{0} wrapped_obj is loaded at {1}", __func__, ofst);
532  auto wrapped_obj = mutils::from_bytes<ObjectType>(dsm, v + ofst);
533  ofst += mutils::bytes_size(*wrapped_obj);
534 
535  dbg_default_trace("{0} log is loaded at {1}", __func__, ofst);
536  PersistentRegistry* pr = nullptr;
537  if(dsm != nullptr) {
538  pr = &dsm->mgr<PersistentRegistry>();
539  }
540  dbg_default_trace("{0}[{1}] create object from serialized bytes.", obj_name->c_str(), __func__);
541  return std::make_unique<Persistent>(obj_name->data(), wrapped_obj, v + ofst, pr);
542 }
543 
544 template <typename ObjectType,
545  StorageType storageType>
547  this->m_pLog->applyLogTail(v);
548 }
549 
550 #if defined(_PERFORMANCE_DEBUG) || defined(DERECHO_DEBUG)
551 template <typename ObjectType,
552  StorageType storageType>
554  std::cout << "Performance Statistic of Persistent<"
555  << typeid(ObjectType).name() << ">,var_name="
556  << this->m_pLog->m_sName << ":" << std::endl;
557  std::cout << "\tpersist:\t" << ns_in_persist << " ns/"
558  << cnt_in_persist << " ops" << std::endl;
559  ;
560  std::cout << "\tset:\t" << ns_in_set << " ns/"
561  << cnt_in_set << " ops" << std::endl;
562  ;
563 }
564 #endif //_PERFORMANCE_DEBUG
565 
566 template <typename ObjectType, StorageType storageType>
568  static std::map<std::string, _NameMaker<ObjectType, storageType>> name_makers;
569  // make sure prefix does exist.
570  auto search = name_makers.find(prefix);
571  if(search == name_makers.end()) {
572  name_makers.emplace(std::make_pair(std::string(prefix), _NameMaker<ObjectType, storageType>()));
573  }
574 
575  return name_makers[prefix];
576 }
577 
578 template <typename ObjectType, StorageType storageType>
579 void saveObject(ObjectType& obj, const char* object_name) noexcept(false) {
580  switch(storageType) {
581  // file system
582  case ST_FILE: {
583  saveNoLogObjectInFile(obj, object_name);
584  break;
585  }
586  // volatile
587  case ST_MEM: {
588  saveNoLogObjectInMem(obj, object_name);
589  break;
590  }
591  default:
592  throw PERSIST_EXP_STORAGE_TYPE_UNKNOWN(storageType);
593  }
594 }
595 
596 template <typename ObjectType, StorageType storageType>
597 std::unique_ptr<ObjectType> loadObject(const char* object_name) noexcept(false) {
598  switch(storageType) {
599  // file system
600  case ST_FILE:
601  return loadNoLogObjectFromFile<ObjectType>(object_name);
602  // volatile
603  case ST_MEM:
604  return loadNoLogObjectFromMem<ObjectType>(object_name);
605  default:
606  throw PERSIST_EXP_STORAGE_TYPE_UNKNOWN(storageType);
607  }
608 }
609 
610 template <StorageType storageType>
611 const typename std::enable_if<(storageType == ST_FILE || storageType == ST_MEM), version_t>::type getMinimumLatestPersistedVersion(const std::type_index& subgroup_type, uint32_t subgroup_index, uint32_t shard_num) {
612  // All persistent log implementation MUST implement getMinimumLatestPersistedVersion()
613  // All of them need to be checked here
614  // NOTE: we assume that an application will only use ONE type of PERSISTED LOG (ST_FILE or ST_NVM, ...). Otherwise,
615  // if some persistentlog returns INVALID_VERSION, it is ambiguous for the following two case:
616  // 1) the subgroup/shard has some persistent<T> member storing data in corresponding persisted log but the log is empty.
617  // 2) the subgroup/shard has no persistent<T> member storing data in corresponding persisted log.
618  // In case we get a valid version from log stored in other storage type, we should return INVALID_VERSION for 1)
619  // but return the valid version for 2).
620  version_t mlpv = INVALID_VERSION;
621  mlpv = FilePersistLog::getMinimumLatestPersistedVersion(PersistentRegistry::generate_prefix(subgroup_type, subgroup_index, shard_num));
622  return mlpv;
623 }
624 }
625 #endif //PERSISTENT_IMPL_HPP
This file include all common types internal to derecho and not necessarily being known by a client pr...
#define PERSIST_EXP_SPIN_LOCK(x)
virtual int64_t getLatestIndex() noexcept(false)
get the latest index excluding truncated ones.
const ObjectType & getConstRef() const
get a const reference to the wrapped object
virtual int64_t getEarliestIndex() noexcept(false)
get the earliest index excluding trimmed ones.
virtual int64_t getEarliestVersion() noexcept(false)
get the earliest version excluding trimmed ones.
std::pair< int_type, int_type > unpack_version(const version_t packed_int)
Helper function for unpacking a Persistent version number into two signed or unsigned int32 values...
virtual void version(const version_t &ver) noexcept(false)
make a version with only a version number, using the current state.
virtual int64_t getNumOfVersions() noexcept(false)
get the number of versions excluding trimmed ones.
virtual int64_t getLatestVersion() noexcept(false)
get the lastest version excluding truncated ones.
#define PERSIST_EXP_NEW_FAILED_UNKNOWN
std::size_t to_bytes(char *ret) const
Write this class&#39;s marshalled representation into the array found at v.
void trim(const TKey &k) noexcept(false)
trim by version or index
void truncate(const int64_t &ver)
truncate the log
ReturnType callFuncMin(Args... args)
Helper function II.
auto bytes_size(const T &)
Just calls sizeof(T)
virtual ~_NameMaker() noexcept(true)
#define PERSIST_EXP_SPIN_INIT(x)
#define INVALID_INDEX
Definition: PersistLog.hpp:29
void saveNoLogObjectInMem(ObjectType &obj, const char *object_name) noexcept(false)
#define PERSIST_EXP_BEYOND_GSF
The manager for any RemoteDeserializationContexts.
const int64_t getMinimumLatestPersistedVersion() noexcept(false)
Returns the minimum of the latest persisted versions among all Persistent fields. ...
Definition: Persistent.cpp:38
std::unique_ptr< std::string > make(const char *prefix) noexcept(false)
std::size_t bytes_size() const
the size of the marshalled representation of this object.
ObjectType * operator->()
overload the &#39;->&#39; operator to access the wrapped object
void initialize_object_from_log(const std::function< std::unique_ptr< ObjectType >(void)> &object_factory, mutils::DeserializationManager *dm)
initialize the object from log
static int64_t getEarliestVersionToSerialize() noexcept(true)
Returns the earliest version for serialization.
Definition: Persistent.cpp:50
std::map< std::size_t, std::tuple< VersionFunc, PersistFunc, TrimFunc, LatestPersistedGetterFunc, TruncateFunc > > _registry
Callback registry.
Definition: Persistent.hpp:217
virtual ~Persistent() noexcept(true)
destructor: release the resources
#define INVALID_VERSION
Definition: PersistLog.hpp:28
#define PERSIST_EXP_STORAGE_TYPE_UNKNOWN(x)
virtual const int64_t persist() noexcept(false)
persist till version
#define PERSIST_EXP_INV_VERSION
static std::unique_ptr< Persistent > from_bytes(mutils::DeserializationManager *dsm, char const *v)
static _NameMaker< ObjectType, storageType > & getNameMaker(const std::string &prefix=std::string(""))
#define dbg_default_trace(...)
Definition: logger.hpp:40
void callFunc(Args... args)
Helper function I.
void post_object(const std::function< void(char const *const, std::size_t)> &f) const
Pass a pointer to a buffer containing this class&#39;s marshalled representation into the function f...
void applyLogTail(mutils::DeserializationManager *dsm, char const *v)
Definition: HLC.hpp:7
void initialize_log(const char *object_name) noexcept(false)
initialize from local state.
PersistentRegistry pr(nullptr, typeid(ReplicatedT), 123, 321)
std::unique_ptr< ObjectType > loadObject(const char *object_name) noexcept(false)
loadObject() loads a serializable object from a persistent store
_NameMaker() noexcept(false)
void unregister_callbacks() noexcept(false)
unregister the callbacks.
void saveObject(ObjectType &obj, const char *object_name) noexcept(false)
saveObject() saves a serializable object
#define PERSIST_EXP_INV_HLC
void saveNoLogObjectInFile(ObjectType &obj, const char *object_name) noexcept(false)
save object in file
version_t combine_int32s(const int_type high_bits, const int_type low_bits)
Helper function for creating Persistent version numbers out of MulticastGroup sequence numbers and Vi...
void register_callbacks() noexcept(false)
register the callbacks.
std::string getPersRamdiskPath()
Definition: util.hpp:29
virtual void print_performance_stat()
std::enable_if_t< std::is_pod< BR >::value > post_object(const F &f, const BR &br, Args &&... args)
In-place serialization is also sometimes possible.
auto getByIndex(int64_t idx, const Func &fun, mutils::DeserializationManager *dm=nullptr) noexcept(false)
get a version of Value T.
std::size_t to_bytes(const ByteRepresentable &b, char *v)
calls b.to_bytes(v) when b is a ByteRepresentable; calls std::memcpy() when b is POD.
static const uint64_t getMinimumLatestPersistedVersion(const std::string &prefix)
Get the minimum latest persisted version for a subgroup/shard with prefix prefix the subgroup/shard ...
Persistent(const std::function< std::unique_ptr< ObjectType >(void)> &object_factory, const char *object_name=nullptr, PersistentRegistry *persistent_registry=nullptr, mutils::DeserializationManager dm={{}}) noexcept(false)
constructor 1 is for building a persistent<T> locally, load/create a log and register itself to a per...
auto get(const Func &fun, mutils::DeserializationManager *dm=nullptr) noexcept(false)
get the latest Value of T.
#define PERSIST_EXP_SPIN_UNLOCK(x)
virtual const int64_t getLastPersisted() noexcept(false)
get the last persisted index.
virtual void set(ObjectType &v, const version_t &ver, const HLC &mhlc) noexcept(false)
make a version with a version number and mhlc clock
const std::string & getObjectName()
get object name
static std::string generate_prefix(const std::type_index &subgroup_type, uint32_t subgroup_index, uint32_t shard_num) noexcept(true)
prefix generator prefix format: [hex of subgroup_type]-[subgroup_index]-[shard_num] ...
Definition: Persistent.cpp:88
PersistentRegistry is a book for all the Persistent<T> or Volatile<T> variables.
Definition: Persistent.hpp:81