Search in sources :

Example 46 with PropertyBlock

use of org.neo4j.kernel.impl.store.record.PropertyBlock in project neo4j by neo4j.

the class PropertyCreator method primitiveSetProperty.

public <P extends PrimitiveRecord> void primitiveSetProperty(RecordProxy<Long, P, Void> primitiveRecordChange, int propertyKey, Object value, RecordAccess<Long, PropertyRecord, PrimitiveRecord> propertyRecords) {
    PropertyBlock block = encodePropertyValue(propertyKey, value);
    P primitive = primitiveRecordChange.forReadingLinkage();
    assert traverser.assertPropertyChain(primitive, propertyRecords);
    int newBlockSizeInBytes = block.getSize();
    // 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
    RecordProxy<Long, PropertyRecord, PrimitiveRecord> freeHostProxy = null;
    RecordProxy<Long, PropertyRecord, PrimitiveRecord> existingHostProxy = null;
    long prop = primitive.getNextProp();
    while (// <-- (4)
    prop != Record.NO_NEXT_PROPERTY.intValue()) {
        RecordProxy<Long, PropertyRecord, PrimitiveRecord> proxy = propertyRecords.getOrLoad(prop, primitive);
        PropertyRecord propRecord = proxy.forReadingLinkage();
        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.setChanged(primitive);
                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 (// cheap check
            newBlockSizeInBytes <= existingBlock.getSize() || // fallback check
            propertyFitsInside(newBlockSizeInBytes, existingHost)) {
                // (1) yes we could add it right into the host of the existing block
                existingHost.addPropertyBlock(block);
                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.setChanged(primitive);
                assert traverser.assertPropertyChain(primitive, propertyRecords);
                return;
            }
        // else we can't add it at this point
        }
        // Continue down the chain
        prop = propRecord.getNextProp();
    }
    // 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 = null;
    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.setInUse(true);
        if (primitive.getNextProp() != 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.getNextProp(), primitive).forChangingLinkage();
            assert prevProp.getPrevProp() == Record.NO_PREVIOUS_PROPERTY.intValue();
            prevProp.setPrevProp(freeHost.getId());
            freeHost.setNextProp(prevProp.getId());
            prevProp.setChanged(primitive);
        }
        // By the way, this is the only condition where the primitive record also needs to change
        primitiveRecordChange.forChangingLinkage().setNextProp(freeHost.getId());
    } 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);
    assert traverser.assertPropertyChain(primitive, propertyRecords);
}
Also used : PropertyRecord(org.neo4j.kernel.impl.store.record.PropertyRecord) PropertyBlock(org.neo4j.kernel.impl.store.record.PropertyBlock) PrimitiveRecord(org.neo4j.kernel.impl.store.record.PrimitiveRecord)

Example 47 with PropertyBlock

use of org.neo4j.kernel.impl.store.record.PropertyBlock in project neo4j by neo4j.

the class PhysicalLogCommandReaderV2_2 method readPropertyBlock.

private PropertyBlock readPropertyBlock(ReadableChannel channel) throws IOException {
    PropertyBlock toReturn = new PropertyBlock();
    // the size is stored in bytes // 1
    byte blockSize = channel.get();
    assert blockSize > 0 && blockSize % 8 == 0 : blockSize + " is not a valid block size value";
    // Read in blocks
    long[] blocks = readLongs(channel, blockSize / 8);
    assert blocks.length == blockSize / 8 : blocks.length + " longs were read in while i asked for what corresponds to " + blockSize;
    assert PropertyType.getPropertyTypeOrThrow(blocks[0]).calculateNumberOfBlocksUsed(blocks[0]) == blocks.length : blocks.length + " is not a valid number of blocks for type " + PropertyType.getPropertyTypeOrThrow(blocks[0]);
    /*
         *  Ok, now we may be ready to return, if there are no DynamicRecords. So
         *  we start building the Object
         */
    toReturn.setValueBlocks(blocks);
    /*
         * Read in existence of DynamicRecords. Remember, this has already been
         * read in the buffer with the blocks, above.
         */
    if (readDynamicRecords(channel, toReturn, PROPERTY_BLOCK_DYNAMIC_RECORD_ADDER) == -1) {
        return null;
    }
    return toReturn;
}
Also used : PropertyBlock(org.neo4j.kernel.impl.store.record.PropertyBlock)

Example 48 with PropertyBlock

use of org.neo4j.kernel.impl.store.record.PropertyBlock in project neo4j by neo4j.

the class PhysicalLogCommandReaderV3_0 method readPropertyRecord.

private PropertyRecord readPropertyRecord(long id, ReadableChannel channel) throws IOException {
    // in_use(byte)+type(int)+key_indexId(int)+prop_blockId(long)+
    // prev_prop_id(long)+next_prop_id(long)
    PropertyRecord record = new PropertyRecord(id);
    // 1
    byte flags = channel.get();
    boolean inUse = bitFlag(flags, Record.IN_USE.byteValue());
    boolean nodeProperty = !bitFlag(flags, Record.REL_PROPERTY.byteValue());
    boolean requireSecondaryUnit = bitFlag(flags, Record.REQUIRE_SECONDARY_UNIT);
    boolean hasSecondaryUnit = bitFlag(flags, Record.HAS_SECONDARY_UNIT);
    record.setRequiresSecondaryUnit(requireSecondaryUnit);
    // 8
    long nextProp = channel.getLong();
    // 8
    long prevProp = channel.getLong();
    record.setNextProp(nextProp);
    record.setPrevProp(prevProp);
    // 8
    long primitiveId = channel.getLong();
    if (primitiveId != -1 && nodeProperty) {
        record.setNodeId(primitiveId);
    } else if (primitiveId != -1) {
        record.setRelId(primitiveId);
    }
    if (hasSecondaryUnit) {
        record.setSecondaryUnitId(channel.getLong());
    }
    int nrPropBlocks = channel.get();
    assert nrPropBlocks >= 0;
    if (nrPropBlocks > 0) {
        record.setInUse(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;
    }
    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 IllegalStateException("Weird, inUse was read in as " + inUse + " but the record is " + record);
    }
    return record;
}
Also used : DynamicRecord(org.neo4j.kernel.impl.store.record.DynamicRecord) PropertyRecord(org.neo4j.kernel.impl.store.record.PropertyRecord) PropertyBlock(org.neo4j.kernel.impl.store.record.PropertyBlock)

Example 49 with PropertyBlock

use of org.neo4j.kernel.impl.store.record.PropertyBlock in project neo4j by neo4j.

the class EntityStoreUpdaterStep method reassignDynamicRecordIds.

static void reassignDynamicRecordIds(PropertyStore propertyStore, PropertyBlock[] blocks, int offset, int length) {
    // where we know we have a single thread doing this.
    for (int i = 0; i < length; i++) {
        PropertyBlock block = blocks[offset + i];
        PropertyType type = block.getType();
        switch(type) {
            case STRING:
                reassignDynamicRecordIds(block, type, propertyStore.getStringStore());
                break;
            case ARRAY:
                reassignDynamicRecordIds(block, type, propertyStore.getArrayStore());
                break;
            // No need to do anything be default, we only need to relink for dynamic records
            default:
        }
    }
}
Also used : PropertyBlock(org.neo4j.kernel.impl.store.record.PropertyBlock) PropertyType(org.neo4j.kernel.impl.store.PropertyType)

Example 50 with PropertyBlock

use of org.neo4j.kernel.impl.store.record.PropertyBlock in project neo4j by neo4j.

the class PropertyEncoderStep method process.

@Override
protected void process(Batch<INPUT, RECORD> batch, BatchSender sender) {
    RelativeIdRecordAllocator stringAllocator = new RelativeIdRecordAllocator(stringDataSize);
    RelativeIdRecordAllocator arrayAllocator = new RelativeIdRecordAllocator(arrayDataSize);
    PropertyCreator propertyCreator = new PropertyCreator(stringAllocator, arrayAllocator, null, null);
    int blockCountGuess = (int) averageBlocksPerBatch.average();
    PropertyBlock[] propertyBlocks = new PropertyBlock[blockCountGuess == 0 ? batch.input.length : blockCountGuess + batch.input.length / 20];
    int blockCursor = 0;
    int[] lengths = new int[batch.input.length];
    for (int i = 0; i < batch.input.length; i++) {
        stringAllocator.initialize();
        arrayAllocator.initialize();
        INPUT input = batch.input[i];
        if (!input.hasFirstPropertyId()) {
            // Encode the properties and attach the blocks to the BatchEntity.
            // Dynamic records for each entity will start from 0, they will be reassigned later anyway
            int count = input.properties().length >> 1;
            if (blockCursor + count > propertyBlocks.length) {
                propertyBlocks = copyOf(propertyBlocks, max(propertyBlocks.length << 1, blockCursor + count));
            }
            propertyKeyHolder.propertyKeysAndValues(propertyBlocks, blockCursor, input.properties(), propertyCreator);
            lengths[i] = count;
            blockCursor += count;
        }
    }
    batch.propertyBlocks = propertyBlocks;
    batch.propertyBlocksLengths = lengths;
    averageBlocksPerBatch.add(blockCursor);
    sender.send(batch);
}
Also used : PropertyCreator(org.neo4j.kernel.impl.transaction.state.PropertyCreator) PropertyBlock(org.neo4j.kernel.impl.store.record.PropertyBlock)

Aggregations

PropertyBlock (org.neo4j.kernel.impl.store.record.PropertyBlock)90 PropertyRecord (org.neo4j.kernel.impl.store.record.PropertyRecord)57 Test (org.junit.Test)21 DynamicRecord (org.neo4j.kernel.impl.store.record.DynamicRecord)16 ConsistencyReport (org.neo4j.consistency.report.ConsistencyReport)9 IOException (java.io.IOException)8 InterruptedIOException (java.io.InterruptedIOException)8 Pair (org.neo4j.helpers.collection.Pair)8 DefinedProperty (org.neo4j.kernel.api.properties.DefinedProperty)8 ArrayMap (org.neo4j.kernel.impl.util.ArrayMap)8 NodeRecord (org.neo4j.kernel.impl.store.record.NodeRecord)6 PropertyKeyTokenRecord (org.neo4j.kernel.impl.store.record.PropertyKeyTokenRecord)6 GraphStoreFixture (org.neo4j.consistency.checking.GraphStoreFixture)5 IdGenerator (org.neo4j.consistency.checking.GraphStoreFixture.IdGenerator)5 TransactionDataBuilder (org.neo4j.consistency.checking.GraphStoreFixture.TransactionDataBuilder)5 ConsistencySummaryStatistics (org.neo4j.consistency.report.ConsistencySummaryStatistics)5 PrimitiveRecord (org.neo4j.kernel.impl.store.record.PrimitiveRecord)4 ChainCheck (org.neo4j.consistency.checking.ChainCheck)3 RecordAccessStub (org.neo4j.consistency.store.RecordAccessStub)3 DynamicRecordAllocator (org.neo4j.kernel.impl.store.DynamicRecordAllocator)3