MVault 1.0.0
Simple c++ database
Loading...
Searching...
No Matches
Vault.hpp
1#pragma once
2
3#include "Vault.h"
4#include "VaultRecordSet.h"
5
6#include "VaultRecord.hpp"
7#include "VaultParamInput.hpp"
8
9// This file contains an implementation of the Vault template methods
10namespace mvlt
11{
12 template <class T>
14 {
15 DBG_LOG_ENTER();
16
17 // Fill res info known at start
19 res.Key = key;
20 res.RequestedType = typeid(T);
21
22 // A pointer for storing a hash table with T type key and vault record as value
24
25 // A pointer for storing a binary tree with T type key and vault record as value
27
28 // Lock Vault to write
29 WriteLock<RecursiveReadWriteMutex> writeLock(RecursiveReadWriteMtx);
30
31 // Check if dataRecord valid
32 if (dataRecord == nullptr || !dataRecord->GetIsValid())
33 {
34 res.IsOperationSuccess = false;
36 return res;
37 }
38
39 // If key not exist
40 if(!GetKeyType(key, res.SavedType))
41 {
42 res.IsOperationSuccess = false;
44 return res;
45 }
46
47 // Check types
48 if (res.SavedType != res.RequestedType)
49 {
50 res.IsOperationSuccess = false;
52 return res;
53 }
54
55
56 // Get std::unordered_multimap with T key and VaultRecord* value
57 VaultHashMapStructure.GetData(key, TtoVaultRecordHashMap);
58
59 // Get the current value of the key key inside the VaultRecordRef and save it for further work
60 T oldData{};
61 dataRecord->GetData(key, oldData);
62
63 // Remove oldData from TtoVaultRecordHashMap from VaultHashMapStructure
65
66 // Check if it is unique key and try to set duplicate data
68 {
69 res.IsOperationSuccess = false;
71
72 return res;
73 }
74
75 // Iterate over all data records with oldData key
77 {
78 // Find required data record
79 if ((*pairIt).second == dataRecord)
80 {
81 TtoVaultRecordHashMap->Erase((*pairIt).first);
82 break;
83 }
84 }
85
86 // Add new data to TtoVaultRecordHashMap to Vault VaultHashMapStructure
88
89
90 // Get std::multimap with T key and VaultRecord* value
91 VaultMapStructure.GetData(key, TtoVaultRecordMap);
92
93 // Remove oldData from TtoVaultRecordMap from VaultMapStructure
95
96 // Iterate over all data records with oldData key
98 {
99 // Find required data record
100 if ((*pairIt).second == dataRecord)
101 {
102 TtoVaultRecordMap->Erase((*pairIt).first);
103 break;
104 }
105 }
106
107 // Add new data to TtoVaultRecordMap to Vault VaultMapStructure
109
110
111 // Check if this method was original called. That mean that this method called not from next if statement.
112 // It is required since VaultRecordSet child of Vault and may also call this method
113 if (VaultDerivedClass == VaultDerivedClasses::VaultBase)
114 {
115 // Update all dependent VaultRecordSets
116 dataRecord->UpdateDependentSets(key, data);
117
118 // Update data inside VaultRecord pointer inside VaultRecordRef and Vault
119 dataRecord->SetData(key, data);
120 }
121
122 res.IsOperationSuccess = true;
124
125 return res;
126 }
127
128 template <class T>
129 VaultOperationResult Vault::RequestRecordsSet(const VaultRequestType& requestType, const std::string& key, const T& beginKeyValue,
130 const T& endKeyValue, std::unordered_set<VaultRecord*>& vaultRecords, const bool& isIncludeBeginKeyValue,
131 const bool& isIncludeEndKeyValue, const std::size_t& amountOfRecords, const std::function<bool(const VaultRecordRef& ref)>& requestPredicat) const noexcept
132 {
133 DBG_LOG_ENTER();
134
135 // Fill res info known at start
137 res.Key = key;
138 res.RequestedType = typeid(T);
139
140 // Lock Vault to read
141 ReadLock<RecursiveReadWriteMutex> readLock(RecursiveReadWriteMtx);
142
143 // If key not exist
144 if(!GetKeyType(key, res.SavedType))
145 {
146 res.IsOperationSuccess = false;
148 return res;
149 }
150
151 // Check types
152 if (res.SavedType != res.RequestedType)
153 {
154 res.IsOperationSuccess = false;
156 return res;
157 }
158
159 // Check if request type is equal
160 if (requestType == VaultRequestType::Equal)
161 {
162 // Pointer to store hash map inside VaultStructureHashMap
164
165 // Get hash map
166 VaultHashMapStructure.GetData(key, TtoVaultRecordHashMap);
167
168 // Pair with begin and end iterator with T type and beginKeyValue value
170 if (equalRange.first != TtoVaultRecordHashMap->End())
171 {
172 std::size_t counter = 0;
173 for (auto equalRangeIt = equalRange.first; equalRangeIt != equalRange.second; ++equalRangeIt)
174 {
175 // Check added records count
176 if (counter >= amountOfRecords) break;
177
178 // Check if it is not default predicate
179 if (&requestPredicat != &DefaultRequestPredicat)
180 {
181 if (requestPredicat(VaultRecordRef((*equalRangeIt).second, const_cast<Vault*>(this))))
182 vaultRecords.emplace((*equalRangeIt).second);
183 }
184 else
185 vaultRecords.emplace((*equalRangeIt).second);
186
187 ++counter;
188 }
189 }
190 }
191 else
192 {
193 // Pointer to store map inside VaultStructureHashMap
195
196 // Get map
197 VaultMapStructure.GetData(key, TtoVaultRecordMap);
198
199 // Iterator to set it in switch
200 decltype(TtoVaultRecordMap->End()) startIt{}, endIt{};
201
202 // Switch by request type
203 switch (requestType)
204 {
205 case VaultRequestType::GreaterOrEqual:
207 endIt = TtoVaultRecordMap->End();
208 break;
209
210 case VaultRequestType::Greater:
212 endIt = TtoVaultRecordMap->End();
213 break;
214
215 case VaultRequestType::Less:
216 startIt = TtoVaultRecordMap->Begin();
217 endIt = TtoVaultRecordMap->LowerBound(endKeyValue);
218 break;
219
220 case VaultRequestType::LessOrEqual:
221 startIt = TtoVaultRecordMap->Begin();
223 break;
224
225 case VaultRequestType::Interval:
227 {
228 startIt = TtoVaultRecordMap->End();
229 endIt = TtoVaultRecordMap->End();
230 break;
231 }
232
234 else startIt = TtoVaultRecordMap->UpperBound(beginKeyValue);
236 else endIt = TtoVaultRecordMap->LowerBound(endKeyValue);
237 // Dont forget to put break here if you adding logic to next cases
238
239 case VaultRequestType::Equal:
240 case VaultRequestType::Or:
241 case VaultRequestType::And:
242 default:
243 break;
244 }
245
246 std::size_t counter = 0;
248 {
249 if (counter >= amountOfRecords) break;
250
251 // Check if it is not default predicate
252 if (&requestPredicat != &DefaultRequestPredicat)
253 {
254 if (requestPredicat(VaultRecordRef((*TtoVaultRecordMapIt).second, const_cast<Vault*>(this))))
255 vaultRecords.emplace((*TtoVaultRecordMapIt).second);
256 }
257 else
258 vaultRecords.emplace((*TtoVaultRecordMapIt).second);
259
260 ++counter;
261 }
262 }
263
265 res.SavedType = res.RequestedType;
266 res.IsOperationSuccess = true;
267
268 return res;
269 }
270
271 template <class T>
272 VaultOperationResult Vault::RequestRecords(const VaultRequestType& requestType, const std::string& key, const T& beginKeyValue,
274 const bool& isIncludeEndKeyValue, const std::size_t& amountOfRecords, const std::function<bool(const VaultRecordRef& ref)>& requestPredicat) const noexcept
275 {
276 DBG_LOG_ENTER();
277
279
280 // Lock Vault to read
281 ReadLock<RecursiveReadWriteMutex> readLock(RecursiveReadWriteMtx);
282
283 // If it is Vault object
284 if (VaultDerivedClass == VaultDerivedClasses::VaultBase)
285 {
286 // Save vaultRecordSet
287 RecordSetsSet.emplace(&vaultRecordSet);
288
289 // Remove old data from vaultRecordSet
290 if (vaultRecordSet.ParentVault != this)
291 {
292 vaultRecordSet.Reset();
293
294 // Set new parent vault to vaultRecordSet
295 vaultRecordSet.ParentVault = const_cast<Vault*>(this);
296
297 // Copy keys from this to vaultRecordSet
298 for (auto& keyCopierIt : VaultKeyCopiers)
300
301 // Set proper key order
302 vaultRecordSet.KeysOrder = KeysOrder;
303
304 // Set unique keys
305 vaultRecordSet.UniqueKeys = UniqueKeys;
306 }
307 else vaultRecordSet.Clear();
308 }
309
311
312 for (VaultRecord* record : vaultRecordSet.RecordsSet)
313 {
314 // Add pointer to record to vaultRecordSet structure
315 for (auto& adder : vaultRecordSet.VaultRecordAdders)
316 adder.second(record);
317
318 record->AddToDependentSets(&vaultRecordSet);
319 }
320
321 return res;
322 }
323
324 template <class T>
325 VaultOperationResult Vault::AddKey(const std::string& key, const T& defaultKeyValue, const bool& isUniqueKey, const bool& isUniqueKeyWithoutLambda,
326 const std::function<T(const std::size_t& counter, const VaultRecordRef& ref)>& uniqueKeyFunction) noexcept
327 {
328 DBG_LOG_ENTER();
329
331 res.Key = key;
332 res.RequestedType = typeid(T);
333
334 // Lock Vault to write
335 WriteLock<RecursiveReadWriteMutex> writeLock(RecursiveReadWriteMtx);
336
337 // If the key was added earlier
338 auto keyType = KeysTypes.find(key);
339 if (keyType != KeysTypes.end())
340 {
341 res.IsOperationSuccess = false;
343 res.SavedType = keyType->second;
344 return res;
345 }
346
347 // Create new hash map to store data with template T key
349 VaultHashMapStructure.SetData(key, TtoVaultRecordHashMap, [](const void* ptr)
350 {
352 }
353 );
354
355 // Create new map to store data with template T key
357 VaultMapStructure.SetData(key, TtoVaultRecordMap, [](const void* ptr)
358 {
359 delete* (Map<T, VaultRecord*>**)ptr;
360 }
361 );
362
363 // Add new data to record set
364 if (isUniqueKey)
365 {
366 // If no lamda provided and vault not empty
367 if (isUniqueKeyWithoutLambda && !RecordsSet.empty())
368 {
369 res.IsOperationSuccess = false;
371 return res;
372 }
373
374 std::size_t counter = 0;
375 std::vector<T> cachedData;
376 bool isCorrectKey = true;
377
378 // Cycle for check uniqueKeyFunction validity
379 for (VaultRecord* recordsSetIt : RecordsSet)
380 {
382 ++counter;
383
385 // If failed to emplace unique key then it is duplicate and error in uniqueKeyFunction
386 if (!emplacePair.second)
387 {
388 isCorrectKey = false;
389 break;
390 }
391
392 cachedData.push_back(std::move(value));
393 }
394
395 // If key correct then add data to all places
396 if (isCorrectKey)
397 {
398 counter = 0;
399 for (VaultRecord* recordsSetIt : RecordsSet)
400 {
402 if (VaultDerivedClass == VaultDerivedClasses::VaultBase)
404
405 ++counter;
406 }
407 }
408 else
409 {
410 VaultHashMapStructure.EraseData(key);
411 VaultMapStructure.EraseData(key);
412
413 res.IsOperationSuccess = false;
415 return res;
416 }
417 }
418 else
419 {
420 for (VaultRecord* recordsSetIt : RecordsSet)
421 {
425 }
426 }
427
428 // Add key to list with key order
429 if(VaultDerivedClass == VaultDerivedClasses::VaultBase)
430 KeysOrder.emplace_back(key);
431
432 // Add key type to hash map with keys types
433 KeysTypes.emplace(key, typeid(T));
434
435 // Add data to template
436 RecordTemplate.SetData(key, defaultKeyValue);
437
438 // Add unique key
439 if (isUniqueKey) UniqueKeys.emplace(key);
440
441 // Add function to VaultRecord creation
442 VaultRecordAdders.emplace(key, [=](VaultRecord* newRecord)
443 {
444 // Make temporary variable to store key value
446 // Try to get key value from new record. If it is not value inside then defaultKeyValue will be used
447 newRecord->GetData(key, value);
448
449 // Try to emplace data into hash table. If it is multi container then it is always emplaced
450 // If it is not multi container then data emplaced only if it was not same data alredy in hash table
452
453 // Return false if data alredy in hash table
454 if (!emplaceRes.second) return false;
455
457 return true;
458 }
459 );
460
461 // Add function to TtoVaultRecordHashMap clearing
462 VaultRecordClearers.emplace(key, [=]()
463 {
464 TtoVaultRecordHashMap->Clear();
465 TtoVaultRecordMap->Clear();
466 }
467 );
468
469 // Add function to erase record from TtoVaultRecordHashMap
470 VaultRecordErasers.emplace(key, [=](VaultRecord* record)
471 {
472 // Get T type data with key key
473 T recordTData{};
474 record->GetData(key, recordTData);
475
476 // Find all elements on multi_map with recordTData value
478
479 // Find record and erase it from TtoVaultRecordHashMap
481 {
482 if ((*pairIt).second == record)
483 {
485 break;
486 }
487 }
488
489 // Find all elements on map with recordTData value
491 // Find record and erase it from TtoVaultRecordHashMap
493 {
494 if ((*pairIt).second == record)
495 {
496 TtoVaultRecordMap->Erase((*pairIt).first);
497 break;
498 }
499 }
500 }
501 );
502
503 VaultRecordSorters.emplace(key, [=](const std::function<bool(const VaultRecordRef& ref)>& functionToSortedData, Vault* vltPtr, const bool& isReverse)
504 {
505 if (!isReverse)
506 {
507 for (const auto& TtoVaultRecordMapIt : *TtoVaultRecordMap)
509 break;
510 }
511 else
512 {
514 if(!functionToSortedData(VaultRecordRef((*TtoVaultRecordMapIt).second, vltPtr)))
515 break;
516 }
517 });
518
519 VaultKeyCopiers.emplace(key, [=](Vault* vaultRecordSet)
520 {
522 });
523
524 if (VaultDerivedClass == VaultDerivedClasses::VaultBase)
525 {
526 for (VaultRecordSet* set : RecordSetsSet)
527 {
528 if (isUniqueKey)
529 set->AddUniqueKey(key, uniqueKeyFunction);
530 else
531 set->AddKey(key, defaultKeyValue);
532 set->KeysOrder.emplace_back(key);
533 }
534 }
535
536 res.IsOperationSuccess = true;
538 return res;
539 }
540
541 template <class T>
542 bool Vault::AddKey(const std::string& key, const T& defaultKeyValue) noexcept
543 {
544 DBG_LOG_ENTER();
545
546 static_assert(!std::is_array<T>::value, "It is not possible to use a c array as a key value. \n\
547 If you want to use a string as a key, you must specialize the function with a string. Like this: \n\
548 AddKey<std::string>(\"Key\", \"Value\") or AddKey(\"Key\", std::string(\"Value\"))");
549
550 return AddKey(key, defaultKeyValue, false, false, {[&](std::size_t counter, const VaultRecordRef&) -> T{ return defaultKeyValue; }}).IsOperationSuccess;
551 }
552
553 template <class T>
554 VaultOperationResult Vault::AddUniqueKey(const std::string& key) noexcept
555 {
556 DBG_LOG_ENTER();
557
558 static_assert(!std::is_array<T>::value, "It is not possible to use a c array as a key value. \n\
559 If you want to use a string as a key, you must specialize the function with a string. Like this: \n\
560 AddUniqueKey<std::string>(\"Key\")");
561
562 return AddKey(key, T{}, true, true, {[&](std::size_t counter, const VaultRecordRef&) -> T{ return T{}; }});
563 }
564
565 template <class T>
566 VaultOperationResult Vault::AddUniqueKey(const std::string& key, const std::function<T(const std::size_t& counter, const VaultRecordRef& ref)>& uniqueKeyFunction) noexcept
567 {
568 DBG_LOG_ENTER();
569
570 return AddKey(key, T{}, true, false, uniqueKeyFunction);
571 }
572
573 template <class T>
574 VaultOperationResult Vault::UpdateKey(const std::string& key, const T& defaultKeyValue) noexcept
575 {
576 DBG_LOG_ENTER();
577
578 static_assert(!std::is_array<T>::value, "It is not possible to use a c array as a key value. \n\
579 If you want to use a string as a key, you must specialize the function with a string. Like this: \n\
580 UpdateKey<std::string>(\"Key\", \"Value\") or UpdateKey(\"Key\", std::string(\"Value\"))");
581
583 res.Key = key;
584 res.RequestedType = typeid(defaultKeyValue);
585
586 // Lock Vault to write
587 WriteLock<RecursiveReadWriteMutex> writeLock(RecursiveReadWriteMtx);
588
589 // If the key was not added earlier, then it can not be updated
590 std::unordered_map<std::string, std::type_index>::iterator keyTypeIt = KeysTypes.find(key);
591 if (keyTypeIt == KeysTypes.end())
592 {
593 res.IsOperationSuccess = false;
595 return res;
596 }
597
598 // Check it is trying to set coorect type
599 if (res.RequestedType != keyTypeIt->second)
600 {
601 res.SavedType = keyTypeIt->second;
602 res.IsOperationSuccess = false;
604 return res;
605 }
606
607 // Check if it is unique key
608 if (UniqueKeys.find(key) != UniqueKeys.end())
609 {
610 res.SavedType = keyTypeIt->second;
611 res.IsOperationSuccess = false;
613 return res;
614 }
615
616 // Change data in template
617 RecordTemplate.SetData(key, defaultKeyValue);
618
619 res.SavedType = res.RequestedType;
621 return res;
622 }
623
624 template <class T>
625 VaultOperationResult Vault::GetKeyValue(const std::string& key, T& defaultKeyValue) const noexcept
626 {
627 DBG_LOG_ENTER();
628
629 static_assert(!std::is_array<T>::value, "It is not possible to use a c array as a key value.");
630
632 res.Key = key;
633 res.RequestedType = typeid(T);
634
635 // Lock Vault to read
636 ReadLock<RecursiveReadWriteMutex> readLock(RecursiveReadWriteMtx);
637
638 // If key not exist
639 if(!GetKeyType(key, res.SavedType))
640 {
641 res.IsOperationSuccess = false;
643 return res;
644 }
645
646 // Check types
647 if (res.SavedType != res.RequestedType)
648 {
649 res.IsOperationSuccess = false;
651 return res;
652 }
653
654 // Check if it is unique key
655 if (UniqueKeys.find(key) != UniqueKeys.end())
656 {
657 res.IsOperationSuccess = false;
659 return res;
660 }
661
662 RecordTemplate.GetData(key, defaultKeyValue);
663
664 res.IsOperationSuccess = true;
666 res.SavedType = res.RequestedType;
667
668 return res;
669 }
670
671 template <class T>
673 {
674 DBG_LOG_ENTER();
675
676 static_assert(!std::is_array<T>::value, "It is not possible to use a c array as a key value. \n\
677 If you want to use a string as a key, you must specialize the function with a string. Like this: \n\
678 GetRecord<std::string>(\"Key\", \"Value\") or GetRecord(\"Key\", std::string(\"Value\"))");
679
680 // Fill res info known at start
682 res.Key = key;
683 res.RequestedType = typeid(T);
684
685 // Lock Vault to read
686 ReadLock<RecursiveReadWriteMutex> readLock(RecursiveReadWriteMtx);
687
688 // If key not exist
689 if(!GetKeyType(key, res.SavedType))
690 {
691 res.IsOperationSuccess = false;
693 return res;
694 }
695
696 // Check types
697 if (res.SavedType != res.RequestedType)
698 {
699 res.IsOperationSuccess = false;
701 return res;
702 }
703
704 // Pointer to store map inside VaultStructureHashMap
706
707 // Checking whether such a key exists
708 VaultHashMapStructure.GetData(key, TtoVaultRecordHashMap);
709
710 // Iterator to element with T type and keyValue value
713 {
714 vaultRecordRef.SetRecord((*TtoVaultRecordIt).second, const_cast<Vault*>(this));
715 res.IsOperationSuccess = true;
717 }
718 else
719 {
720 vaultRecordRef.SetRecord(nullptr, const_cast<Vault*>(this));
721 res.IsOperationSuccess = false;
723 }
724
725 return res;
726 }
727
728 template <class T>
729 VaultOperationResult Vault::GetRecords(const std::string& key, const T& keyValue, std::vector<VaultRecordRef>& recordsRefs, const std::size_t& amountOfRecords) const noexcept
730 {
731 DBG_LOG_ENTER();
732
733 static_assert(!std::is_array<T>::value, "It is not possible to use a c array as a key value. \n\
734 If you want to use a string as a key, you must specialize the function with a string. Like this: \n\
735 GetRecords<std::string>(\"Key\", \"Value\") or GetRecords(\"Key\", std::string(\"Value\"))");
736
737 // Fill res info known at start
739 res.Key = key;
740 res.RequestedType = typeid(T);
741
742 recordsRefs.clear();
743
744 // Lock Vault to read
745 ReadLock<RecursiveReadWriteMutex> readLock(RecursiveReadWriteMtx);
746
747 // If key not exist
748 if(!GetKeyType(key, res.SavedType))
749 {
750 res.IsOperationSuccess = false;
752 return res;
753 }
754
755 // Check types
756 if (res.SavedType != res.RequestedType)
757 {
758 res.IsOperationSuccess = false;
760 return res;
761 }
762
763 // Pointer to store map inside VaultStructureHashMap
765
766 // Checking whether such a key exists
767 VaultHashMapStructure.GetData(key, TtoVaultRecordHashMap);
768
769 // Pair with begin and end iterator with T type and keyValue value
770 auto equalRange = TtoVaultRecordHashMap->EqualRange(keyValue);
771 if (equalRange.first != TtoVaultRecordHashMap->end())
772 {
773 std::size_t counter = 0;
774 for (auto equalRangeIt = equalRange.first; equalRangeIt != equalRange.second; ++equalRangeIt)
775 {
776 ++counter;
777 recordsRefs.emplace_back(VaultRecordRef((*equalRangeIt).second, const_cast<Vault*>(this)));
778 if (counter >= amountOfRecords) break;
779 }
780
781 res.IsOperationSuccess = true;
783 }
784 else
785 {
786 res.IsOperationSuccess = false;
788 }
789
790 return res;
791 }
792
793 template <class T>
795 const std::size_t& amountOfRecords, const std::function<bool(const VaultRecordRef& ref)>& requestPredicat) const noexcept
796 {
797 DBG_LOG_ENTER();
798
799 static_assert(!std::is_array<T>::value, "It is not possible to use a c array as a key value. \n\
800 If you want to use a string as a key, you must specialize the function with a string. Like this: \n\
801 RequestEqual<std::string>(\"Key\", \"Value\") or RequestEqual(\"Key\", std::string(\"Value\"))");
802
803 return RequestRecords(VaultRequestType::Equal, key, keyValue, keyValue, vaultRecordSet, false, false, amountOfRecords, requestPredicat);
804 }
805
806 template <class T>
808 const std::size_t& amountOfRecords, const std::function<bool(const VaultRecordRef& ref)>& requestPredicat) const noexcept
809 {
810 DBG_LOG_ENTER();
811
812 static_assert(!std::is_array<T>::value, "It is not possible to use a c array as a key value. \n\
813 If you want to use a string as a key, you must specialize the function with a string. Like this: \n\
814 RequestGreater<std::string>(\"Key\", \"Value\") or RequestGreater(\"Key\", std::string(\"Value\"))");
815
816 return RequestRecords(VaultRequestType::Greater, key, keyValue, keyValue, vaultRecordSet, false, false, amountOfRecords, requestPredicat);
817 }
818
819 template <class T>
821 const std::size_t& amountOfRecords, const std::function<bool(const VaultRecordRef& ref)>& requestPredicat) const noexcept
822 {
823 DBG_LOG_ENTER();
824
825 static_assert(!std::is_array<T>::value, "It is not possible to use a c array as a key value. \n\
826 If you want to use a string as a key, you must specialize the function with a string. Like this: \n\
827 RequestGreaterOrEqual<std::string>(\"Key\", \"Value\") or RequestGreaterOrEqual(\"Key\", std::string(\"Value\"))");
828
829 return RequestRecords(VaultRequestType::GreaterOrEqual, key, keyValue, keyValue, vaultRecordSet, false, false, amountOfRecords, requestPredicat);
830 }
831
832 template <class T>
834 const std::size_t& amountOfRecords, const std::function<bool(const VaultRecordRef& ref)>& requestPredicat) const noexcept
835 {
836 DBG_LOG_ENTER();
837
838 static_assert(!std::is_array<T>::value, "It is not possible to use a c array as a key value. \n\
839 If you want to use a string as a key, you must specialize the function with a string. Like this: \n\
840 RequestLess<std::string>(\"Key\", \"Value\") or RequestLess(\"Key\", std::string(\"Value\"))");
841
842 return RequestRecords(VaultRequestType::Less, key, keyValue, keyValue, vaultRecordSet, false, false, amountOfRecords, requestPredicat);
843 }
844
845 template <class T>
847 const std::size_t& amountOfRecords, const std::function<bool(const VaultRecordRef& ref)>& requestPredicat) const noexcept
848 {
849 DBG_LOG_ENTER();
850
851 static_assert(!std::is_array<T>::value, "It is not possible to use a c array as a key value. \n\
852 If you want to use a string as a key, you must specialize the function with a string. Like this: \n\
853 RequestLessOrEqual<std::string>(\"Key\", \"Value\") or RequestLessOrEqual(\"Key\", std::string(\"Value\"))");
854
855 return RequestRecords(VaultRequestType::LessOrEqual, key, keyValue, keyValue, vaultRecordSet, false, false, amountOfRecords, requestPredicat);
856 }
857
858 template <class T>
861 const bool& isIncludeEndKeyValue, const std::size_t& amountOfRecords, const std::function<bool(const VaultRecordRef& ref)>& requestPredicat) const noexcept
862 {
863 DBG_LOG_ENTER();
864
865 static_assert(!std::is_array<T>::value, "It is not possible to use a c array as a key value. \n\
866 If you want to use a string as a key, you must specialize the function with a string. Like this: \n\
867 RequestInterval<std::string>(\"Key\", \"Value\") or RequestInterval(\"Key\", std::string(\"Value\"))");
868
869 return RequestRecords(VaultRequestType::Interval, key, beginKeyValue,
872 }
873
874 template <VaultRequestType Type>
876 {
877 DBG_LOG_ENTER();
878
880 res.IsOperationSuccess = true;
882
883 // Lock Vault to read
884 ReadLock<RecursiveReadWriteMutex> readLock(RecursiveReadWriteMtx);
885
886 // If it is Vault object
888 {
889 // Save vaultRecordSet
891
892 // Remove old data from vaultRecordSet
893 if (vaultRecordSet.ParentVault != this)
894 {
895 vaultRecordSet.Reset();
896
897 // Set new parent vault to vaultRecordSet
898 vaultRecordSet.ParentVault = const_cast<Vault*>(this);
899
900 // Copy keys from this to vaultRecordSet
901 for (auto& keyCopierIt : VaultKeyCopiers)
903
904 // Set proper key order
905 vaultRecordSet.KeysOrder = KeysOrder;
906
907 // Set unique keys
908 vaultRecordSet.UniqueKeys = UniqueKeys;
909 }
910 else vaultRecordSet.Clear();
911 }
912
913 // Try to make complex request
914 try
915 {
916 request.Request(const_cast<Vault*>(this), vaultRecordSet.RecordsSet);
917
918 for (VaultRecord* record : vaultRecordSet.RecordsSet)
919 {
920 // Add pointer to record from this to vaultRecordSet structure
921 for (auto& adder : vaultRecordSet.VaultRecordAdders)
922 adder.second(record);
923
924 // Lock VaultRecord to thread safety add new dependent VaultRecordSet
925 record->AddToDependentSets(&vaultRecordSet);
926 }
927 }
928 catch(VaultOperationResult& result) // Catch complex request errors
929 {
930 vaultRecordSet.Clear();
931 res = result;
932 }
933
934 return res;
935 }
936
937 template <class T>
938 VaultOperationResult Vault::EraseRecord(const std::string& key, const T& keyValue) noexcept
939 {
940 DBG_LOG_ENTER();
941
942 static_assert(!std::is_array<T>::value, "It is not possible to use a c array as a key value. \n\
943 If you want to use a string as a key, you must specialize the function with a string. Like this: \n\
944 EraseRecord<std::string>(\"Key\", \"Value\") or EraseRecord(\"Key\", std::string(\"Value\"))");
945
946 // Fill res info known at start
948 res.Key = key;
949 res.RequestedType = typeid(T);
950
951 // Lock Vault to write
952 WriteLock<RecursiveReadWriteMutex> writeLock(RecursiveReadWriteMtx);
953
954 // If key not exist
955 if(!GetKeyType(key, res.SavedType))
956 {
957 res.IsOperationSuccess = false;
959 return res;
960 }
961
962 // Check types
963 if (res.SavedType != res.RequestedType)
964 {
965 res.IsOperationSuccess = false;
967 return res;
968 }
969
970 // Pointer to store map inside VaultStructureHashMap
972
973 // Checking whether such a key exists
974 VaultHashMapStructure.GetData(key, TtoVaultRecordHashMap);
975
976 // Iterator to element with T type and keyValue value
979 {
980 VaultRecord* tmpRec = (*TtoVaultRecordIt).second;
981
982 for (auto& eraser : VaultRecordErasers)
983 eraser.second(tmpRec);
984
985 RecordsSet.erase(tmpRec);
986
987 // Check if it is delete. By now it is deletion when EraseRecord called from vault.
988 // It is not deleting when RemoveRecord called from VaultRecordSet
989 if (VaultDerivedClass == VaultDerivedClasses::VaultBase)
990 {
991 tmpRec->RemoveFromDependentSets();
992 tmpRec->Invalidate();
993 }
994
995 res.IsOperationSuccess = true;
997 }
998 else
999 {
1000 res.IsOperationSuccess = false;
1002 }
1003
1004 return res;
1005 }
1006
1007 template <class T>
1008 VaultOperationResult Vault::EraseRecords(const std::string& key, const T& keyValue, const std::size_t& amountOfRecords) noexcept
1009 {
1010 DBG_LOG_ENTER();
1011
1012 static_assert(!std::is_array<T>::value, "It is not possible to use a c array as a key value. \n\
1013 If you want to use a string as a key, you must specialize the function with a string. Like this: \n\
1014 EraseRecords<std::string>(\"Key\", \"Value\") or EraseRecords(\"Key\", std::string(\"Value\"))");
1015
1016 // Fill res info known at start
1018 res.Key = key;
1019 res.RequestedType = typeid(T);
1020
1021 // Lock Vault to write
1022 WriteLock<RecursiveReadWriteMutex> writeLock(RecursiveReadWriteMtx);
1023
1024 // If key not exist
1025 if(!GetKeyType(key, res.SavedType))
1026 {
1027 res.IsOperationSuccess = false;
1029 return res;
1030 }
1031
1032 // Check types
1033 if (res.SavedType != res.RequestedType)
1034 {
1035 res.IsOperationSuccess = false;
1037 return res;
1038 }
1039
1040 // Pointer to store map inside VaultStructureHashMap
1042
1043 // Checking whether such a key exists
1044 VaultHashMapStructure.GetData(key, TtoVaultRecordHashMap);
1045
1046 // Pair with begin and end iterator with T type and keyValue value
1047 auto equalRange = TtoVaultRecordHashMap->EqualRange(keyValue);
1048 if (equalRange.first != TtoVaultRecordHashMap->end())
1049 {
1050 res.IsOperationSuccess = true;
1052
1053 std::size_t counter = 0;
1054 for (auto equalRangeIt = equalRange.first; equalRangeIt != equalRange.second;)
1055 {
1056 // Save next iterator
1057 auto nextIt = equalRangeIt;
1058 ++nextIt;
1059
1060 ++counter;
1061
1062 VaultRecord* tmpRec = (*equalRangeIt).second;
1063 for (auto& eraser : VaultRecordErasers)
1064 eraser.second(tmpRec);
1065
1066 RecordsSet.erase(tmpRec);
1067
1068 // Check if it is delete. By now it is deletion when EraseRecord called from vault.
1069 // It is not deleting when RemoveRecord called from VaultRecordSet
1070 if (VaultDerivedClass == VaultDerivedClasses::VaultBase)
1071 {
1072 tmpRec->RemoveFromDependentSets();
1073 tmpRec->Invalidate();
1074 }
1075
1076 if (counter >= amountOfRecords) break;
1077
1079 }
1080 }
1081 else
1082 {
1083 res.IsOperationSuccess = false;
1085 }
1086
1087 return res;
1088 }
1089}
Iterator class for all library maps.
Definition Map.h:18
A class for storing data with the ability to quickly search for a variety of different keys of any ty...
Definition Vault.h:35
bool EraseRecord(const VaultRecordRef &recordRefToErase) noexcept
Method for deleting a record from a Vault.
Definition Vault.cpp:626
VaultOperationResult RequestLessOrEqual(const std::string &key, const T &keyValue, VaultRecordSet &vaultRecordSet, const std::size_t &amountOfRecords=-1, const std::function< bool(const VaultRecordRef &ref)> &requestPredicat=DefaultRequestPredicat) const noexcept
A method for getting all records that have a value less than or equal to keyValue stored by the key k...
Definition Vault.hpp:846
VaultOperationResult GetKeyValue(const std::string &key, T &defaultKeyValue) const noexcept
The method for getting a default key value.
Definition Vault.hpp:625
VaultOperationResult RequestRecords(const VaultRequestType &requestType, const std::string &key, const T &beginKeyValue, const T &endKeyValue, VaultRecordSet &vaultRecordSet, const bool &isIncludeBeginKeyValue, const bool &isIncludeEndKeyValue, const std::size_t &amountOfRecords, const std::function< bool(const VaultRecordRef &ref)> &requestPredicat) const noexcept
The method for getting the result of the request.
Definition Vault.hpp:272
VaultOperationResult SetDataToRecord(VaultRecord *dataRecord, const std::string &key, const T &data) noexcept
Method for setting a new value in VaultRecord and Vault.
Definition Vault.hpp:13
VaultOperationResult AddKey(const std::string &key, const T &defaultKeyValue, const bool &isUniqueKey, const bool &isUniqueKeyWithoutLambda, const std::function< T(const std::size_t &counter, const VaultRecordRef &ref)> &uniqueKeyFunction) noexcept
Template method to add new key with default value to Vault.
Definition Vault.hpp:325
VaultOperationResult GetRecord(const std::string &key, const T &keyValue, VaultRecordRef &vaultRecordRef) const noexcept
The method for getting a reference to the data inside Vault.
Definition Vault.hpp:672
VaultOperationResult RequestRecordsSet(const VaultRequestType &requestType, const std::string &key, const T &beginKeyValue, const T &endKeyValue, std::unordered_set< VaultRecord * > &recordsSet, const bool &isIncludeBeginKeyValue, const bool &isIncludeEndKeyValue, const std::size_t &amountOfRecords, const std::function< bool(const VaultRecordRef &ref)> &requestPredicat) const noexcept
The method for getting the result of the request in the std::set.
Definition Vault.hpp:129
VaultOperationResult GetRecords(const std::string &key, const T &keyValue, std::vector< VaultRecordRef > &recordsRefs, const std::size_t &amountOfRecords=-1) const noexcept
The method for getting a vector of references to the data inside Vault.
Definition Vault.hpp:729
VaultDerivedClasses VaultDerivedClass
A variable for storing the object type in the Vault inheritance tree.
Definition Vault.h:107
VaultOperationResult RequestEqual(const std::string &key, const T &keyValue, VaultRecordSet &vaultRecordSet, const std::size_t &amountOfRecords=-1, const std::function< bool(const VaultRecordRef &ref)> &requestPredicat=DefaultRequestPredicat) const noexcept
A method for getting all records that have a value equal to keyValue stored by the key key.
Definition Vault.hpp:794
VaultOperationResult RequestGreater(const std::string &key, const T &keyValue, VaultRecordSet &vaultRecordSet, const std::size_t &amountOfRecords=-1, const std::function< bool(const VaultRecordRef &ref)> &requestPredicat=DefaultRequestPredicat) const noexcept
A method for getting all records that have a value greater than keyValue stored by the key key.
Definition Vault.hpp:807
VaultOperationResult RequestLess(const std::string &key, const T &keyValue, VaultRecordSet &vaultRecordSet, const std::size_t &amountOfRecords=-1, const std::function< bool(const VaultRecordRef &ref)> &requestPredicat=DefaultRequestPredicat) const noexcept
A method for getting all records that have a value less than keyValue stored by the key key.
Definition Vault.hpp:833
VaultOperationResult RequestInterval(const std::string &key, const T &beginKeyValue, const T &endKeyValue, VaultRecordSet &vaultRecordSet, const bool &isIncludeBeginKeyValue=true, const bool &isIncludeEndKeyValue=true, const std::size_t &amountOfRecords=-1, const std::function< bool(const VaultRecordRef &ref)> &requestPredicat=DefaultRequestPredicat) const noexcept
The method for getting the result of the request.
Definition Vault.hpp:859
@ VaultBase
Vault class itself.
std::unordered_set< VaultRecordSet * > RecordSetsSet
Unordered set with all VaultRecordSet pointers.
Definition Vault.h:113
VaultOperationResult Request(const VaultRequest< Type > &request, VaultRecordSet &vaultRecordSet) const
A method for complex requests.
Definition Vault.hpp:875
VaultOperationResult RequestGreaterOrEqual(const std::string &key, const T &keyValue, VaultRecordSet &vaultRecordSet, const std::size_t &amountOfRecords=-1, const std::function< bool(const VaultRecordRef &ref)> &requestPredicat=DefaultRequestPredicat) const noexcept
A method for getting all records that have a value greater than or equal to keyValue stored by the ke...
Definition Vault.hpp:820
VaultOperationResult EraseRecords(const std::string &key, const T &keyValue, const std::size_t &amountOfRecords=-1) noexcept
The method for erase records using key and value.
Definition Vault.hpp:1008
VaultOperationResult UpdateKey(const std::string &key, const T &defaultKeyValue) noexcept
Template method to update default key value.
Definition Vault.hpp:574
VaultOperationResult AddUniqueKey(const std::string &key) noexcept
Template method to add new unique key to Vault.
Definition Vault.hpp:554
A class for storing data inside Vault.
Definition VaultRecord.h:18
A class that provides access to data inside Vault.
Definition VaultRecordRef.h:21
A class for storing query results.
Definition VaultRecordSet.h:14
@ Success
This value is returned when the request was completely successful.
@ DataRecordNotValid
This code is returned when data is requested from the VaultRecordRef and the record it refers to is n...
@ UniqueKeyValueAlredyInSet
This value is returned when the key was found, the requested type and the saved type are equal,...
@ WrongKey
This code is returned when the requested key has not been found.
@ WrongValue
This value is returned when the key was found, the requested type and the saved type are equal,...
@ UniqueKey
This code is returned when trying to update default value in an unique key.
@ TryToAddUniqueKeyInNonEmptyVaultWithoutLambda
This code is returned when trying to add unique key without lamda in non-empty vault.
@ DuplicateKey
This code is returned when trying to add key which alredy in vault.
@ WrongType
This code is returned when the requested type does not match the saved type.
Structure for storing the results of MVault operations.
Definition VaultOperationResult.h:44