All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.neo4j.kernel.impl.nioneo.xa.TransactionWriter Maven / Gradle / Ivy

Go to download

Neo4j kernel is a lightweight, embedded Java database designed to store data structured as graphs rather than tables. For more information, see http://neo4j.org.

There is a newer version: 5.26.0
Show newest version
/**
 * Copyright (c) 2002-2013 "Neo Technology,"
 * Network Engine for Objects in Lund AB [http://neotechnology.com]
 *
 * This file is part of Neo4j.
 *
 * Neo4j is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */
package org.neo4j.kernel.impl.nioneo.xa;

import static org.neo4j.kernel.impl.nioneo.store.AbstractNameStore.NAME_STORE_BLOCK_SIZE;

import java.io.IOException;

import javax.transaction.xa.Xid;

import org.neo4j.kernel.impl.nioneo.store.AbstractNameRecord;
import org.neo4j.kernel.impl.nioneo.store.DynamicRecord;
import org.neo4j.kernel.impl.nioneo.store.NeoStoreRecord;
import org.neo4j.kernel.impl.nioneo.store.NodeRecord;
import org.neo4j.kernel.impl.nioneo.store.PropertyIndexRecord;
import org.neo4j.kernel.impl.nioneo.store.PropertyRecord;
import org.neo4j.kernel.impl.nioneo.store.PropertyStore;
import org.neo4j.kernel.impl.nioneo.store.RelationshipRecord;
import org.neo4j.kernel.impl.nioneo.store.RelationshipTypeRecord;
import org.neo4j.kernel.impl.transaction.XidImpl;
import org.neo4j.kernel.impl.transaction.xaframework.LogBuffer;
import org.neo4j.kernel.impl.transaction.xaframework.LogIoUtils;

/**
 * This class lives here instead of somewhere else in order to be able to access the {@link Command} implementations.
 *
 * @author Tobias Lindaaker
 */
public class TransactionWriter
{
    private final LogBuffer buffer;
    private final int localId;

    public TransactionWriter( LogBuffer buffer, int localId )
    {
        this.buffer = buffer;
        this.localId = localId;
    }

    // Transaction coordination

    public void start( int masterId, int myId ) throws IOException
    {
        start( XidImpl.getNewGlobalId(), masterId, myId, System.currentTimeMillis() );
    }

    public void start( byte[] globalId, int masterId, int myId, long startTimestamp ) throws IOException
    {
        Xid xid = new XidImpl( globalId, NeoStoreXaDataSource.BRANCH_ID );
        LogIoUtils.writeStart( buffer, this.localId, xid, masterId, myId, startTimestamp );
    }

    public void prepare() throws IOException
    {
        prepare( System.currentTimeMillis() );
    }

    public void prepare( long prepareTimestamp ) throws IOException
    {
        LogIoUtils.writePrepare( buffer, localId, prepareTimestamp );
    }

    public void commit( boolean twoPhase, long txId ) throws IOException
    {
        commit( twoPhase, txId, System.currentTimeMillis() );
    }

    public void commit( boolean twoPhase, long txId, long commitTimestamp ) throws IOException
    {
        LogIoUtils.writeCommit( twoPhase, buffer, localId, txId, commitTimestamp );
    }

    public void done() throws IOException
    {
        LogIoUtils.writeDone( buffer, localId );
    }

    // Transaction data

    public void propertyKey( int id, String key, int... dynamicIds ) throws IOException
    {
        write( new Command.PropertyIndexCommand( null, withName( new PropertyIndexRecord( id ), dynamicIds, key ) ) );
    }

    public void relationshipType( int id, String label, int... dynamicIds ) throws IOException
    {
        write( new Command.RelationshipTypeCommand( null,
                withName( new RelationshipTypeRecord( id ), dynamicIds, label ) ) );
    }

    public void update( NeoStoreRecord record ) throws IOException
    {
        write( new Command.NeoStoreCommand( null, record ) );
    }

    public void create( NodeRecord node ) throws IOException
    {
        node.setCreated();
        update( node );
    }

    public void update( NodeRecord node ) throws IOException
    {
        node.setInUse( true );
        add( node );
    }

    public void delete( NodeRecord node ) throws IOException
    {
        node.setInUse( false );
        add( node );
    }

    public void create( RelationshipRecord relationship ) throws IOException
    {
        relationship.setCreated();
        update( relationship );
    }

    public void update( RelationshipRecord relationship ) throws IOException
    {
        relationship.setInUse( true );
        add( relationship );
    }

    public void delete( RelationshipRecord relationship ) throws IOException
    {
        relationship.setInUse( false );
        add( relationship );
    }

    public void create( PropertyRecord property ) throws IOException
    {
        property.setCreated();
        update( property );
    }

    public void update( PropertyRecord property ) throws IOException
    {
        property.setInUse( true );
        add( property );
    }

    public void delete( PropertyRecord property ) throws IOException
    {
        property.setInUse( false );
        add( property );
    }

    // Internals

    public void add( NodeRecord node ) throws IOException
    {
        write( new Command.NodeCommand( null, node ) );
    }

    public void add( RelationshipRecord relationship ) throws IOException
    {
        write( new Command.RelationshipCommand( null, relationship ) );
    }

    public void add( PropertyRecord property ) throws IOException
    {
        write( new Command.PropertyCommand( null, property ) );
    }

    public void add( RelationshipTypeRecord record ) throws IOException
    {
        write( new Command.RelationshipTypeCommand( null, record ) );
    }

    public void add( PropertyIndexRecord record ) throws IOException
    {
        write( new Command.PropertyIndexCommand( null, record ) );
    }

    public void add( NeoStoreRecord record ) throws IOException
    {
        write( new Command.NeoStoreCommand( null, record ) );
    }

    private void write( Command command ) throws IOException
    {
        LogIoUtils.writeCommand( buffer, localId, command );
    }

    private static  T withName( T record, int[] dynamicIds, String name )
    {
        if ( dynamicIds == null || dynamicIds.length == 0 )
        {
            throw new IllegalArgumentException( "No dynamic records for storing the name." );
        }
        record.setInUse( true );
        byte[] data = PropertyStore.encodeString( name );
        if ( data.length > dynamicIds.length * NAME_STORE_BLOCK_SIZE )
        {
            throw new IllegalArgumentException(
                    String.format( "[%s] is too long to fit in %d blocks", name, dynamicIds.length ) );
        }
        else if ( data.length <= (dynamicIds.length - 1) * NAME_STORE_BLOCK_SIZE )
        {
            throw new IllegalArgumentException(
                    String.format( "[%s] is to short to fill %d blocks", name, dynamicIds.length ) );
        }

        for ( int i = 0; i < dynamicIds.length; i++ )
        {
            byte[] part = new byte[Math.min( NAME_STORE_BLOCK_SIZE, data.length - i * NAME_STORE_BLOCK_SIZE )];
            System.arraycopy( data, i * NAME_STORE_BLOCK_SIZE, part, 0, part.length );

            DynamicRecord dynamicRecord = new DynamicRecord( dynamicIds[i] );
            dynamicRecord.setInUse( true );
            dynamicRecord.setData( part );
            dynamicRecord.setCreated();
            record.addNameRecord( dynamicRecord );
        }
        record.setNameId( dynamicIds[0] );
        return record;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy