Package org.apache.cassandra.dht

Source Code of org.apache.cassandra.dht.LeaveJoinProtocolHelper

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.cassandra.dht;

import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.cassandra.net.EndPoint;
import org.apache.cassandra.net.Message;
import org.apache.cassandra.net.MessagingService;
import org.apache.log4j.Logger;


class LeaveJoinProtocolHelper
{
    private static Logger logger_ = Logger.getLogger(LeaveJoinProtocolHelper.class);
   
    /**
     * Give a range a-------------b which is being split as
     * a-----x-----y-----b then we want a mapping from
     * (a, b] --> (a, x], (x, y], (y, b]
    */
    protected static Map<Range, List<Range>> getRangeSplitRangeMapping(Range[] oldRanges, BigInteger[] allTokens)
    {
        Map<Range, List<Range>> splitRanges = new HashMap<Range, List<Range>>();
        BigInteger[] tokens = new BigInteger[allTokens.length];
        System.arraycopy(allTokens, 0, tokens, 0, tokens.length);
        Arrays.sort(tokens);
       
        Range prevRange = null;
        BigInteger prevToken = null;
        boolean bVal = false;
       
        for ( Range oldRange : oldRanges )
        {
            if ( bVal && prevRange != null )
            {
                bVal = false;
                List<Range> subRanges = splitRanges.get(prevRange);
                if ( subRanges != null )
                    subRanges.add( new Range(prevToken, prevRange.right()) );    
            }
           
            prevRange = oldRange;
            prevToken = oldRange.left();               
            for ( BigInteger token : tokens )
            {    
                List<Range> subRanges = splitRanges.get(oldRange);
                if ( oldRange.contains(token) )
                {                       
                    if ( subRanges == null )
                    {
                        subRanges = new ArrayList<Range>();
                        splitRanges.put(oldRange, subRanges);
                    }                           
                    subRanges.add( new Range(prevToken, token) );
                    prevToken = token;
                    bVal = true;
                }
                else
                {
                    if ( bVal )
                    {
                        bVal = false;                                                                               
                        subRanges.add( new Range(prevToken, oldRange.right()) );                           
                    }
                }
            }
        }
        /* This is to handle the last range being processed. */
        if ( bVal )
        {
            bVal = false;
            List<Range> subRanges = splitRanges.get(prevRange);
            subRanges.add( new Range(prevToken, prevRange.right()) );                           
        }
        return splitRanges;
    }
   
    protected static Map<Range, List<BootstrapSourceTarget>> getRangeSourceTargetInfo(Map<Range, List<EndPoint>> oldRangeToEndPointMap, Map<Range, List<EndPoint>> newRangeToEndPointMap)
    {
        Map<Range, List<BootstrapSourceTarget>> rangesWithSourceTarget = new HashMap<Range, List<BootstrapSourceTarget>>();
        /*
         * Basically calculate for each range the endpoints handling the
         * range in the old token set and in the new token set. Whoever
         * gets bumped out of the top N will have to hand off that range
         * to the new dude.
        */
        Set<Range> oldRangeSet = oldRangeToEndPointMap.keySet();
        for(Range range : oldRangeSet)
        {
            logger_.debug("Attempting to figure out the dudes who are bumped out for " + range + " ...");
            List<EndPoint> oldEndPoints = oldRangeToEndPointMap.get(range);
            List<EndPoint> newEndPoints = newRangeToEndPointMap.get(range);
            if ( newEndPoints != null )
            {                       
                List<EndPoint> newEndPoints2 = new ArrayList<EndPoint>(newEndPoints);
                for ( EndPoint newEndPoint : newEndPoints2 )
                {
                    if ( oldEndPoints.contains(newEndPoint) )
                    {
                        oldEndPoints.remove(newEndPoint);
                        newEndPoints.remove(newEndPoint);
                    }
                }                       
            }
            else
            {
                logger_.warn("Trespassing - scram");
            }
            logger_.debug("Done figuring out the dudes who are bumped out for range " + range + " ...");
        }
        for ( Range range : oldRangeSet )
        {                   
            List<EndPoint> oldEndPoints = oldRangeToEndPointMap.get(range);
            List<EndPoint> newEndPoints = newRangeToEndPointMap.get(range);
            List<BootstrapSourceTarget> srcTarget = rangesWithSourceTarget.get(range);
            if ( srcTarget == null )
            {
                srcTarget = new ArrayList<BootstrapSourceTarget>();
                rangesWithSourceTarget.put(range, srcTarget);
            }
            int i = 0;
            for ( EndPoint oldEndPoint : oldEndPoints )
            {                       
                srcTarget.add( new BootstrapSourceTarget(oldEndPoint, newEndPoints.get(i++)) );
            }
        }
        return rangesWithSourceTarget;
    }
   
    /**
     * This method sends messages out to nodes instructing them
     * to stream the specified ranges to specified target nodes.
    */
    protected static void assignWork(Map<Range, List<BootstrapSourceTarget>> rangesWithSourceTarget) throws IOException
    {
        assignWork(rangesWithSourceTarget, null);
    }
   
    /**
     * This method sends messages out to nodes instructing them
     * to stream the specified ranges to specified target nodes.
    */
    protected static void assignWork(Map<Range, List<BootstrapSourceTarget>> rangesWithSourceTarget, List<EndPoint> filters) throws IOException
    {
        /*
         * Map whose key is the source node and the value is a map whose key is the
         * target and value is the list of ranges to be sent to it.
        */
        Map<EndPoint, Map<EndPoint, List<Range>>> rangeInfo = new HashMap<EndPoint, Map<EndPoint, List<Range>>>();
        Set<Range> ranges = rangesWithSourceTarget.keySet();
       
        for ( Range range : ranges )
        {
            List<BootstrapSourceTarget> rangeSourceTargets = rangesWithSourceTarget.get(range);
            for ( BootstrapSourceTarget rangeSourceTarget : rangeSourceTargets )
            {
                Map<EndPoint, List<Range>> targetRangeMap = rangeInfo.get(rangeSourceTarget.source_);
                if ( targetRangeMap == null )
                {
                    targetRangeMap = new HashMap<EndPoint, List<Range>>();
                    rangeInfo.put(rangeSourceTarget.source_, targetRangeMap);
                }
                List<Range> rangesToGive = targetRangeMap.get(rangeSourceTarget.target_);
                if ( rangesToGive == null )
                {
                    rangesToGive = new ArrayList<Range>();
                    targetRangeMap.put(rangeSourceTarget.target_, rangesToGive);
                }
                rangesToGive.add(range);
            }
        }
       
        Set<EndPoint> sources = rangeInfo.keySet();
        for ( EndPoint source : sources )
        {
            /* only send the message to the nodes that are in the filter. */
            if ( filters != null && filters.size() > 0 && !filters.contains(source) )
            {
                logger_.debug("Filtering endpoint " + source + " as source ...");
                continue;
            }
           
            Map<EndPoint, List<Range>> targetRangesMap = rangeInfo.get(source);
            Set<EndPoint> targets = targetRangesMap.keySet();
            List<BootstrapMetadata> bsmdList = new ArrayList<BootstrapMetadata>();
           
            for ( EndPoint target : targets )
            {
                List<Range> rangeForTarget = targetRangesMap.get(target);
                BootstrapMetadata bsMetadata = new BootstrapMetadata(target, rangeForTarget);
                bsmdList.add(bsMetadata);
            }
           
            BootstrapMetadataMessage bsMetadataMessage = new BootstrapMetadataMessage(bsmdList.toArray( new BootstrapMetadata[0] ) );
            /* Send this message to the source to do his shit. */
            Message message = BootstrapMetadataMessage.makeBootstrapMetadataMessage(bsMetadataMessage);
            logger_.debug("Sending the BootstrapMetadataMessage to " + source);
            MessagingService.getMessagingInstance().sendOneWay(message, source);
        }
    }
}
TOP

Related Classes of org.apache.cassandra.dht.LeaveJoinProtocolHelper

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.