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

org.neo4j.coreedge.core.state.machines.id.ReplicatedIdGenerator Maven / Gradle / Ivy

/*
 * Copyright (c) 2002-2016 "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 Affero 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see .
 */
package org.neo4j.coreedge.core.state.machines.id;

import org.neo4j.kernel.impl.store.id.IdGenerator;
import org.neo4j.kernel.impl.store.id.IdRange;
import org.neo4j.kernel.impl.store.id.IdType;
import org.neo4j.logging.Log;
import org.neo4j.logging.LogProvider;

import static java.lang.Math.max;
import static org.neo4j.coreedge.core.state.machines.id.IdRangeIterator.EMPTY_ID_RANGE_ITERATOR;
import static org.neo4j.coreedge.core.state.machines.id.IdRangeIterator.VALUE_REPRESENTING_NULL;

class ReplicatedIdGenerator implements IdGenerator
{
    private final IdType idType;
    private final Log log;
    private final ReplicatedIdRangeAcquirer acquirer;
    private volatile long highId;
    private volatile long defragCount;
    private volatile IdRangeIterator idQueue = EMPTY_ID_RANGE_ITERATOR;

    ReplicatedIdGenerator( IdType idType, long highId, ReplicatedIdRangeAcquirer acquirer, LogProvider
            logProvider )
    {
        this.idType = idType;
        this.highId = highId;
        this.acquirer = acquirer;
        this.log = logProvider.getLog( getClass() );
    }

    @Override
    public void close()
    {
    }

    @Override
    public void freeId( long id )
    {
    }

    @Override
    public long getHighId()
    {
        return highId;
    }

    @Override
    public void setHighId( long id )
    {
        this.highId = max( this.highId, id );
    }

    @Override
    public long getHighestPossibleIdInUse()
    {
        return highId - 1;
    }

    @Override
    public long getNumberOfIdsInUse()
    {
        return highId - defragCount;
    }

    @Override
    public synchronized long nextId()
    {
        long nextId = idQueue.next();
        if ( nextId == VALUE_REPRESENTING_NULL )
        {
            IdAllocation allocation;
            allocation = acquirer.acquireIds( idType );

            assert allocation.getIdRange().getRangeLength() > 0;
            log.debug( "Received id allocation " + allocation + " for " + idType );
            nextId = storeLocally( allocation );
        }
        highId = max( highId, nextId + 1 );
        return nextId;
    }

    @Override
    public IdRange nextIdBatch( int size )
    {
        throw new UnsupportedOperationException( "Should never be called" );
    }

    private long storeLocally( IdAllocation allocation )
    {
        setHighId( allocation.getHighestIdInUse() + 1 ); // high id is certainly bigger than the highest id in use
        this.defragCount = allocation.getDefragCount();
        this.idQueue = new IdRangeIterator( respectingHighId( allocation.getIdRange() ) );
        return idQueue.next();
    }

    private IdRange respectingHighId( IdRange idRange )
    {
        int adjustment = 0;
        long originalRangeStart = idRange.getRangeStart();
        if ( highId > originalRangeStart )
        {
            adjustment = (int) (highId - originalRangeStart);
        }
        long rangeStart = max( this.highId, originalRangeStart );
        int rangeLength = idRange.getRangeLength() - adjustment;
        if ( rangeLength <= 0 )
        {
            throw new IllegalStateException(
                    "IdAllocation state is probably corrupted or out of sync with the cluster. " +
                    "Local highId is " + highId + " and allocation range is " + idRange );
        }
        return new IdRange( idRange.getDefragIds(), rangeStart, rangeLength );
    }

    @Override
    public long getDefragCount()
    {
        return this.defragCount;
    }

    @Override
    public void delete()
    {
    }

    @Override
    public String toString()
    {
        return getClass().getSimpleName() + "[" + this.idQueue + "]";
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy