Skip to content

Commit

Permalink
Use IndexDefinition as the index id instead of the Index name. And so…
Browse files Browse the repository at this point in the history
…me updates according to pr comments.
  • Loading branch information
xhad1234 committed Jun 23, 2016
1 parent 5bc9df6 commit 95bea9b
Show file tree
Hide file tree
Showing 14 changed files with 234 additions and 352 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -35,4 +35,5 @@
/underFSStorage/ /underFSStorage/
dependency-reduced-pom.xml dependency-reduced-pom.xml
target/ target/
examples/src/main/java/alluxio/examples/LoadGenerator.java
tests.log* tests.log*
22 changes: 10 additions & 12 deletions core/common/src/main/java/alluxio/collections/FieldIndex.java
Expand Up @@ -22,20 +22,20 @@
* @param <T> type of objects in this {@link IndexedSet} * @param <T> type of objects in this {@link IndexedSet}
*/ */
interface FieldIndex<T> { interface FieldIndex<T> {
/** // /**
* Gets the value of the field that serves as index. // * Gets the value of the field that serves as index.
* // *
* @param o the instance to get the field value from // * @param o the instance to get the field value from
* @return the field value, which is just an Object // * @return the field value, which is just an Object
*/ // */
Object getFieldValue(T o); // Object getFieldValue(T o);


/** /**
* Puts the an object o to the index. * Puts the an object o to the index.
* *
* @param o the instance to get the field value from * @param o the instance to get the field value from
*/ */
void put(T o); void add(T o);


/** /**
* Remove the object o from the index. * Remove the object o from the index.
Expand All @@ -55,17 +55,15 @@ interface FieldIndex<T> {


/** /**
* Gets a subset of objects with the specified field value. If there is no object with * Gets a subset of objects with the specified field value. If there is no object with
* the specified field value, a newly created empty set is returned. For non unique index, the * the specified field value, a newly created empty set is returned.
* returned set is backed up by an internal set, so changes in internal set will be reflected
* in returned set.
* *
* @param value the field value to be satisfied * @param value the field value to be satisfied
* @return the set of objects or an empty set if no such object exists * @return the set of objects or an empty set if no such object exists
*/ */
Set<T> getByField(Object value); Set<T> getByField(Object value);


/** /**
* Gets the object from the set of objects with the specified unique field value. * Gets an object from the set of objects with the specified unique field value.
* *
* @param value the field value * @param value the field value
* @return the object or null if there is no such object * @return the object or null if there is no such object
Expand Down
46 changes: 7 additions & 39 deletions core/common/src/main/java/alluxio/collections/IndexDefinition.java
Expand Up @@ -19,46 +19,20 @@
* *
* @param <T> type of objects in this {@link IndexedSet} * @param <T> type of objects in this {@link IndexedSet}
*/ */
public class IndexDefinition<T> { public abstract class IndexDefinition<T> {

/**
* An interface abstracting the value of the field that serves as index.
*
* @param <T> type of objects in this {@link Abstracter}
*/
public interface Abstracter<T> {
/**
* Gets the value of the field that serves as index.
*
* @param o the instance to get the field value from
* @return the field value, which is just an Object
*/
Object getFieldValue(T o);
}

/** The index name, representing the index in methods of {@link IndexedSet}. */
private final String mName;

/** Whether it is a unique index. */ /** Whether it is a unique index. */
//TODO(lei): change the mIsUnique to mIndexType enum //TODO(lei): change the mIsUnique to mIndexType enum
private final boolean mIsUnique; private final boolean mIsUnique;


/** Abstracts the data field of this index. */
private final Abstracter mAbstracter;

/** /**
* Constructs a new {@link IndexDefinition} instance. * Constructs a new {@link IndexDefinition} instance.
* *
* @param name the name of the field index, used as index id
* @param isUnique if the index is unique. A unique index is an index where each index value only * @param isUnique if the index is unique. A unique index is an index where each index value only
* maps toone object; A non-unique index is an index where an index value can map * maps toone object; A non-unique index is an index where an index value can map
* to one or more objects. * to one or more objects.
* @param abstracter the interface to abstract the value of the field that serves as index
*/ */
public IndexDefinition(String name, boolean isUnique, Abstracter abstracter) { public IndexDefinition(boolean isUnique) {
mIsUnique = isUnique; mIsUnique = isUnique;
mAbstracter = abstracter;
mName = name;
} }


/** /**
Expand All @@ -69,16 +43,10 @@ public boolean isUnique() {
} }


/** /**
* @return the abstracter of the index * Gets the value of the field that serves as index.
*/ *
public Abstracter getAbstracter() { * @param o the instance to get the field value from
return mAbstracter; * @return the field value, which is just an Object
}

/**
* @return the name of the index
*/ */
public String getName() { public abstract Object getFieldValue(T o);
return mName;
}
} }
89 changes: 40 additions & 49 deletions core/common/src/main/java/alluxio/collections/IndexedSet.java
Expand Up @@ -67,14 +67,14 @@
* First, define the fields to be indexed: * First, define the fields to be indexed:
* *
* <pre> * <pre>
* FieldIndex<Puppy> idIndex = new FieldIndex<Puppy> { * IndexDefinition<Puppy> idIndex = new IndexDefinition<Puppy>(true) {
* {@literal @Override} * {@literal @Override}
* Object getFieldValue(Puppy o) { * Object getFieldValue(Puppy o) {
* return o.id(); * return o.id();
* } * }
* } * }
* *
* FieldIndex<Puppy> nameIndex = new FieldIndex<Puppy> { * IndexDefinition<Puppy> nameIndex = new IndexDefinition<Puppy>(true) {
* {@literal @Override} * {@literal @Override}
* Object getFieldValue(Puppy o) { * Object getFieldValue(Puppy o) {
* return o.name(); * return o.name();
Expand Down Expand Up @@ -111,37 +111,36 @@ public class IndexedSet<T> extends AbstractSet<T> {
private final ConcurrentHashSet<T> mObjects = new ConcurrentHashSet<>(8, 0.95f, 8); private final ConcurrentHashSet<T> mObjects = new ConcurrentHashSet<>(8, 0.95f, 8);


/** /**
* Map from {@link FieldIndex} to the index. An index is a map from index value to one or a set of * Map from index name to the index. An index is a map from index value to one or a set of
* objects with that index value. A unique index is an index where each index value only maps to * objects with that index value. A unique index is an index where each index value only maps to
* one object. A non-unique index is an index where an index value can map to one or more objects. * one object. A non-unique index is an index where an index value can map to one or more objects.
*/ */

private final Map<IndexDefinition<T>, FieldIndex<T>> mIndices;
private final Map<String, FieldIndex<T>> mIndices;


/** /**
* Constructs a new {@link IndexedSet} instance with at least one field as the index. * Constructs a new {@link IndexedSet} instance with at least one field as the index.
* *
* @param field at least one field is needed to index the set of objects * @param firstIndexDefinition at least one field is needed to index the set of objects
* @param otherFields other fields to index the set * @param otherIndexDefinitions other index definitions to index the set
*/ */
@SafeVarargs @SafeVarargs
public IndexedSet(IndexDefinition<T> field, IndexDefinition<T>... otherFields) { public IndexedSet(IndexDefinition<T> firstIndexDefinition, IndexDefinition<T>...
// count the numbers of two index types otherIndexDefinitions) {
Iterable<IndexDefinition<T>> fields = Iterable<IndexDefinition<T>> indexDefinitions =
Iterables.concat(Arrays.asList(field), Arrays.asList(otherFields)); Iterables.concat(Arrays.asList(firstIndexDefinition), Arrays.asList(otherIndexDefinitions));


// initialization // initialization
Map<String, FieldIndex<T>> indices = new HashMap<String, FieldIndex<T>>(); Map<IndexDefinition<T>, FieldIndex<T>> indices = new HashMap<>();


for (IndexDefinition<T> indexDefinition : fields) { for (IndexDefinition<T> indexDefinition : indexDefinitions) {
FieldIndex<T> index; FieldIndex<T> index;
if (indexDefinition.isUnique()) { if (indexDefinition.isUnique()) {
index = new UniqueFieldIndex<T>(indexDefinition.getAbstracter()); index = new UniqueFieldIndex<T>(indexDefinition);
} else { } else {
index = new NonUniqueFieldIndex<T>(indexDefinition.getAbstracter()); index = new NonUniqueFieldIndex<T>(indexDefinition);
} }


if (indices.put(indexDefinition.getName(), index) != null) { if (indices.put(indexDefinition, index) != null) {
throw new IllegalStateException("Adding two indices to indexedSet using same name."); throw new IllegalStateException("Adding two indices to indexedSet using same name.");
} }
} }
Expand Down Expand Up @@ -180,8 +179,8 @@ public boolean add(T object) {
return false; return false;
} }


for (Map.Entry<String, FieldIndex<T>> fieldInfo : mIndices.entrySet()) { for (Map.Entry<IndexDefinition<T>, FieldIndex<T>> fieldInfo : mIndices.entrySet()) {
fieldInfo.getValue().put(object); fieldInfo.getValue().add(object);
} }
} }
return true; return true;
Expand Down Expand Up @@ -242,38 +241,37 @@ public void remove() {
/** /**
* Whether there is an object with the specified unique index field value in the set. * Whether there is an object with the specified unique index field value in the set.
* *
* @param indexName the field index name * @param indexDefinition the field index definition
* @param value the field value * @param value the field value
* @return true if there is one such object, otherwise false * @return true if there is one such object, otherwise false
*/ */
public boolean contains(String indexName, Object value) { public boolean contains(IndexDefinition<T> indexDefinition, Object value) {
FieldIndex<T> index = mIndices.get(indexName); FieldIndex<T> index = mIndices.get(indexDefinition);
return index != null && index.contains(value); return index != null && index.contains(value);
} }


/** /**
* Gets a subset of objects with the specified field value. If there is no object with the * Gets a subset of objects with the specified field value. If there is no object with the
* specified field value, a newly created empty set is returned. Otherwise, the returned set is * specified field value, a newly created empty set is returned.
* backed up by an internal set, so changes in internal set will be reflected in returned set.
* *
* @param indexName the field index name * @param indexDefinition the field index definition
* @param value the field value to be satisfied * @param value the field value to be satisfied
* @return the set of objects or an empty set if no such object exists * @return the set of objects or an empty set if no such object exists
*/ */
public Set<T> getByField(String indexName, Object value) { public Set<T> getByField(IndexDefinition<T> indexDefinition, Object value) {
FieldIndex<T> index = mIndices.get(indexName); FieldIndex<T> index = mIndices.get(indexDefinition);
return index == null ? new HashSet<T>() : index.getByField(value); return index == null ? new HashSet<T>() : index.getByField(value);
} }


/** /**
* Gets the object from the set of objects with the specified non-unique field value. * Gets the object from the set of objects with the specified non-unique field value.
* *
* @param indexName the field index name * @param indexDefinition the field index definition
* @param value the field value * @param value the field value
* @return the object or null if there is no such object * @return the object or null if there is no such object
*/ */
public T getFirstByField(String indexName, Object value) { public T getFirstByField(IndexDefinition<T> indexDefinition, Object value) {
FieldIndex<T> index = mIndices.get(indexName); FieldIndex<T> index = mIndices.get(indexDefinition);
return index == null ? null : index.getFirst(value); return index == null ? null : index.getFirst(value);
} }


Expand Down Expand Up @@ -311,42 +309,35 @@ public boolean remove(Object object) {
* @param object the object to be removed * @param object the object to be removed
*/ */
private void removeFromIndices(T object) { private void removeFromIndices(T object) {
for (Map.Entry<String, FieldIndex<T>> fieldInfo : mIndices.entrySet()) { for (Map.Entry<IndexDefinition<T>, FieldIndex<T>> fieldInfo : mIndices.entrySet()) {
fieldInfo.getValue().remove(object); fieldInfo.getValue().remove(object);
} }
} }


/** /**
* Removes the object with the specified unique index field value. * Removes the object with the specified unique index field value.
* *
* @param indexName the field index * @param indexDefinition the field index
* @param value the field value * @param value the field value
* @return the number of objects removed * @return the number of objects removed
*/ */
public int removeByField(String indexName, Object value) { public int removeByField(IndexDefinition<T> indexDefinition, Object value) {
int removed = 0; FieldIndex<T> index = mIndices.get(indexDefinition);
FieldIndex<T> index = mIndices.get(indexName);


if (index == null) { if (index == null) {
return 0; return 0;
} else if (index instanceof UniqueFieldIndex) { }
T toRemove = ((UniqueFieldIndex<T>) index).get(value);
if (remove(toRemove)) {
removed++;
}
} else if (index instanceof NonUniqueFieldIndex) {
ConcurrentHashSet<T> toRemove = ((NonUniqueFieldIndex<T>) index).get(value);


if (toRemove == null) { Set<T> toRemove = index.getByField(value);
return 0; if (toRemove == null) {
} return 0;
for (T o : toRemove) { }
if (remove(o)) { int removed = 0;
removed++; for (T o : toRemove) {
} if (remove(o)) {
removed++;
} }
} }

return removed; return removed;
} }


Expand Down
Expand Up @@ -23,35 +23,20 @@
* @param <T> type of objects in this {@link IndexedSet} * @param <T> type of objects in this {@link IndexedSet}
*/ */
class NonUniqueFieldIndex<T> implements FieldIndex<T> { class NonUniqueFieldIndex<T> implements FieldIndex<T> {
private final IndexDefinition.Abstracter mAbstracter; private final IndexDefinition<T> mIndexDefinition;
private ConcurrentHashMap<Object, ConcurrentHashSet<T>> mIndexMap; private ConcurrentHashMap<Object, ConcurrentHashSet<T>> mIndexMap;


/** /**
* Constructs a new {@link NonUniqueFieldIndex} instance. * Constructs a new {@link NonUniqueFieldIndex} instance.
*/ */
public NonUniqueFieldIndex(IndexDefinition.Abstracter abstracter) { public NonUniqueFieldIndex(IndexDefinition<T> indexDefinition) {
mIndexMap = new ConcurrentHashMap<Object, ConcurrentHashSet<T>>(8, 0.95f, 8); mIndexMap = new ConcurrentHashMap<Object, ConcurrentHashSet<T>>(8, 0.95f, 8);
mAbstracter = abstracter; mIndexDefinition = indexDefinition;
}

/**
* Gets the set of objects with the specified field value - internal function.
*
* @param value the field value
* @return the set of objects with the specified field value
*/
public ConcurrentHashSet<T> get(Object value) {
return mIndexMap.get(value);
} }


@Override @Override
public Object getFieldValue(T o) { public void add(T object) {
return mAbstracter.getFieldValue(o); Object fieldValue = mIndexDefinition.getFieldValue(object);
}

@Override
public void put(T object) {
Object fieldValue = getFieldValue(object);


ConcurrentHashSet<T> objSet = mIndexMap.get(fieldValue); ConcurrentHashSet<T> objSet = mIndexMap.get(fieldValue);


Expand All @@ -61,20 +46,12 @@ public void put(T object) {
objSet = mIndexMap.get(fieldValue); objSet = mIndexMap.get(fieldValue);
} }


if (!objSet.addIfAbsent(object)) { objSet.add(object);
// this call can never return false because:
// a. the second-level sets in the indices are all
// {@link java.util.Set} instances of unbounded space
// b. We have already successfully added object on mObjects,
// meaning that it cannot be already in any of the sets.
// (mObjects is exactly the set-union of all the other second-level sets)
throw new IllegalStateException("Indexed Set is in an illegal state");
}
} }


@Override @Override
public boolean remove(T object) { public boolean remove(T object) {
Object fieldValue = getFieldValue(object); Object fieldValue = mIndexDefinition.getFieldValue(object);
ConcurrentHashSet<T> objSet = mIndexMap.get(fieldValue); ConcurrentHashSet<T> objSet = mIndexMap.get(fieldValue);
if (objSet != null) { if (objSet != null) {
return objSet.remove(object); return objSet.remove(object);
Expand Down

0 comments on commit 95bea9b

Please sign in to comment.