com.aegisql.conveyor.parallel.LBalancedParallelConveyor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of conveyor-parallel Show documentation
Show all versions of conveyor-parallel Show documentation
Implementation of Parallel Conveyor interface
The newest version!
/*
* COPYRIGHT (C) AEGIS DATA SOLUTIONS, LLC, 2015
*/
package com.aegisql.conveyor.parallel;
import com.aegisql.conveyor.AcknowledgeStatus;
import com.aegisql.conveyor.BuilderAndFutureSupplier;
import com.aegisql.conveyor.BuilderSupplier;
import com.aegisql.conveyor.Conveyor;
import com.aegisql.conveyor.cart.Cart;
import com.aegisql.conveyor.cart.CreatingCart;
import com.aegisql.conveyor.cart.FutureCart;
import com.aegisql.conveyor.cart.ShoppingCart;
import com.aegisql.conveyor.cart.command.GeneralCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.function.Function;
// TODO: Auto-generated Javadoc
/**
* The Class ParallelConveyor.
*
* @author Mikhail Teplitskiy
* @version 1.0.0
* @param the key type
* @param the label type
* @param the Product type
*/
public class LBalancedParallelConveyor extends ParallelConveyor {
/** The Constant LOG. */
private final static Logger LOG = LoggerFactory.getLogger(LBalancedParallelConveyor.class);
/** The final consumer. */
protected Conveyor finalConsumer = null;
/**
* Instantiates a new l balanced parallel conveyor.
*
* @param conveyors the conveyors
*/
public LBalancedParallelConveyor(String... conveyors) {
super();
Objects.requireNonNull(conveyors,"List of conveyors is null");
if(conveyors.length == 0) {
throw new RuntimeException("List of conveyors is empty");
}
Conveyor[] array = new Conveyor[conveyors.length];
for(int i = 0; i < conveyors.length; i++) {
array[i] = Conveyor.byName(conveyors[i]);
}
init(array);
}
/**
* Instantiates a new parallel conveyor.
*
* @param conveyors the conveyors
*/
public LBalancedParallelConveyor(Conveyor... conveyors) {
super();
init(conveyors);
}
private void init(Conveyor... conveyors) {
this.pf = conveyors.length;
if( this.pf == 0 ) {
throw new IllegalArgumentException("Parallelism Factor must be >=1");
}
int kBalanced = 0;
int lBalanced = 0;
int notForvarding = 0;
Conveyor lastNotForwarding = null;
List> defaultConv = new ArrayList<>();
Map>> map = new HashMap<>();
for(Conveyor c:conveyors) {
this.conveyors.add(c);
if(c.isLBalanced()) {
lBalanced++;
Set labels = c.getAcceptedLabels();
for(L l:labels) {
List> convs = map.get(l);
if(convs == null) {
convs = new ArrayList<>();
}
convs.add(c);
map.put(l, convs);
}
} else {
kBalanced++;
defaultConv.add( c );
}
if( ! c.isForwardingResults()) {
lastNotForwarding = c;
notForvarding++;
}
}
if(notForvarding == 1 && lBalanced > 0) {
List> notForwardingList = new ArrayList<>();
notForwardingList.add(lastNotForwarding);
finalConsumer = lastNotForwarding;
map.put(null, notForwardingList); //Creating cart delivered to all, had null in place of Label
}
if(lBalanced == 0) {
throw new RuntimeException("L-Balanced parallel conveyor must have at least one L-balanced assembling conveyor");
} else {
if( kBalanced > 1 ) {
throw new RuntimeException("L-Balanced parallel conveyor cannot have more than one K-balanced default assembling conveyor");
} else if(kBalanced == 1) {
LOG.debug("L-Balanced Parallel conveyor with default labels. {}",map);
this.balancingCart = cart -> map.getOrDefault(cart.getLabel(), defaultConv);
} else {
LOG.debug("L-Balanced Parallel conveyor. {}",map);
this.balancingCart = cart -> {
if(map.containsKey(cart.getLabel())) {
return map.get(cart.getLabel());
} else {
throw new RuntimeException("L-Balanced parallel conveyor "+this.name+"has no default conveyor for label "+cart.getLabel());
}
};
}
this.balancingCommand = command -> this.conveyors;
this.lBalanced = true;
}
this.setMbean(this.name);
}
/**
* Command.
*
* @param the value type
* @param cart the cart
* @return the completable future
*/
@Override
public CompletableFuture command(GeneralCommand cart) {
Objects.requireNonNull(cart, "Command is null");
CompletableFuture combinedFutures = new CompletableFuture<>();
combinedFutures.complete(true);
for(Conveyor conv: this.balancingCommand.apply(cart)) {
combinedFutures = combinedFutures.thenCombine(conv.command((GeneralCommand) cart.copy()), (a,b) -> a && b );
}
return combinedFutures;
}
/* (non-Javadoc)
* @see com.aegisql.conveyor.Conveyor#add(com.aegisql.conveyor.Cart)
*/
@Override
public CompletableFuture place(Cart cart) {
Objects.requireNonNull(cart, "Cart is null");
CompletableFuture combinedFuture = null;
for(Conveyor conv : this.balancingCart.apply(cart)) {
if(combinedFuture == null) {
combinedFuture = conv.place(cart.copy());
} else {
combinedFuture = combinedFuture.thenCombine(conv.place(cart.copy()), ( a, b ) -> a && b );
}
}
return combinedFuture;
}
/* (non-Javadoc)
* @see com.aegisql.conveyor.utils.parallel.ParallelConveyor#createBuildWithCart(com.aegisql.conveyor.cart.Cart)
*/
@Override
protected CompletableFuture createBuildWithCart(Cart cart) {
Objects.requireNonNull(cart, "Cart is null");
CompletableFuture combinedFuture = null;
for(Conveyor conv : this.conveyors) {
if(combinedFuture == null) {
combinedFuture = conv.place(cart.copy());
} else {
combinedFuture = combinedFuture.thenCombine(conv.place(cart.copy()), ( a, b ) -> a && b );
}
}
return combinedFuture;
}
/* (non-Javadoc)
* @see com.aegisql.conveyor.utils.parallel.ParallelConveyor#createBuildFutureWithCart(java.util.function.Function, com.aegisql.conveyor.BuilderSupplier)
*/
protected CompletableFuture createBuildFutureWithCart(Function, CreatingCart> cartSupplier, BuilderSupplier builderSupplier) {
Objects.requireNonNull(cartSupplier, "Cart supplier is null");
CompletableFuture combinedCreateFuture = null;
CompletableFuture productFuture = new CompletableFuture<>();
BuilderAndFutureSupplier supplier = new BuilderAndFutureSupplier<>(builderSupplier, productFuture);
CreatingCart cart = cartSupplier.apply( supplier );
for(Conveyor conv : this.conveyors) {
if(conv.isForwardingResults()) {
LOG.debug("Create in conveyor {} {}",conv,cart);
if(combinedCreateFuture == null) {
combinedCreateFuture = conv.place(new CreatingCart<>(cart.getKey(), builderSupplier, cart.getCreationTime(), cart.getExpirationTime(), cart.getPriority()));
} else {
combinedCreateFuture = combinedCreateFuture.thenCombine(conv.place(new CreatingCart<>(cart.getKey(), builderSupplier, cart.getCreationTime(), cart.getExpirationTime(), cart.getPriority())), (a, b ) -> a && b );
}
} else {
//this conv will finally create the product
LOG.debug("Final conveyor {} {}",conv,cart);
if(combinedCreateFuture == null) {
combinedCreateFuture = conv.place(cart);
} else {
combinedCreateFuture = combinedCreateFuture.thenCombine(conv.place(cart), ( a, b ) -> a && b );
}
}
}
Objects.requireNonNull(combinedCreateFuture, "Create future is empty");
if( combinedCreateFuture.isCancelled()) {
productFuture.cancel(true);
}
return productFuture;
}
/* (non-Javadoc)
* @see com.aegisql.conveyor.utils.parallel.ParallelConveyor#getFutureByCart(com.aegisql.conveyor.cart.FutureCart)
*/
protected CompletableFuture getFutureByCart(FutureCart futureCart) {
CompletableFuture future = futureCart.getValue();
CompletableFuture cartFuture = this.finalConsumer.place( futureCart );
if(cartFuture.isCancelled()) {
future.cancel(true);
}
return future;
}
/**
* Gets the expiration time.
*
* @param key the key
* @param label the label
* @return the expiration time
*/
public long getExpirationTime(K key,L label) {
return ((ParallelConveyor) this.balancingCart.apply( new ShoppingCart(key, null, label)).get(0)).getExpirationTime(key);
}
/* (non-Javadoc)
* @see com.aegisql.conveyor.utils.parallel.ParallelConveyor#isLBalanced()
*/
@Override
public boolean isLBalanced() {
return true;
}
/* (non-Javadoc)
* @see com.aegisql.conveyor.utils.parallel.ParallelConveyor#toString()
*/
@Override
public String toString() {
return "L-Balanced ParallelConveyor [name=" + name + ", pf=" + pf + ", lBalanced=" + lBalanced + "]";
}
@Override
public void setAcknowledgeAction(Consumer> ackAction) {
finalConsumer.setAcknowledgeAction(ackAction);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy