Skip to content

Commit

Permalink
Merge pull request #568 from FgForrest/dev
Browse files Browse the repository at this point in the history
Stability patch (memory leaking fix)
  • Loading branch information
novoj committed May 15, 2024
2 parents 70a13cc + 2a9f019 commit 6c8a352
Show file tree
Hide file tree
Showing 34 changed files with 701 additions and 604 deletions.
187 changes: 134 additions & 53 deletions documentation/user/en/operate/monitor.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions evita_engine/src/main/java/io/evitadb/core/Catalog.java
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ public CatalogContract replace(@Nonnull CatalogSchemaContract updatedSchema, @No
return new Catalog(
catalogVersionAfterRename,
getCatalogState(),
this.catalogIndex,
this.catalogIndex.createCopyForNewCatalogAttachment(),
newCollections,
newIoService,
this,
Expand Down Expand Up @@ -779,7 +779,7 @@ public boolean goLive() {
final Catalog newCatalog = new Catalog(
1L,
CatalogState.ALIVE,
this.catalogIndex,
this.catalogIndex.createCopyForNewCatalogAttachment(),
newCollections,
this.persistenceService,
this,
Expand Down
11 changes: 2 additions & 9 deletions evita_engine/src/main/java/io/evitadb/core/EntityCollection.java
Original file line number Diff line number Diff line change
Expand Up @@ -1207,7 +1207,6 @@ public void attachToCatalog(@Nullable String entityType, @Nonnull Catalog catalo
new EntitySchemaDecorator(catalog::getSchema, this.initialSchema)
);
for (EntityIndex entityIndex : indexes.values()) {
entityIndex.useSchema(this::getInternalSchema);
if (entityIndex instanceof CatalogRelatedDataStructure<?> catalogRelatedEntityIndex) {
catalogRelatedEntityIndex.attachToCatalog(this.entityType, this.catalog);
}
Expand Down Expand Up @@ -1297,7 +1296,6 @@ private TransactionalMap<EntityIndexKey, EntityIndex> loadIndexes(long catalogVe
entityHeader.globalEntityIndexId(),
this.initialSchema
);
globalIndex.useSchema(this::getInternalSchema);
Assert.isPremiseValid(
globalIndex != null,
() -> "Global index must never be null for entity type `" + this.initialSchema.getName() + "`!"
Expand All @@ -1308,11 +1306,7 @@ private TransactionalMap<EntityIndexKey, EntityIndex> loadIndexes(long catalogVe
Stream.of(globalIndex),
entityHeader.usedEntityIndexIds()
.stream()
.map(eid -> {
final EntityIndex entityIndex = this.persistenceService.readEntityIndex(catalogVersion, eid, this.initialSchema);
entityIndex.useSchema(this::getInternalSchema);
return entityIndex;
})
.map(eid -> this.persistenceService.readEntityIndex(catalogVersion, eid, this.initialSchema))
)
.collect(
Collectors.toMap(
Expand Down Expand Up @@ -1656,8 +1650,7 @@ public EntityIndex getOrCreateIndex(@Nonnull EntityIndexKey entityIndexKey) {
}
}

entityIndex.useSchema(EntityCollection.this::getInternalSchema);
if (entityIndex instanceof CatalogRelatedDataStructure lateInitializationIndex) {
if (entityIndex instanceof CatalogRelatedDataStructure<?> lateInitializationIndex) {
lateInitializationIndex.attachToCatalog(EntityCollection.this.entityType, EntityCollection.this.catalog);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1102,14 +1102,15 @@ private void prefetchParents(
new IntHashSet(parentIds.length * 3) : null;

// initialize used data structures
final String entityType = entityCollection.getEntityType();
final EntitySchemaContract entitySchema = entityCollection.getSchema();
final String entityType = entitySchema.getName();
final GlobalEntityIndex globalIndex = entityCollection instanceof EntityCollection ec ?
ec.getGlobalIndex() :
queryContext.getGlobalEntityIndexIfExists(entityType)
.orElseThrow(() -> new CollectionNotFoundException(entityType));
// scope predicate limits the parent traversal
final HierarchyTraversalPredicate scopePredicate = hierarchyContent.getStopAt()
.map(stopAt -> stopAtConstraintToPredicate(TraversalDirection.BOTTOM_UP, stopAt, queryContext, globalIndex, null))
.map(stopAt -> stopAtConstraintToPredicate(TraversalDirection.BOTTOM_UP, stopAt, queryContext, globalIndex, entitySchema, null))
.orElse(HierarchyTraversalPredicate.NEVER_STOP_PREDICATE);

// first, construct EntityReferenceWithParent for each requested parent id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import io.evitadb.api.requestResponse.data.structure.EntityReference;
import io.evitadb.api.requestResponse.extraResult.Hierarchy.LevelInfo;
import io.evitadb.api.requestResponse.extraResult.QueryTelemetry.QueryPhase;
import io.evitadb.api.requestResponse.schema.EntitySchemaContract;
import io.evitadb.api.requestResponse.schema.ReferenceSchemaContract;
import io.evitadb.core.query.AttributeSchemaAccessor;
import io.evitadb.core.query.QueryContext;
Expand Down Expand Up @@ -97,6 +98,7 @@ public static HierarchyTraversalPredicate stopAtConstraintToPredicate(
@Nonnull HierarchyStopAt stopAt,
@Nonnull QueryContext queryContext,
@Nonnull GlobalEntityIndex entityIndex,
@Nonnull EntitySchemaContract entitySchema,
@Nullable ReferenceSchemaContract referenceSchema
) {
final HierarchyStopAtRequireConstraint filter = stopAt.getStopAtDefinition();
Expand All @@ -111,6 +113,7 @@ public static HierarchyTraversalPredicate stopAtConstraintToPredicate(
queryContext,
entityIndex,
node.getFilterBy(),
entitySchema,
referenceSchema
);
} else {
Expand Down Expand Up @@ -152,11 +155,12 @@ protected <T extends EntityIndex> Formula createFilterFormula(
@Nonnull QueryContext queryContext,
@Nonnull FilterBy filterBy,
@Nonnull Class<T> indexType,
@Nonnull EntitySchemaContract targetEntitySchema,
@Nonnull T entityIndex,
@Nonnull AttributeSchemaAccessor attributeSchemaAccessor
) {
try {
final Supplier<String> stepDescriptionSupplier = () -> "Hierarchy statistics of `" + entityIndex.getEntitySchema().getName() + "`: " +
final Supplier<String> stepDescriptionSupplier = () -> "Hierarchy statistics of `" + targetEntitySchema.getName() + "`: " +
Arrays.stream(filterBy.getChildren()).map(Object::toString).collect(Collectors.joining(", "));
queryContext.pushStep(
QueryPhase.PLANNING_FILTER_NESTED_QUERY,
Expand All @@ -175,7 +179,7 @@ protected <T extends EntityIndex> Formula createFilterFormula(
indexType,
Collections.singletonList(entityIndex),
null,
entityIndex.getEntitySchema(),
targetEntitySchema,
null,
null,
null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public ExtraResultProducer apply(HierarchyChildren children, ExtraResultPlanning
final Optional<HierarchyStatistics> statistics = children.getStatistics();
final HierarchyProducerContext context = producer.getContext(children.getName());
final HierarchyTraversalPredicate scopePredicate = children.getStopAt()
.map(it -> stopAtConstraintToPredicate(TraversalDirection.TOP_DOWN, it, context.queryContext(), context.entityIndex(), context.referenceSchema()))
.map(it -> stopAtConstraintToPredicate(TraversalDirection.TOP_DOWN, it, context.queryContext(), context.entityIndex(), context.entitySchema(), context.referenceSchema()))
.orElse(HierarchyTraversalPredicate.NEVER_STOP_PREDICATE);
producer.addComputer(
children.getName(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public ExtraResultProducer apply(HierarchyFromNode fromNode, ExtraResultPlanning
final HierarchyProducerContext context = producer.getContext(fromNode.getName());
final FilterBy fromNodeFilter = fromNode.getFromNode().getFilterBy();
final HierarchyTraversalPredicate scopePredicate = fromNode.getStopAt()
.map(it -> stopAtConstraintToPredicate(TraversalDirection.TOP_DOWN, it, context.queryContext(), context.entityIndex(), context.referenceSchema()))
.map(it -> stopAtConstraintToPredicate(TraversalDirection.TOP_DOWN, it, context.queryContext(), context.entityIndex(), context.entitySchema(), context.referenceSchema()))
.orElse(HierarchyTraversalPredicate.NEVER_STOP_PREDICATE);
producer.addComputer(
fromNode.getName(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public ExtraResultProducer apply(HierarchyFromRoot fromRoot, ExtraResultPlanning
final Optional<HierarchyStatistics> statistics = fromRoot.getStatistics();
final HierarchyProducerContext context = producer.getContext(fromRoot.getName());
final HierarchyTraversalPredicate scopePredicate = fromRoot.getStopAt()
.map(it -> stopAtConstraintToPredicate(TraversalDirection.TOP_DOWN, it, context.queryContext(), context.entityIndex(), context.referenceSchema()))
.map(it -> stopAtConstraintToPredicate(TraversalDirection.TOP_DOWN, it, context.queryContext(), context.entityIndex(), context.entitySchema(), context.referenceSchema()))
.orElse(HierarchyTraversalPredicate.NEVER_STOP_PREDICATE);
producer.addComputer(
fromRoot.getName(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ public ExtraResultProducer apply(HierarchyOfReference hierarchyOfReference, Extr
extraResultPlanner.getQueryContext(),
filter,
ReducedEntityIndex.class,
extraResultPlanner.getSchema(queriedEntityType),
hierarchyIndex,
extraResultPlanner.getAttributeSchemaAccessor()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ public class HierarchyOfSelfTranslator

@Override
public ExtraResultProducer apply(HierarchyOfSelf hierarchyOfSelf, ExtraResultPlanningVisitor extraResultPlanner) {
final String queriedEntityType = extraResultPlanner.getSchema().getName();
final EntitySchemaContract queriedSchema = extraResultPlanner.getSchema();
final String queriedEntityType = queriedSchema.getName();
// verify that requested entityType is hierarchical
final EntitySchemaContract entitySchema = extraResultPlanner.getSchema(queriedEntityType);
Assert.isTrue(
entitySchema.isWithHierarchy(),
queriedSchema.isWithHierarchy(),
() -> new EntityIsNotHierarchicalException(null, queriedEntityType));

// prepare shared data from the context
Expand All @@ -94,14 +94,14 @@ public ExtraResultProducer apply(HierarchyOfSelf hierarchyOfSelf, ExtraResultPla
null,
targetCollectionRef.get(),
queriedEntityType,
() -> "Hierarchy statistics of `" + entitySchema.getName() + "`: " + it
() -> "Hierarchy statistics of `" + queriedEntityType + "`: " + it
)
)
.orElse(null);

// the request is simple - we use global index of current entity
hierarchyStatisticsProducer.interpret(
entitySchema,
queriedSchema,
null,
extraResultPlanner.getAttributeSchemaAccessor(),
hierarchyWithin,
Expand All @@ -125,6 +125,7 @@ public ExtraResultProducer apply(HierarchyOfSelf hierarchyOfSelf, ExtraResultPla
extraResultPlanner.getQueryContext(),
filter,
GlobalEntityIndex.class,
queriedSchema,
globalIndex,
extraResultPlanner.getAttributeSchemaAccessor()
)
Expand All @@ -149,6 +150,7 @@ public ExtraResultProducer apply(HierarchyOfSelf hierarchyOfSelf, ExtraResultPla
extraResultPlanner.getQueryContext(),
filter,
GlobalEntityIndex.class,
queriedSchema,
globalIndex,
extraResultPlanner.getAttributeSchemaAccessor()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public ExtraResultProducer apply(HierarchyParents parents, ExtraResultPlanningVi
final Optional<HierarchyStatistics> statistics = parents.getStatistics();
final HierarchyProducerContext context = producer.getContext(parents.getName());
final HierarchyTraversalPredicate scopePredicate = parents.getStopAt()
.map(it -> stopAtConstraintToPredicate(TraversalDirection.BOTTOM_UP, it, context.queryContext(), context.entityIndex(), context.referenceSchema()))
.map(it -> stopAtConstraintToPredicate(TraversalDirection.BOTTOM_UP, it, context.queryContext(), context.entityIndex(), context.entitySchema(), context.referenceSchema()))
.orElse(HierarchyTraversalPredicate.NEVER_STOP_PREDICATE);
final SiblingsStatisticsTravelingComputer siblingsStatisticsComputer = parents.getSiblings()
.map(
Expand Down Expand Up @@ -121,7 +121,7 @@ private static SiblingsStatisticsTravelingComputer createComputer(
) {
final Optional<HierarchyStatistics> statistics = siblings.getStatistics().or(() -> ofNullable(parentStatistics));
final HierarchyTraversalPredicate scopePredicate = siblings.getStopAt()
.map(it -> stopAtConstraintToPredicate(TraversalDirection.TOP_DOWN, it, context.queryContext(), context.entityIndex(), context.referenceSchema()))
.map(it -> stopAtConstraintToPredicate(TraversalDirection.TOP_DOWN, it, context.queryContext(), context.entityIndex(), context.entitySchema(), context.referenceSchema()))
.orElse((hierarchyNodeId, level, distance) -> distance == 0);
return new SiblingsStatisticsTravelingComputer(
context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public ExtraResultProducer apply(HierarchySiblings siblings, ExtraResultPlanning
final Optional<HierarchyStatistics> statistics = siblings.getStatistics();
final HierarchyProducerContext context = producer.getContext(siblings.getName());
final HierarchyTraversalPredicate scopePredicate = siblings.getStopAt()
.map(it -> stopAtConstraintToPredicate(TraversalDirection.TOP_DOWN, it, context.queryContext(), context.entityIndex(), context.referenceSchema()))
.map(it -> stopAtConstraintToPredicate(TraversalDirection.TOP_DOWN, it, context.queryContext(), context.entityIndex(), context.entitySchema(), context.referenceSchema()))
.orElse(HierarchyTraversalPredicate.ONLY_SELF);
producer.addComputer(
siblings.getName(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ protected List<Accumulator> createStatistics(
context.queryContext(),
context.entityIndex(),
parentId,
context.entitySchema(),
context.referenceSchema()
);
final Bitmap parentId = parentIdPredicate.getFilteringFormula().compute();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ public static Formula createFormulaForTheFilter(
GlobalEntityIndex.class,
Collections.singletonList(entityIndex),
null,
entityIndex.getEntitySchema(),
queryContext.getSchema(entityType),
null,
null,
null,
Expand Down Expand Up @@ -594,7 +594,7 @@ public Formula getReferencedRecordIdFormula(
ReferencedTypeEntityIndex.class,
Collections.singletonList(entityIndex),
ReferenceContent.ALL_REFERENCES,
entityIndex.getEntitySchema(),
entitySchema,
referenceSchema,
null, null,
getProcessingScope().withReferenceSchemaAccessor(referenceSchema.getName()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ public static Formula createFormulaFromHierarchyIndex(
),
hierarchyWithin.isDirectRelation(),
hierarchyWithin.isExcludingRoot(),
targetEntitySchema,
targetEntityIndex,
queryContext
)
Expand All @@ -144,12 +145,13 @@ private static Formula createFormulaFromHierarchyIndex(
@Nullable HierarchyFilteringPredicate excludedChildren,
boolean directRelation,
boolean excludingRoot,
@Nonnull EntitySchemaContract targetEntitySchema,
@Nonnull EntityIndex entityIndex,
@Nonnull QueryContext queryContext
) {
if (directRelation) {
// if the hierarchy entity is the same as queried entity
if (Objects.equals(queryContext.getSchema().getName(), entityIndex.getEntitySchema().getName())) {
if (Objects.equals(queryContext.getSchema().getName(), targetEntitySchema.getName())) {
if (excludedChildren == null) {
return entityIndex.getHierarchyNodesForParentFormula(parentId);
} else {
Expand Down
19 changes: 17 additions & 2 deletions evita_engine/src/main/java/io/evitadb/index/CatalogIndex.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import static io.evitadb.core.Transaction.isTransactionAvailable;
import static io.evitadb.index.attribute.AttributeIndex.verifyLocalizedAttribute;
Expand Down Expand Up @@ -115,14 +116,27 @@ private CatalogIndex(int version, @Nonnull TransactionalMap<AttributeKey, Global

@Override
public void attachToCatalog(@Nullable String entityType, @Nonnull Catalog catalog) {
Assert.isPremiseValid(this.catalog == null, "Catalog was already attached to this index!");
this.catalog = catalog;
for (GlobalUniqueIndex globalUniqueIndex : uniqueIndex.values()) {
globalUniqueIndex.attachToCatalog(null, catalog);
}
}

@Nonnull
@Override
public CatalogIndex createCopyForNewCatalogAttachment() {
return new CatalogIndex(
this.version, this.uniqueIndex
this.version,
this.uniqueIndex
.entrySet()
.stream()
.collect(
Collectors.toMap(
Entry::getKey,
entry -> entry.getValue().createCopyForNewCatalogAttachment()
)
)
);
}

Expand Down Expand Up @@ -162,7 +176,8 @@ public void insertUniqueAttribute(
final GlobalUniqueIndex theUniqueIndex = this.uniqueIndex.computeIfAbsent(
createAttributeKey(attributeSchema, allowedLocales, locale, value),
lookupKey -> {
final GlobalUniqueIndex newUniqueIndex = new GlobalUniqueIndex(lookupKey, attributeSchema.getType(), catalog);
final GlobalUniqueIndex newUniqueIndex = new GlobalUniqueIndex(lookupKey, attributeSchema.getType());
newUniqueIndex.attachToCatalog(null, catalog);
ofNullable(Transaction.getOrCreateTransactionalMemoryLayer(this))
.ifPresent(it -> it.addCreatedItem(newUniqueIndex));
this.dirty.setToTrue();
Expand Down
Loading

0 comments on commit 6c8a352

Please sign in to comment.