Persistence

GigaMap seamlessly integrates with EclipseStore. All required type handlers are registered automatically.

Loading

The loading process is fully automatic, as usual. Even the lazy loading is handled internally.

Storing

After updating the contents of the GigaMap, call gigaMap.store() to persist the changes:

gigaMap.store();

This is the recommended way to store. gigaMap.store() is synchronized internally — it acquires the GigaMap’s lock, ensuring that no other thread can modify the GigaMap while the store operation is running.

The GigaMap monitors changes internally, ensuring that only the modified parts are written to the storage.

This applies to all internal changes of the GigaMap as well as to added and removed entities.

Entities modified through the update or apply methods are automatically included in the store operation. There is no need to store them separately.

gigaMap.update(person, p -> {
    p.setLastName("Smith"),
    p.setAddress(newAddress)
});
gigaMap.store();

GigaMap has no automatic change tracking. Changes made to entities directly (outside of update, apply, set, replace, add or remove) are not tracked, so they are neither stored automatically nor reflected in the indices.

Mutating an indexed field directly leaves the indices stale: bitmap queries return wrong results, and Lucene searches fail silently (no error). A subsequent gigaMap.store() does not fix this — it neither re-runs the indexers nor implicitly persists the direct mutation.

Always mutate indexed entities through update / apply, which update the indices and schedule the entity for storing. If a mutation already bypassed them, store the affected entities explicitly and call reindex() to rebuild all indices from the current entity state, then store() (note that reindex() rebuilds only the index structures — it does not store the entities):

person.setLastName("Smith");        // direct mutation (not tracked)
storageManager.store(person);       // persist the changed entity explicitly
gigaMap.reindex();                  // rebuild every index from current entity state
gigaMap.store();                    // persist the rebuilt indices

Why not storageManager.store(gigaMap)?

Storing the GigaMap through storageManager.store(gigaMap) or storageConnection.storeAll(…​) does not acquire the GigaMap’s internal lock. This means other threads can modify the GigaMap (e.g. by calling add, remove, or update) while it is being serialized, leading to errors such as BinaryPersistenceException: Inconsistent element count.

Always prefer gigaMap.store().

If you must store the GigaMap through an external path, you need to synchronize on the GigaMap instance yourself:

synchronized (gigaMap) {
    storageManager.store(gigaMap);
}

This is the same principle as the classic problem with synchronized JDK collections like Vector: synchronizing individual methods is not sufficient when multiple operations need to be atomic. In this case, the entire store traversal must be protected from concurrent modifications.

Class evolution and indexed fields

GigaMap’s indices (bitmap, Lucene, vector) are a derived cache: their keys are computed from your entities by the indexers and are then persisted alongside the entities. On load the index keys are restored verbatim from storage — they are not recomputed from, or revalidated against, the entities.

This matters when an indexed field’s class layout evolves between releases. EclipseStore’s serializer maps an evolved class to the new layout on load (see Legacy Type Mapping). If an indexed field is renamed or retyped without a value-preserving refactoring mapping, the loaded entities carry shifted or defaulted field values while the persisted index still carries the pre-evolution keys. The index is now stale, and nothing detects this automatically.

Evolving an indexed field without a value-preserving refactoring mapping leaves the indices stale — with the same consequences as a direct (untracked) mutation:

  • Queries return pre-evolution results: is(oldValue) still matches, is(actualValue) returns nothing. Only reindex() restores correct query results.

  • A subsequent update / apply / set that writes the entity’s true value may fail with a StaleIndexException. The committed entity is not deleted by this: a stale index never causes a phantom unique-constraint violation against the entity’s own entry, and a stale-index failure retains the entity rather than removing it. You still need to reindex() to make the index consistent again.

After evolving an indexed field, rebuild every index from the current entity state with reindex() before running any query or update, then store():

gigaMap.reindex();   // rebuild every index from current entity state
gigaMap.store();     // persist the rebuilt indices

If in doubt, prefer a value-preserving refactoring mapping for indexed fields, or call reindex() on first load after a release that changed an indexed field’s name or type.

Concurrency

See Concurrent Access for the full conceptual treatment.

As with any EclipseStore application, modifying the object graph and storing the changes must be done under the same lock. The gigaMap.store() method handles this for you by acquiring the GigaMap’s internal lock.

However, if your application modifies other parts of the object graph alongside the GigaMap, you are responsible for synchronizing those modifications and their corresponding store() calls as well. See Locking for details on application-level synchronization strategies.