Major Objects: Difference between revisions
Line 21: | Line 21: | ||
=== Delayed delete pattern === | === Delayed delete pattern === | ||
1) to dynamically delete an object: | 1) to dynamically delete an object: | ||
ba.setDeleted(); | a) ba.setDeleted(); | ||
b) do not remove from any container indexes | |||
c) but fix the index sorting, flags, etc, as if the object were gone, so the program will function as if it is! | |||
eg: do not remove from runsByRank_, but adjust all other ranking as if the run was gone | |||
2) include deleted status in active check, etc.: | 2) include deleted status in active check, etc.: | ||
// NOTE use the direct function rather than !bFunc(), as deleted objects return false for both. | // NOTE use the direct function rather than !bFunc(), as deleted objects return false for both. | ||
bool bActive() const { return b_active_ && !bDeleted(); } | bool bActive() const { return b_active_ && !bDeleted(); } | ||
bool bInactive() const { return !b_active_ && !bDeleted(); } | bool bInactive() const { return !b_active_ && !bDeleted(); } | ||
--- | |||
for (auto& psr: runsByRank_) { | |||
if (psr->bDeleted()) continue; | |||
... | |||
3) all deletion work is done in MemoryModel::saveDirtyObjectsAsNeeded(), see that code | 3) all deletion work is done in MemoryModel::saveDirtyObjectsAsNeeded(), see that code | ||
a) deletion check should happen in delayed write check: | a) deletion check should happen in delayed write check: |
Revision as of 12:41, 12 April 2017
Overview
- Major Objects
- Use Major Objects for fast in-memory handling of large amount of data that is thread-safe but must be persisted
- We must support complex objects with simple keys, crud, and fast lookup by multiple keys.
- Our most useful containers are vector, set (key in object) and map (<key,value> pair). Set can give us almost every positive feature, when used to store the PersistentIDObject class.
- Use an unordered_set of const pointers to objects derived from PersistentIDObject
- The default container should index by db_id primary key
- Always use the db_id for foreign keys
- Other containers can be created with alternate keys using object members; just define new hash functions.
- PersistentIDObject
- Add a dirty flag to all objects, set to true on any change that must be persisted
- Use an internal in-memory counter to generate the next db_id for a newly created object
- This means that when creating new objects, there is NO NEED to access db, VERY IMPORTANT!
- Use delayed-write tactics to write all dirty objects on idle time
- Memory Model
- Use a Datastore manager (aka "MemoryModel") to hold sets
- It can look up objects by any key, and strip away const to return a mutable object. NOTE that the user must not damage the key values!
- Derive a class from the memory model for persistence; it can use any persistence method (local, remote, sql, nosql, etc.).
- Make sure that the base MemoryModel class is concrete not abstract, thread-safe and self-contained; this makes parallel calculations trivial, helps scalability, etc.
Delayed delete pattern
1) to dynamically delete an object: a) ba.setDeleted(); b) do not remove from any container indexes c) but fix the index sorting, flags, etc, as if the object were gone, so the program will function as if it is! eg: do not remove from runsByRank_, but adjust all other ranking as if the run was gone 2) include deleted status in active check, etc.: // NOTE use the direct function rather than !bFunc(), as deleted objects return false for both. bool bActive() const { return b_active_ && !bDeleted(); } bool bInactive() const { return !b_active_ && !bDeleted(); } --- for (auto& psr: runsByRank_) { if (psr->bDeleted()) continue; ... 3) all deletion work is done in MemoryModel::saveDirtyObjectsAsNeeded(), see that code a) deletion check should happen in delayed write check: if (pau->bDirtyOrDeleted()) bNeeded = true; b) if bNeeded, always do deletions first, starting with greatest grandparent container, to minimize work c) use the erase-remove pattern to remove all deleted items in one loop see code here for reference implementation: BrokerAccount::removeDeletedStockRuns() i) iterate and remove item from all secondary indices ii) iterate primary index, and use the lambda of the erase-remove operation to delete memory allocation and remove db record iii) associative container iterators can be safely deleted directly sequential containers like vector require use of erase-remove idiom see reference implementation for example code!