
com.tangosol.persistence.ArchiverHelper Maven / Gradle / Ivy
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
package com.tangosol.persistence;
import com.tangosol.net.CacheFactory;
import com.tangosol.util.Base;
import java.io.File;
import java.io.FileFilter;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* Various helper methods for the archiver functionality.
*
* @since 12.2.1
* @author tam 2014.03.18
* @deprecated this API is intended for internal purposes only and will be removed
* in a future version of Coherence
*/
@Deprecated
// Internal Notes: THIS IMPLEMENTATION HAS BEEN ABANDONED AS OF 12.2.1.2
public class ArchiverHelper
{
/**
* Given a {@link Map} of member Id's and the stores each member can see
* for a given snapshot, allocate the stores evenly as so to allow the
* archival process to run in parallel across the greatest number of
* members. Each member may see the same stores, as they may be on
* shared disk or on the same machine.
*
* @param mapStores a {@link Map} of members and {@link Object[]}s
* that need sorting and allocating
* @param cPartitions the number of partitions
*
*/
public static void allocateSnapshotPartitions(Map mapStores, int cPartitions)
{
try
{
if (mapStores == null || mapStores.size() == 0)
{
throw new IllegalArgumentException("You must supply a collected map of partitions");
}
int nMemberCount = mapStores.size();
String[] asStoresAll = getDistinctStores(mapStores);
if (asStoresAll.length != cPartitions)
{
String sMessage = "Number of unique stores is " + asStoresAll.length
+ " and does not match partition count of " + cPartitions
+ ". This means that some stores are missing or the snapshot is corrupted.";
CacheFactory.log(sMessage, CacheFactory.LOG_ERR);
CacheFactory.log("Dumping distinct store list because of error", CacheFactory.LOG_WARN);
for (String sStore : asStoresAll)
{
CacheFactory.log(sStore,CacheFactory.LOG_WARN);
}
throw new IllegalArgumentException(sMessage);
}
// check for the special case where all members see the same partitions,
// e.g. shared disk
boolean fSharedPartitions = true;
for (Map.Entry entry : mapStores.entrySet())
{
Object[] asSorted = entry.getValue();
if (asSorted != null)
{
Arrays.sort(asSorted);
}
if (!Arrays.equals(asSorted, asStoresAll))
{
fSharedPartitions = false;
break;
}
}
if (fSharedPartitions)
{
// work out a fair share and allocate to all
int nFairShare = cPartitions / nMemberCount;
int nPartitionStart = 0;
int nEntriesProcessed = 0;
for (Iterator> iter = mapStores.entrySet().iterator(); iter.hasNext();)
{
Map.Entry entry = iter.next();
nEntriesProcessed++;
int nLastPartition = nEntriesProcessed < nMemberCount ? (nPartitionStart + nFairShare - 1) : cPartitions - 1;
String[] asStores = new String[nLastPartition - nPartitionStart + 1];
for (int i = nPartitionStart, j = 0; i <= nLastPartition; i++)
{
asStores[j++] = asStoresAll[i];
}
mapStores.put(entry.getKey(), asStores);
nPartitionStart += nFairShare;
}
}
else
{
// partitions are distributed amongst all members with some potential
// duplicates. Remove the duplicates trying to keep it as balanced as possible
// go through each store and see if the store is known to more than 1 member
for (int iPart = 0; iPart < cPartitions; iPart++)
{
Set setMembers = getMembersOwningPartition(mapStores, asStoresAll[iPart]);
// keep reducing the members that know about this partition to 1 while trying to keep balanced
while (setMembers.size() > 1)
{
// find the member that has the most partitions allocated and remove the partition from it
int nMemberMaxPartitions = -1;
int nMaxPartitions = -1;
for (Integer nMember : setMembers)
{
int nMax = mapStores.get(nMember).length;
if (nMax > nMaxPartitions)
{
nMaxPartitions = nMax;
nMemberMaxPartitions = nMember;
}
}
// the member nMemberMaxPartitions will have the partition "iPart" removed
Object[] aoStores = mapStores.get(nMemberMaxPartitions);
// remove the store from this array
mapStores.put(nMemberMaxPartitions, removeStoreFromArray(asStoresAll[iPart], aoStores));
// re-query the set again
setMembers = getMembersOwningPartition(mapStores, asStoresAll[iPart]);
}
}
}
}
catch (Exception e)
{
throw Base.ensureRuntimeException(e, "Error in ArchiverHelper.allocateSnapshotPartitions");
}
}
/**
* Return the {@link Set} of members who are aware of a particular
* store.
*
* @param mapStores the {@link Map} of discovered partitions for members
* @param sStore the store we are interested in
*
* @return the {@link Set} of members who are aware of a particular store
*/
public static Set getMembersOwningPartition(Map mapStores, String sStore)
{
Set setMembers = new HashSet<>();
for (Map.Entry entry : mapStores.entrySet())
{
Object[] aoValue = entry.getValue();
if (aoValue != null)
{
for (int i = 0; i < aoValue.length; i++)
{
if (sStore.equals(aoValue[i]))
{
setMembers.add(entry.getKey());
break;
}
}
}
}
return setMembers;
}
// ----- helpers --------------------------------------------------------
/**
* Return a a sorted array of distinct stores
*
* @param mapStores the {@link Map} of discovered partitions for members
*
* @return a {@link String[]} of distinct stores
*/
private static String[] getDistinctStores(Map mapStores)
{
Set setStores = new HashSet<>();
for (Map.Entry entry : mapStores.entrySet())
{
Object[] aoValue = entry.getValue();
if (aoValue != null)
{
for (int i = 0; i < aoValue.length; i++)
{
String sStore = (String) aoValue[i];
if (!setStores.contains(sStore))
{
setStores.add(sStore);
}
}
}
}
String[] asResults = setStores.toArray(new String[setStores.size()]);
Arrays.sort(asResults);
return asResults;
}
/**
* Remove the given store from the array and return a new array.
*
* @param sStoreToRemove the store to remove
* @param aoArray the array to remove from
*
* @return the new array with the store removed
*/
private static Object[] removeStoreFromArray(String sStoreToRemove, Object[] aoArray)
{
Object[] aoNewArray = new Object[aoArray.length - 1];
for (int i = 0, j = 0; j < aoArray.length; j++)
{
String sStore = (String) aoArray[j];
if (!sStore.equals(sStoreToRemove))
{
aoNewArray[i++] = sStore;
}
}
return aoNewArray;
}
// ----- inner class: DirectoryFileFilter -------------------------------
/**
* FileFilter implementation that only includes directories.
*/
public static class DirectoryFileFilter
implements FileFilter
{
/**
* Accept the given file only if it is a directory.
*
* @param file the file
*
* @return true if the given file is a directory
*/
@Override
public boolean accept(File file)
{
return file.isDirectory();
}
/**
* Singleton instance.
*/
public static final FileFilter INSTANCE = new DirectoryFileFilter();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy