Closed csc-gip closed 1 year ago
Possible implementation
private static class PersistenceStoreContext {
private Map<String, HashMap<String, Storable<?>>> objectsToStorePerTable = new HashMap<>();
private Map<Storable<?>, XynaObject> collisionInformation = new HashMap<>();
private final List<StorableStructureInformation> order;
private PersistenceStoreContext(XMOMStorableStructureInformation rootInfo) {
order = getStorableStructureHierarchyOrder(rootInfo);
}
public boolean add(StorableStructureInformation info, Storable<?> storable, XynaObject xoStorable) {
if (storable == null) {
return false;
}
Map<String, Storable<?>> objectsToStoreForTable = objectsToStorePerTable.get(info.getTableName());
if (objectsToStoreForTable == null) {
objectsToStoreForTable = new HashMap<String, Storable<?>>();
objectsToStorePerTable.put(info.getTableName(), objectsToStoreForTable);
}
String pk = String.valueOf(storable.getPrimaryKey());
boolean contained = objectsToStoreForTable.containsKey(pk);
if (!contained) {
objectsToStoreForTable.put(pk, storable);
if (info instanceof XMOMStorableStructureInformation) {
collisionInformation.put(storable, xoStorable);
}
} else {
logger.debug("Multiple instances for table " + info.getTableName() + " with same primaryKey " + pk + " contained in hierarchy, skipping additional Data!");
}
return contained;
}
public void store(ODSConnection con) throws HistorizationTimeStampCollision, PersistenceLayerException {
try {
for (StorableStructureInformation structureInfo : order) {
List<Storable<?>> objectsToStoreForTable = objectsToStorePerTable.remove(structureInfo.getTableName());
if (objectsToStoreForTable != null && !objectsToStoreForTable.isEmpty()) {
if (structureInfo instanceof XMOMStorableStructureInformation) {
for (Storable<?> rootOrReferenceStorable : objectsToStoreForTable.values()) {
if (con.persistObject(rootOrReferenceStorable)) {
// update-fall
// can happen if the entry did not exist during historization but does now exist
throw new HistorizationTimeStampCollision((XMOMStorableStructureInformation)structureInfo, collisionInformation.get(rootOrReferenceStorable));
}
}
} else {
if (!objectsToStoreForTable.isEmpty()) {
for (Storable<?> objectToStoreForTable : objectsToStoreForTable.values()) {
if (objectToStoreForTable != null) {
con.persistObject(objectToStoreForTable);
}
}
}
}
}
}
} finally {
// there might be a pending retry
objectsToStorePerTable.clear();
collisionInformation.clear();
}
}
}
https://github.com/GIP-SmartMercial/xyna-factory/blob/7d5e3053c6c0e73aba4cc7cf17b2ff2d1824d0d3/server/src/com/gip/xyna/xnwh/persistence/xmom/XMOMPersistenceOperationAlgorithms.java#L2311
If you have a Storable containing a reference to a Storable as list and you store a lot of elements this gets expensive. Storing 160k elements takes about 15 minutes and Xyna spends a lot of its time in this method.
Using a hashtable with the primary key as key instead of a list in https://github.com/GIP-SmartMercial/xyna-factory/blob/7d5e3053c6c0e73aba4cc7cf17b2ff2d1824d0d3/server/src/com/gip/xyna/xnwh/persistence/xmom/XMOMPersistenceOperationAlgorithms.java#L2294 and using containsKey in https://github.com/GIP-SmartMercial/xyna-factory/blob/7d5e3053c6c0e73aba4cc7cf17b2ff2d1824d0d3/server/src/com/gip/xyna/xnwh/persistence/xmom/XMOMPersistenceOperationAlgorithms.java#L2312 should help.