use of org.neo4j.memory.MemoryTracker in project neo4j by neo4j.
the class IndexTxStateUpdater method onPropertyChange.
private void onPropertyChange(EntityCursor entity, PropertyCursor propertyCursor, long[] tokens, int propertyKeyId, int[] existingPropertyKeyIds, Value beforeValue, Value afterValue) {
assert noSchemaChangedInTx();
Collection<IndexDescriptor> indexes = storageReader.valueIndexesGetRelated(tokens, propertyKeyId, entity.entityType());
if (!indexes.isEmpty()) {
MutableIntObjectMap<Value> materializedProperties = IntObjectMaps.mutable.empty();
SchemaMatcher.onMatchingSchema(indexes.iterator(), propertyKeyId, existingPropertyKeyIds, index -> {
MemoryTracker memoryTracker = read.txState().memoryTracker();
SchemaDescriptor schema = index.schema();
int[] propertyIds = schema.getPropertyIds();
Value[] valuesAfter = getValueTuple(entity, propertyCursor, propertyKeyId, afterValue, propertyIds, materializedProperties, memoryTracker);
// The valuesBefore tuple is just like valuesAfter, except is has the afterValue instead of the beforeValue
Value[] valuesBefore = Arrays.copyOf(valuesAfter, valuesAfter.length);
int k = ArrayUtils.indexOf(propertyIds, propertyKeyId);
valuesBefore[k] = beforeValue;
indexingService.validateBeforeCommit(index, valuesAfter, entity.reference());
ValueTuple valuesTupleBefore = ValueTuple.of(valuesBefore);
ValueTuple valuesTupleAfter = ValueTuple.of(valuesAfter);
// They are copies and same shallow size
memoryTracker.allocateHeap(valuesTupleBefore.getShallowSize() * 2);
read.txState().indexDoUpdateEntry(schema, entity.reference(), valuesTupleBefore, valuesTupleAfter);
});
}
}
use of org.neo4j.memory.MemoryTracker in project neo4j by neo4j.
the class IndexTxStateUpdater method onPropertyAdd.
private void onPropertyAdd(EntityCursor entity, PropertyCursor propertyCursor, long[] tokens, int propertyKeyId, int[] existingPropertyKeyIds, Value value) {
assert noSchemaChangedInTx();
Collection<IndexDescriptor> indexes = storageReader.valueIndexesGetRelated(tokens, propertyKeyId, entity.entityType());
if (!indexes.isEmpty()) {
MutableIntObjectMap<Value> materializedProperties = IntObjectMaps.mutable.empty();
SchemaMatcher.onMatchingSchema(indexes.iterator(), propertyKeyId, existingPropertyKeyIds, index -> {
MemoryTracker memoryTracker = read.txState().memoryTracker();
SchemaDescriptor schema = index.schema();
Value[] values = getValueTuple(entity, propertyCursor, propertyKeyId, value, schema.getPropertyIds(), materializedProperties, memoryTracker);
indexingService.validateBeforeCommit(index, values, entity.reference());
ValueTuple valueTuple = ValueTuple.of(values);
memoryTracker.allocateHeap(valueTuple.getShallowSize());
read.txState().indexDoUpdateEntry(schema, entity.reference(), null, valueTuple);
});
}
}
use of org.neo4j.memory.MemoryTracker in project neo4j by neo4j.
the class IndexTxStateUpdater method onPropertyRemove.
private void onPropertyRemove(EntityCursor entity, PropertyCursor propertyCursor, long[] tokens, int propertyKeyId, int[] existingPropertyKeyIds, Value value) {
assert noSchemaChangedInTx();
Collection<IndexDescriptor> indexes = storageReader.valueIndexesGetRelated(tokens, propertyKeyId, entity.entityType());
if (!indexes.isEmpty()) {
MutableIntObjectMap<Value> materializedProperties = IntObjectMaps.mutable.empty();
SchemaMatcher.onMatchingSchema(indexes.iterator(), propertyKeyId, existingPropertyKeyIds, index -> {
MemoryTracker memoryTracker = read.txState().memoryTracker();
SchemaDescriptor schema = index.schema();
Value[] values = getValueTuple(entity, propertyCursor, propertyKeyId, value, schema.getPropertyIds(), materializedProperties, memoryTracker);
ValueTuple valueTuple = ValueTuple.of(values);
memoryTracker.allocateHeap(valueTuple.getShallowSize());
read.txState().indexDoUpdateEntry(schema, entity.reference(), valueTuple, null);
});
}
}
use of org.neo4j.memory.MemoryTracker in project neo4j by neo4j.
the class MutableLinearProbeLongHashSetTest method allocateFreeMemory.
@Test
void allocateFreeMemory() {
final MemoryTracker memoryTrackerSpy = spy(new LocalMemoryTracker());
final MutableLinearProbeLongHashSet set2 = new MutableLinearProbeLongHashSet(new OffHeapMemoryAllocator(blockAllocator), memoryTrackerSpy);
verify(memoryTrackerSpy).allocateNative(anyLong());
for (int i = 0; i < DEFAULT_CAPACITY; i++) {
set2.add(100 + i);
}
verify(memoryTrackerSpy).releaseNative(anyLong());
verify(memoryTrackerSpy, times(2)).allocateNative(anyLong());
set2.close();
verify(memoryTrackerSpy, times(2)).releaseNative(anyLong());
}
use of org.neo4j.memory.MemoryTracker in project neo4j by neo4j.
the class RelationshipLockHelper method lockMultipleRelationships.
private static void lockMultipleRelationships(RelationshipModifications.RelationshipBatch ids, long optionalFirstInChain, RecordAccess<RelationshipRecord, Void> relRecords, ResourceLocker locks, CursorContext cursorContext, MemoryTracker memoryTracker) {
/*
* The idea here is to take all locks in sorted order to avoid deadlocks
* We start locking by optimistic reading of relationship neighbours
* Once all neighbours plus the relationship itself is locked, we verify if there are changes.
* If not -> then just continue
* Changes means we need to rewind and unlock, to get the new changes in correct order
*/
int upperLimitOfLocks = ids.size() * 5 + /* self and 4 neighbours */
1;
try (MemoryTracker scopedMemoryTracker = memoryTracker.getScopedMemoryTracker()) {
HeapTrackingLongObjectHashMap<RelationshipRecord> optimistic = HeapTrackingCollections.newLongObjectMap(scopedMemoryTracker);
scopedMemoryTracker.allocateHeap(sizeOfLongArray(upperLimitOfLocks));
// First will build the list of locks we need
SortedLockList lockList = new SortedLockList(upperLimitOfLocks);
// The locklist does not accept NULL(-1) values, so we don't need to care about that
lockList.add(optionalFirstInChain);
ids.forEach((id, type, startNode, endNode) -> {
RelationshipRecord relationship = relRecords.getOrLoad(id, null, cursorContext).forReadingLinkage();
optimistic.put(id, relationship);
lockList.add(relationship.getId());
lockList.add(START_NEXT.get(relationship));
lockList.add(START_PREV.get(relationship));
lockList.add(END_NEXT.get(relationship));
lockList.add(END_PREV.get(relationship));
});
// Then we start traversing and locking
while (lockList.nextUnique()) {
long id = lockList.currentHighestLockedId();
// This could be either a relationship we're deleting, a neighbour or the first-in-chain. They all needs to be locked
locks.acquireExclusive(NONE, RELATIONSHIP, id);
RelationshipRecord old = optimistic.get(id);
if (old != null) {
// This is a relationship we we're deleting
// No when it is locked we can check if the optimistic read is stable
RelationshipRecord actual = relRecords.getOrLoad(id, null, cursorContext).forReadingLinkage();
if (recordHasLinkageChanges(old, actual)) {
// Something changed, so we need to retry, by unlocking and trying again
rewindAndUnlockChanged(locks, lockList, old, actual);
optimistic.put(id, actual);
}
}
}
}
}
Aggregations