public override void CheckReference(RECORD record, PropertyRecord property, CheckerEngine <RECORD, REPORT> engine, RecordAccess records) { if (!property.InUse()) { engine.Report().propertyNotInUse(property); } else { if (!Record.NO_PREVIOUS_PROPERTY.@is(property.PrevProp)) { engine.Report().propertyNotFirstInChain(property); } (new ChainCheck <RECORD, REPORT>()).CheckReference(record, property, engine, records); } }
private static long CalculateNumberOfProperties(NeoStores stores) { long count = 0; PropertyRecord record = stores.PropertyStore.newRecord(); using (PageCursor cursor = stores.PropertyStore.openPageCursorForReading(0)) { long highId = stores.PropertyStore.HighId; for (long id = 0; id < highId; id++) { stores.PropertyStore.getRecordByCursor(id, record, CHECK, cursor); if (record.InUse()) { count += count(record); } } } return(count); }
private void UnlinkPropertyRecord <P>(PropertyRecord propRecord, RecordAccess <PropertyRecord, PrimitiveRecord> propertyRecords, RecordAccess_RecordProxy <P, Void> primitiveRecordChange) where P : Org.Neo4j.Kernel.impl.store.record.PrimitiveRecord { P primitive = primitiveRecordChange.ForReadingLinkage(); Debug.Assert(_traverser.assertPropertyChain(primitive, propertyRecords)); Debug.Assert(propRecord.Size() == 0); long prevProp = propRecord.PrevProp; long nextProp = propRecord.NextProp; if (primitive.NextProp == propRecord.Id) { Debug.Assert(propRecord.PrevProp == Record.NO_PREVIOUS_PROPERTY.intValue(), propRecord + " for "); +primitive; primitiveRecordChange.ForChangingLinkage().NextProp = nextProp; } if (prevProp != Record.NO_PREVIOUS_PROPERTY.intValue()) { PropertyRecord prevPropRecord = propertyRecords.GetOrLoad(prevProp, primitive).forChangingLinkage(); Debug.Assert(prevPropRecord.InUse(), prevPropRecord + "->" + propRecord + " for " + primitive); prevPropRecord.NextProp = nextProp; prevPropRecord.Changed = primitive; } if (nextProp != Record.NO_NEXT_PROPERTY.intValue()) { PropertyRecord nextPropRecord = propertyRecords.GetOrLoad(nextProp, primitive).forChangingLinkage(); Debug.Assert(nextPropRecord.InUse(), propRecord + "->" + nextPropRecord + " for " + primitive); nextPropRecord.PrevProp = prevProp; nextPropRecord.Changed = primitive; } propRecord.InUse = false; /* * The following two are not needed - the above line does all the work (PropertyStore * does not write out the prev/next for !inUse records). It is nice to set this * however to check for consistency when assertPropertyChain(). */ propRecord.PrevProp = Record.NO_PREVIOUS_PROPERTY.intValue(); propRecord.NextProp = Record.NO_NEXT_PROPERTY.intValue(); propRecord.Changed = primitive; Debug.Assert(_traverser.assertPropertyChain(primitive, propertyRecords)); }
public virtual bool AssertPropertyChain(PrimitiveRecord primitive, RecordAccess <PropertyRecord, PrimitiveRecord> propertyRecords) { IList <PropertyRecord> toCheck = new LinkedList <PropertyRecord>(); long nextIdToFetch = primitive.NextProp; while (nextIdToFetch != Record.NO_NEXT_PROPERTY.intValue()) { PropertyRecord propRecord = propertyRecords.GetOrLoad(nextIdToFetch, primitive).forReadingLinkage(); toCheck.Add(propRecord); Debug.Assert(propRecord.InUse(), primitive + "->"); +Arrays.ToString(toCheck.ToArray()); Debug.Assert(propRecord.Size() <= PropertyType.PayloadSize, propRecord + " size " + propRecord.Size()); nextIdToFetch = propRecord.NextProp; } if (toCheck.Count == 0) { Debug.Assert(primitive.NextProp == Record.NO_NEXT_PROPERTY.intValue(), primitive); return(true); } PropertyRecord first = toCheck[0]; PropertyRecord last = toCheck[toCheck.Count - 1]; Debug.Assert(first.PrevProp == Record.NO_PREVIOUS_PROPERTY.intValue(), primitive + "->"); +Arrays.ToString(toCheck.ToArray()); Debug.Assert(last.NextProp == Record.NO_NEXT_PROPERTY.intValue(), primitive + "->"); +Arrays.ToString(toCheck.ToArray()); PropertyRecord current; PropertyRecord previous = first; for (int i = 1; i < toCheck.Count; i++) { current = toCheck[i]; Debug.Assert(current.PrevProp == previous.Id, primitive + "->"); +Arrays.ToString(toCheck.ToArray()); Debug.Assert(previous.NextProp == current.Id, primitive + "->"); +Arrays.ToString(toCheck.ToArray()); previous = current; } return(true); }
private void CheckChainItem(PropertyRecord property, CheckerEngine <RECORD, REPORT> engine, MutableIntSet keys, MandatoryProperties.Check <RECORD, REPORT> mandatory) { if (!property.InUse()) { engine.Report().propertyNotInUse(property); } else { int[] keysInRecord = ChainCheck.Keys(property); if (mandatory != null) { mandatory.Receive(keysInRecord); } foreach (int key in keysInRecord) { if (!keys.add(key)) { engine.Report().propertyKeyNotUniqueInChain(); } } } }
protected internal override void Process() { NodeRecord nodeRecord = _nodeStore.newRecord(); PropertyRecord propertyRecord = _propertyStore.newRecord(); using (PageCursor cursor = _nodeStore.openPageCursorForReading(0), PageCursor propertyCursor = _propertyStore.openPageCursorForReading(0)) { while (_nodeIds.hasNext()) { long duplicateNodeId = _nodeIds.next(); _nodeStore.getRecordByCursor(duplicateNodeId, nodeRecord, NORMAL, cursor); Debug.Assert(nodeRecord.InUse(), nodeRecord); // Ensure heavy so that the dynamic label records gets loaded (and then deleted) too _nodeStore.ensureHeavy(nodeRecord); // Delete property records long nextProp = nodeRecord.NextProp; while (!Record.NULL_REFERENCE.@is(nextProp)) { _propertyStore.getRecordByCursor(nextProp, propertyRecord, NORMAL, propertyCursor); Debug.Assert(propertyRecord.InUse(), propertyRecord + " for " + nodeRecord); _propertyStore.ensureHeavy(propertyRecord); _propertiesRemoved += propertyRecord.NumberOfProperties(); nextProp = propertyRecord.NextProp; deletePropertyRecordIncludingValueRecords(propertyRecord); _propertyStore.updateRecord(propertyRecord); } // Delete node (and dynamic label records, if any) nodeRecord.InUse = false; foreach (DynamicRecord labelRecord in nodeRecord.DynamicLabelRecords) { labelRecord.InUse = false; } _nodeStore.updateRecord(nodeRecord); _nodesRemoved++; } } }
private void RemoveProperty <P>(RecordAccess_RecordProxy <P, Void> primitiveProxy, int propertyKey, RecordAccess <PropertyRecord, PrimitiveRecord> propertyRecords, PrimitiveRecord primitive, long propertyId) where P : Org.Neo4j.Kernel.impl.store.record.PrimitiveRecord { RecordAccess_RecordProxy <PropertyRecord, PrimitiveRecord> recordChange = propertyRecords.GetOrLoad(propertyId, primitive); PropertyRecord propRecord = recordChange.ForChangingData(); if (!propRecord.InUse()) { throw new System.InvalidOperationException("Unable to delete property[" + propertyId + "] since it is already deleted."); } PropertyBlock block = propRecord.RemovePropertyBlock(propertyKey); if (block == null) { throw new System.InvalidOperationException("Property with index[" + propertyKey + "] is not present in property[" + propertyId + "]"); } foreach (DynamicRecord valueRecord in block.ValueRecords) { Debug.Assert(valueRecord.InUse()); valueRecord.SetInUse(false, block.Type.intValue()); propRecord.AddDeletedRecord(valueRecord); } if (propRecord.Size() > 0) { /* * There are remaining blocks in the record. We do not unlink yet. */ propRecord.Changed = primitive; Debug.Assert(_traverser.assertPropertyChain(primitive, propertyRecords)); } else { UnlinkPropertyRecord(propRecord, propertyRecords, primitiveProxy); } }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: private org.neo4j.kernel.impl.store.record.PropertyRecord readPropertyRecord(long id, org.neo4j.storageengine.api.ReadableChannel channel) throws java.io.IOException private PropertyRecord ReadPropertyRecord(long id, ReadableChannel channel) { // in_use(byte)+type(int)+key_indexId(int)+prop_blockId(long)+ // prev_prop_id(long)+next_prop_id(long) PropertyRecord record = new PropertyRecord(id); sbyte flags = channel.Get(); // 1 bool inUse = bitFlag(flags, Record.IN_USE.byteValue()); bool nodeProperty = !bitFlag(flags, Record.REL_PROPERTY.byteValue()); bool requireSecondaryUnit = bitFlag(flags, Record.REQUIRE_SECONDARY_UNIT); bool hasSecondaryUnit = bitFlag(flags, Record.HAS_SECONDARY_UNIT); bool usesFixedReferenceFormat = bitFlag(flags, Record.USES_FIXED_REFERENCE_FORMAT); record.RequiresSecondaryUnit = requireSecondaryUnit; record.UseFixedReferences = usesFixedReferenceFormat; long nextProp = channel.Long; // 8 long prevProp = channel.Long; // 8 record.NextProp = nextProp; record.PrevProp = prevProp; long primitiveId = channel.Long; // 8 if (primitiveId != -1 && nodeProperty) { record.NodeId = primitiveId; } else if (primitiveId != -1) { record.RelId = primitiveId; } if (hasSecondaryUnit) { record.SecondaryUnitId = channel.Long; } int nrPropBlocks = channel.Get(); Debug.Assert(nrPropBlocks >= 0); if (nrPropBlocks > 0) { record.InUse = true; } while (nrPropBlocks-- > 0) { PropertyBlock block = ReadPropertyBlock(channel); if (block == null) { return(null); } record.AddPropertyBlock(block); } int deletedRecords = ReadDynamicRecords(channel, record, PROPERTY_DELETED_DYNAMIC_RECORD_ADDER); if (deletedRecords == -1) { return(null); } Debug.Assert(deletedRecords >= 0); while (deletedRecords-- > 0) { DynamicRecord read = ReadDynamicRecord(channel); if (read == null) { return(null); } record.AddDeletedRecord(read); } if ((inUse && !record.InUse()) || (!inUse && record.InUse())) { throw new System.InvalidOperationException("Weird, inUse was read in as " + inUse + " but the record is " + record); } return(record); }
public virtual void PrimitiveSetProperty <P>(RecordAccess_RecordProxy <P, Void> primitiveRecordChange, int propertyKey, Value value, RecordAccess <PropertyRecord, PrimitiveRecord> propertyRecords) where P : Org.Neo4j.Kernel.impl.store.record.PrimitiveRecord { PropertyBlock block = EncodePropertyValue(propertyKey, value); P primitive = primitiveRecordChange.ForReadingLinkage(); Debug.Assert(_traverser.assertPropertyChain(primitive, propertyRecords)); int newBlockSizeInBytes = block.Size; // Traverse the existing property chain. Tracking two things along the way: // - (a) Free space for this block (candidateHost) // - (b) Existence of a block with the property key // Chain traversal can be aborted only if: // - (1) (b) occurs and new property block fits where the current is // - (2) (a) occurs and (b) has occurred, but new property block didn't fit // - (3) (b) occurs and (a) has occurred // - (4) Chain ends RecordAccess_RecordProxy <PropertyRecord, PrimitiveRecord> freeHostProxy = null; RecordAccess_RecordProxy <PropertyRecord, PrimitiveRecord> existingHostProxy = null; long prop = primitive.NextProp; while (prop != Record.NO_NEXT_PROPERTY.intValue()) // <-- (4) { RecordAccess_RecordProxy <PropertyRecord, PrimitiveRecord> proxy = propertyRecords.GetOrLoad(prop, primitive); PropertyRecord propRecord = proxy.ForReadingLinkage(); Debug.Assert(propRecord.InUse(), propRecord); // (a) search for free space if (PropertyFitsInside(newBlockSizeInBytes, propRecord)) { freeHostProxy = proxy; if (existingHostProxy != null) { // (2) PropertyRecord freeHost = proxy.ForChangingData(); freeHost.AddPropertyBlock(block); freeHost.Changed = primitive; Debug.Assert(_traverser.assertPropertyChain(primitive, propertyRecords)); return; } } // (b) search for existence of property key PropertyBlock existingBlock = propRecord.GetPropertyBlock(propertyKey); if (existingBlock != null) { // We found an existing property and whatever happens we have to remove the existing // block so that we can add the new one, where ever we decide to place it existingHostProxy = proxy; PropertyRecord existingHost = existingHostProxy.ForChangingData(); RemoveProperty(primitive, existingHost, existingBlock); // Now see if we at this point can add the new block if (newBlockSizeInBytes <= existingBlock.Size || PropertyFitsInside(newBlockSizeInBytes, existingHost)) // fallback check { // (1) yes we could add it right into the host of the existing block existingHost.AddPropertyBlock(block); Debug.Assert(_traverser.assertPropertyChain(primitive, propertyRecords)); return; } else if (freeHostProxy != null) { // (3) yes we could add it to a previously found host with sufficiently free space in it PropertyRecord freeHost = freeHostProxy.ForChangingData(); freeHost.AddPropertyBlock(block); freeHost.Changed = primitive; Debug.Assert(_traverser.assertPropertyChain(primitive, propertyRecords)); return; } // else we can't add it at this point } // Continue down the chain prop = propRecord.NextProp; } // At this point we haven't added the property block, although we may have found room for it // along the way. If we didn't then just create a new record, it's fine PropertyRecord freeHost; if (freeHostProxy == null) { // We couldn't find free space along the way, so create a new host record freeHost = propertyRecords.Create(_propertyRecordIdGenerator.nextId(), primitive).forChangingData(); freeHost.InUse = true; if (primitive.NextProp != Record.NO_NEXT_PROPERTY.intValue()) { // This isn't the first property record for the entity, re-shuffle the first one so that // the new one becomes the first PropertyRecord prevProp = propertyRecords.GetOrLoad(primitive.NextProp, primitive).forChangingLinkage(); Debug.Assert(prevProp.PrevProp == Record.NO_PREVIOUS_PROPERTY.intValue()); prevProp.PrevProp = freeHost.Id; freeHost.NextProp = prevProp.Id; prevProp.Changed = primitive; } // By the way, this is the only condition where the primitive record also needs to change primitiveRecordChange.ForChangingLinkage().NextProp = freeHost.Id; } else { freeHost = freeHostProxy.ForChangingData(); } // At this point we know that we have a host record with sufficient space in it for the block // to add, so simply add it freeHost.AddPropertyBlock(block); Debug.Assert(_traverser.assertPropertyChain(primitive, propertyRecords)); }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: private org.neo4j.kernel.impl.store.record.PropertyRecord readPropertyRecord(long id, org.neo4j.storageengine.api.ReadableChannel channel) throws java.io.IOException private PropertyRecord ReadPropertyRecord(long id, ReadableChannel channel) { // in_use(byte)+type(int)+key_indexId(int)+prop_blockId(long)+ // prev_prop_id(long)+next_prop_id(long) PropertyRecord record = new PropertyRecord(id); sbyte inUseFlag = channel.Get(); // 1 long nextProp = channel.Long; // 8 long prevProp = channel.Long; // 8 record.NextProp = nextProp; record.PrevProp = prevProp; bool inUse = false; if ((inUseFlag & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue()) { inUse = true; } bool nodeProperty = true; if ((inUseFlag & Record.REL_PROPERTY.byteValue()) == Record.REL_PROPERTY.byteValue()) { nodeProperty = false; } long primitiveId = channel.Long; // 8 if (primitiveId != -1 && nodeProperty) { record.NodeId = primitiveId; } else if (primitiveId != -1) { record.RelId = primitiveId; } int nrPropBlocks = channel.Get(); Debug.Assert(nrPropBlocks >= 0); if (nrPropBlocks > 0) { record.InUse = true; } while (nrPropBlocks-- > 0) { PropertyBlock block = ReadPropertyBlock(channel); if (block == null) { return(null); } record.AddPropertyBlock(block); } int deletedRecords = ReadDynamicRecords(channel, record, PROPERTY_DELETED_DYNAMIC_RECORD_ADDER); if (deletedRecords == -1) { return(null); } Debug.Assert(deletedRecords >= 0); while (deletedRecords-- > 0) { DynamicRecord read = ReadDynamicRecord(channel); if (read == null) { return(null); } record.AddDeletedRecord(read); } if ((inUse && !record.InUse()) || (!inUse && record.InUse())) { throw new System.InvalidOperationException("Weird, inUse was read in as " + inUse + " but the record is " + record); } return(record); }