package rocks.inspectit.shared.cs.indexing.storage.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
import org.apache.commons.lang.builder.ToStringBuilder;
import rocks.inspectit.shared.all.cmr.cache.IObjectSizes;
import rocks.inspectit.shared.all.communication.DefaultData;
import rocks.inspectit.shared.all.indexing.IIndexQuery;
import rocks.inspectit.shared.cs.indexing.QueryTask;
import rocks.inspectit.shared.cs.indexing.impl.IndexingException;
import rocks.inspectit.shared.cs.indexing.storage.IStorageDescriptor;
import rocks.inspectit.shared.cs.indexing.storage.IStorageTreeComponent;
/**
* This classes enables joining of many storage indexing trees, so that all of them can be queried.
* Note that this class provide read only operations. Thus call of the method
* {@link #put(DefaultData)} and {@link #getAndRemove(DefaultData)} will throw and
* {@link UnsupportedOperationException} because simply the class does not know where in which
* branch the object belongs.
*
* @author Ivan Senic
*
* @param <E>
*/
public class CombinedStorageBranch<E extends DefaultData> implements IStorageTreeComponent<E> {
/**
* List of combined branches.
*/
private List<IStorageTreeComponent<E>> branches;
/**
* Default no-args constructor.
*/
public CombinedStorageBranch() {
branches = new ArrayList<>();
}
/**
* Constructor thats sets branches.
*
* @param branches
* Branches that are joined in one.
*/
public CombinedStorageBranch(List<IStorageTreeComponent<E>> branches) {
this.branches = branches;
}
/**
* @return the branches
*/
public List<IStorageTreeComponent<E>> getBranches() {
return branches;
}
/**
* @param branches
* the branches to set
*/
public void setBranches(List<IStorageTreeComponent<E>> branches) {
this.branches = branches;
}
/**
* Adds a branch to the combined branches list.
*
* @param branch
* {@link IStorageTreeComponent} to add.
*/
public void addBranch(IStorageTreeComponent<E> branch) {
branches.add(branch);
}
/**
* {@inheritDoc}
* <p>
* Call to this method throws the {@link UnsupportedOperationException} cause combined branch
* should only be used for read operations.
*/
@Override
public IStorageDescriptor put(E element) throws IndexingException {
throw new UnsupportedOperationException("Combined storage branch provides only read-only operations.");
}
/**
* {@inheritDoc}
*/
@Override
public IStorageDescriptor get(E element) {
for (IStorageTreeComponent<E> branch : branches) {
IStorageDescriptor descriptor = branch.get(element);
if (descriptor != null) {
return descriptor;
}
}
return null;
}
/**
* {@inheritDoc}
* <p>
* Method returns combined results from all branches that are combined.
*/
public List<IStorageDescriptor> query(StorageIndexQuery query) {
List<IStorageDescriptor> combinedResult = new ArrayList<>();
for (IStorageTreeComponent<E> branch : branches) {
List<IStorageDescriptor> branchResult = branch.query(query);
if ((branchResult != null) && !branchResult.isEmpty()) {
combinedResult.addAll(branchResult);
}
}
return combinedResult;
}
/**
* {@inheritDoc}
*/
@Override
public void preWriteFinalization() {
for (IStorageTreeComponent<E> branch : branches) {
branch.preWriteFinalization();
}
}
/**
* {@inheritDoc}
* <p>
* Method returns combined results from all branches that are combined.
*/
@Override
public List<IStorageDescriptor> query(IIndexQuery query) {
List<IStorageDescriptor> combinedResult = new ArrayList<>();
for (IStorageTreeComponent<E> branch : branches) {
List<IStorageDescriptor> branchResult = branch.query(query);
if ((branchResult != null) && !branchResult.isEmpty()) {
combinedResult.addAll(branchResult);
}
}
return combinedResult;
}
/**
* {@inheritDoc}
*/
@Override
public List<IStorageDescriptor> query(IIndexQuery query, ForkJoinPool forkJoinPool) {
return forkJoinPool.invoke(getTaskForForkJoinQuery(query));
}
/**
* {@inheritDoc}
* <p>
* Call to this method throws the {@link UnsupportedOperationException} cause combined branch
* should only be used for read operations.
*/
@Override
public IStorageDescriptor getAndRemove(E element) {
throw new UnsupportedOperationException("Combined storage branch provides only read-only operations.");
}
/**
* {@inheritDoc}
*/
@Override
public long getComponentSize(IObjectSizes objectSizes) {
long size = objectSizes.getSizeOfObjectHeader() + objectSizes.getPrimitiveTypesSize(1, 0, 0, 0, 0, 0);
size += objectSizes.getSizeOf(branches);
for (IStorageTreeComponent<E> branch : branches) {
size += branch.getComponentSize(objectSizes);
}
return objectSizes.alignTo8Bytes(size);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
ToStringBuilder toStringBuilder = new ToStringBuilder(this);
toStringBuilder.append("branches", branches);
return toStringBuilder.toString();
}
/**
* Returns the branches to Query.
*
* @param <R>
*
* @param query
* query
* @return the list of branches
*/
public List<IStorageTreeComponent<E>> getBranchesToQuery(IIndexQuery query) {
return getBranches();
}
/**
* {@inheritDoc}
*/
@Override
public RecursiveTask<List<IStorageDescriptor>> getTaskForForkJoinQuery(IIndexQuery query) {
return new QueryTask<>(branches, query);
}
}