Package org.neo4j.kernel.ha

Source Code of org.neo4j.kernel.ha.SlaveIdGenerator$SlaveIdGeneratorFactory

/**
* Copyright (c) 2002-2011 "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 <http://www.gnu.org/licenses/>.
*/
package org.neo4j.kernel.ha;

import java.util.EnumMap;
import java.util.Map;

import org.neo4j.com.ComException;
import org.neo4j.helpers.Pair;
import org.neo4j.kernel.CommonFactories;
import org.neo4j.kernel.IdGeneratorFactory;
import org.neo4j.kernel.IdType;
import org.neo4j.kernel.ha.zookeeper.Machine;
import org.neo4j.kernel.ha.zookeeper.ZooKeeperException;
import org.neo4j.kernel.impl.nioneo.store.IdGenerator;
import org.neo4j.kernel.impl.nioneo.store.IdRange;
import org.neo4j.kernel.impl.nioneo.store.NeoStore;

public class SlaveIdGenerator implements IdGenerator
{
    private static final long VALUE_REPRESENTING_NULL = -1;
   
    public static class SlaveIdGeneratorFactory implements IdGeneratorFactory
    {
        private final Broker broker;
        private final ResponseReceiver receiver;
        private final Map<IdType, SlaveIdGenerator> generators =
                new EnumMap<IdType, SlaveIdGenerator>( IdType.class );
        private final IdGeneratorFactory localFactory =
                CommonFactories.defaultIdGeneratorFactory();

        public SlaveIdGeneratorFactory( Broker broker, ResponseReceiver receiver )
        {
            this.broker = broker;
            this.receiver = receiver;
        }
       
        public IdGenerator open( String fileName, int grabSize, IdType idType, long highestIdInUse )
        {
            IdGenerator localIdGenerator = localFactory.open( fileName, grabSize,
                    idType, highestIdInUse );
            SlaveIdGenerator generator = new SlaveIdGenerator( idType, highestIdInUse, broker,
                    receiver, localIdGenerator );
            generators.put( idType, generator );
            return generator;
        }
       
        public void create( String fileName )
        {
            localFactory.create( fileName );
        }

        public IdGenerator get( IdType idType )
        {
            return generators.get( idType );
        }
       
        public void updateIdGenerators( NeoStore store )
        {
            store.updateIdGenerators();
        }
       
        public void forgetIdAllocationsFromMaster()
        {
            for ( SlaveIdGenerator idGenerator : generators.values() )
            {
                idGenerator.forgetIdAllocationFromMaster();
            }
        }
    };
   
    private final Broker broker;
    private final ResponseReceiver receiver;
    private volatile long highestIdInUse;
    private volatile long defragCount;
    private volatile IdRangeIterator idQueue = EMPTY_ID_RANGE_ITERATOR;
    private volatile int allocationMaster;
    private final IdType idType;
    private final IdGenerator localIdGenerator;

    public SlaveIdGenerator( IdType idType, long highestIdInUse, Broker broker,
            ResponseReceiver receiver, IdGenerator localIdGenerator )
    {
        this.idType = idType;
        this.broker = broker;
        this.receiver = receiver;
        this.localIdGenerator = localIdGenerator;
    }
   
    private void forgetIdAllocationFromMaster()
    {
        this.idQueue = EMPTY_ID_RANGE_ITERATOR;
    }

    public void close()
    {
        this.localIdGenerator.close();
    }

    public void freeId( long id )
    {
    }

    public long getHighId()
    {
        return Math.max( this.localIdGenerator.getHighId(), highestIdInUse );
    }

    public long getNumberOfIdsInUse()
    {
        return Math.max( this.localIdGenerator.getNumberOfIdsInUse(), highestIdInUse-defragCount );
    }

    public synchronized long nextId()
    {
        try
        {
            long nextId = nextLocalId();
            Pair<Master, Machine> master = broker.getMaster();
            if ( nextId == VALUE_REPRESENTING_NULL )
            {
                // If we dont have anymore grabbed ids from master, grab a bunch
                IdAllocation allocation = master.first().allocateIds( idType ).response();
                allocationMaster = master.other().getMachineId();
                nextId = storeLocally( allocation );
            }
            else
            {
                assert master.other().getMachineId() == allocationMaster;
            }
            return nextId;
        }
        catch ( ZooKeeperException e )
        {
            receiver.newMaster( null, e );
            throw e;
        }
        catch ( ComException e )
        {
            receiver.newMaster( null, e );
            throw e;
        }
    }
   
    public IdRange nextIdBatch( int size )
    {
        throw new UnsupportedOperationException( "Should never be called" );
    }

    private long storeLocally( IdAllocation allocation )
    {
        this.highestIdInUse = allocation.getHighestIdInUse();
        this.defragCount = allocation.getDefragCount();
        this.idQueue = new IdRangeIterator( allocation.getIdRange() );
        updateLocalIdGenerator();
        return idQueue.next();
    }

    private void updateLocalIdGenerator()
    {
        long localHighId = this.localIdGenerator.getHighId();
        if ( this.highestIdInUse > localHighId )
        {
            this.localIdGenerator.setHighId( this.highestIdInUse );
        }
    }

    private long nextLocalId()
    {
        return this.idQueue.next();
    }

    public void setHighId( long id )
    {
        this.localIdGenerator.setHighId( id );
    }
   
    public long getDefragCount()
    {
        return this.defragCount;
    }
   
    private static class IdRangeIterator
    {
        private int position = 0;
        private final long[] defrag;
        private final long start;
        private final int length;

        IdRangeIterator( IdRange idRange )
        {
            this.defrag = idRange.getDefragIds();
            this.start = idRange.getRangeStart();
            this.length = idRange.getRangeLength();
        }
       
        long next()
        {
            try
            {
                if ( position < defrag.length )
                {
                    return defrag[position];
                }
                else
                {
                    int offset = position - defrag.length;
                    return ( offset < length ) ? ( start + offset ) : VALUE_REPRESENTING_NULL;
                }
            }
            finally
            {
                ++position;
            }
        }
    }
   
    private static IdRangeIterator EMPTY_ID_RANGE_ITERATOR =
            new IdRangeIterator( new IdRange( new long[0], 0, 0 ) )
    {
        @Override
        long next()
        {
            return VALUE_REPRESENTING_NULL;
        };
    };
}
TOP

Related Classes of org.neo4j.kernel.ha.SlaveIdGenerator$SlaveIdGeneratorFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.