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

org.bboxdb.network.client.tools.AbtractClusterFutureBuilder Maven / Gradle / Ivy

There is a newer version: 1.0.0-rc3
Show newest version
/*******************************************************************************
 *
 *    Copyright (C) 2015-2018 the BBoxDB project
 *  
 *    Licensed 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.bboxdb.network.client.tools;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;

import org.bboxdb.commons.math.Hyperrectangle;
import org.bboxdb.distribution.membership.BBoxDBInstance;
import org.bboxdb.distribution.membership.MembershipConnectionService;
import org.bboxdb.distribution.partitioner.SpacePartitionerHelper;
import org.bboxdb.distribution.region.DistributionRegion;
import org.bboxdb.distribution.region.DistributionRegionHelper;
import org.bboxdb.misc.BBoxDBException;
import org.bboxdb.network.client.BBoxDBConnection;
import org.bboxdb.network.client.future.network.NetworkOperationFuture;
import org.bboxdb.network.client.future.network.NetworkOperationFutureMultiImpl;
import org.bboxdb.network.routing.RoutingHeader;
import org.bboxdb.network.routing.RoutingHop;
import org.bboxdb.network.routing.RoutingHopHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class AbtractClusterFutureBuilder {
	
	/**
	 * The distribution region
	 */
	private final DistributionRegion distributionRegion;
	
	/**
	 * The bounding box
	 */
	private final Hyperrectangle boundingBox;

	/**
	 * The membership connection service
	 */
	private final MembershipConnectionService membershipConnectionService;

	/**
	 * The cluster operation type
	 */
	private ClusterOperationType clusterOperationType;
	
	/**
	 * The Logger
	 */
	private final static Logger logger = LoggerFactory.getLogger(AbtractClusterFutureBuilder.class);

	public AbtractClusterFutureBuilder(final ClusterOperationType clusterOperationType, 
			final String table, final Hyperrectangle boundingBox) throws BBoxDBException {
		
		this.clusterOperationType = clusterOperationType;
		this.distributionRegion = SpacePartitionerHelper.getRootNode(table);
		this.boundingBox = boundingBox;
		this.membershipConnectionService = MembershipConnectionService.getInstance();
	}

	public Supplier> getSupplier() {
		
		if(clusterOperationType == ClusterOperationType.READ_FROM_NODES_HA_IF_REPLICATED) {
			return getReplicatedSupplier();
		} else {
			return getUnreplicatedSupplier();
		}
	}

	/**
	 * Get the replicated supplier 
	 * Only one read operation per replicate needs to be successful
	 * 
	 * @return
	 */
	private Supplier> getReplicatedSupplier() {
		
		final Supplier> supplier = () -> {
			
			final List futures = new ArrayList<>();

			final List regions = RoutingHopHelper.getRegionsForPredicate(
					distributionRegion, boundingBox, DistributionRegionHelper.PREDICATE_REGIONS_FOR_READ);
						
			if(regions.isEmpty()) {
				logger.error("Got empty hop list by bbox {} read {}", boundingBox, clusterOperationType);
			}

			for(final DistributionRegion region : regions) {
				final List futuresPerReplicate = new ArrayList<>();

				for(final BBoxDBInstance instance : region.getSystems()) {
					final BBoxDBConnection connection
						= membershipConnectionService.getConnectionForInstance(instance);
					
					// Node is down
					if(connection == null) {
						logger.debug("Skipping connection for {}", instance.getInetSocketAddress());
						continue;
					}
					
					final RoutingHop hop = new RoutingHop(instance, Arrays.asList(region.getRegionId()));

					final RoutingHeader routingHeader = new RoutingHeader((short) 0, Arrays.asList(hop));

					final Supplier> future = buildFuture(connection, routingHeader);
					futuresPerReplicate.addAll(future.get());
				}
				
				// Only one future of the list needs to be successful
				final NetworkOperationFutureMultiImpl future = new NetworkOperationFutureMultiImpl(
						futuresPerReplicate);
				
				futures.add(future);
			}

			return futures;
		};
		
		return supplier;
	}

	/**
	 * Get the unreplicated supplier
	 * All operations needs to be successful
	 * 
	 * @return
	 */
	private Supplier> getUnreplicatedSupplier() {
		final Supplier> supplier = () -> {
			
			final List futures = new ArrayList<>();

			final List hops = getHops();
			
			if(hops.isEmpty()) {
				logger.error("Got empty hop list by bbox {} read {}", boundingBox, clusterOperationType);
			}

			for(final RoutingHop hop : hops) {
				final BBoxDBInstance instance = hop.getDistributedInstance();

				final BBoxDBConnection connection
					= membershipConnectionService.getConnectionForInstance(instance);

				final RoutingHeader routingHeader = new RoutingHeader((short) 0, Arrays.asList(hop));

				final Supplier> future = buildFuture(connection, routingHeader);

				futures.addAll(future.get());
			}

			return futures;
		};
		return supplier;
	}
	
	/**
	 * Build the future
	 * @param routingHeader 
	 * @param connection 
	 * @return
	 */
	protected abstract Supplier> buildFuture(
			final BBoxDBConnection connection, final RoutingHeader routingHeader);
	
	/**
	 * Get the hop for the operation
	 * @return
	 */
	private List getHops() {
		switch(clusterOperationType) {
			case READ_FROM_NODES:
				return RoutingHopHelper.getRoutingHopsForRead(distributionRegion, boundingBox);
			case WRITE_TO_NODES:
				return RoutingHopHelper.getRoutingHopsForWrite(distributionRegion, boundingBox);
			default:
				throw new IllegalArgumentException("Unknown type: " + clusterOperationType);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy