Example #1
0
 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);
     }
 }
Example #2
0
        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);
        }
Example #3
0
        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));
        }
Example #4
0
        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);
        }
Example #5
0
 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();
             }
         }
     }
 }
Example #6
0
        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++;
                }
            }
        }
Example #7
0
        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);
        }
Example #9
0
        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);
        }