From 9d219c6af6ce718a282a00fd2a93dc0e08ccf548 Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Mon, 22 Dec 2008 19:35:56 +0000 Subject: Eliminate level of indirection when accessing indexes. --- .../carbonado/repo/indexed/IndexAnalysis.java | 9 +- .../repo/indexed/IndexEntryGenerator.java | 137 ++++++--------------- .../carbonado/repo/indexed/IndexedCursor.java | 20 +-- .../carbonado/repo/indexed/IndexedStorage.java | 2 +- .../carbonado/repo/indexed/ManagedIndex.java | 24 ++-- 5 files changed, 72 insertions(+), 120 deletions(-) diff --git a/src/main/java/com/amazon/carbonado/repo/indexed/IndexAnalysis.java b/src/main/java/com/amazon/carbonado/repo/indexed/IndexAnalysis.java index 241f297..5175488 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/IndexAnalysis.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/IndexAnalysis.java @@ -51,6 +51,8 @@ import com.amazon.carbonado.info.StorableProperty; import com.amazon.carbonado.qe.FilteringScore; import com.amazon.carbonado.qe.StorableIndexSet; +import com.amazon.carbonado.synthetic.SyntheticStorableReferenceAccess; + /** * Builds various sets of indexes for a Storable type. * @@ -275,11 +277,12 @@ class IndexAnalysis { ManagedIndex[] managedIndexes = new ManagedIndex[managedIndexSet.size()]; int i = 0; for (StorableIndex index : managedIndexSet) { - IndexEntryGenerator builder = IndexEntryGenerator.getInstance(index); - Class indexEntryClass = builder.getIndexEntryClass(); + SyntheticStorableReferenceAccess accessor = + IndexEntryGenerator.getIndexAccess(index); + Class indexEntryClass = accessor.getReferenceClass(); Storage indexEntryStorage = repository.getIndexEntryStorageFor(indexEntryClass); ManagedIndex managedIndex = new ManagedIndex - (repository, masterStorage, index, builder, indexEntryStorage); + (repository, masterStorage, index, accessor, indexEntryStorage); allIndexInfoMap.put(index, managedIndex); managedIndexes[i++] = managedIndex; diff --git a/src/main/java/com/amazon/carbonado/repo/indexed/IndexEntryGenerator.java b/src/main/java/com/amazon/carbonado/repo/indexed/IndexEntryGenerator.java index 7fb80dc..19bfa8c 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/IndexEntryGenerator.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/IndexEntryGenerator.java @@ -41,138 +41,83 @@ import com.amazon.carbonado.synthetic.SyntheticStorableReferenceBuilder; */ class IndexEntryGenerator { - // cache for generators - private static Map> cCache = - new WeakHashMap>(); - + // cache for access classes + private static Map> cCache = + new WeakHashMap>(); /** - * Returns a new or cached generator instance. The caching of generators is - * soft, so if no references remain to a given instance it may be garbage - * collected. A subsequent call will return a newly created instance. + * Returns a new or cached index access instance. The caching of accessors + * is soft, so if no references remain to a given instance it may be + * garbage collected. A subsequent call will return a newly created + * instance. * - *

In addition to generating an index entry storable, this class + *

In addition to generating an index entry storable, the accessor * contains methods to operate on it. Care must be taken to ensure that the - * index entry instances are of the same type that the generator expects. - * Since the generator may be garbage collected freely of the generated + * index entry instances are of the same type that the accessor expects. + * Since the accessor may be garbage collected freely of the generated * index entry class, it is possible for index entries to be passed to a - * generator instance that does not understand it. For example: + * accessor instance that does not understand it. For example: * *

      * StorableIndex index = ...
-     * Class indexEntryClass = IndexEntryGenerator.getInstance(index).getIndexEntryClass();
+     * Class indexEntryClass = IndexEntryGenerator.getIndexAccess(index).getReferenceClass();
      * ...
      * garbage collection
      * ...
      * Storable indexEntry = instance of indexEntryClass
      * // Might fail because generator instance is new
-     * IndexEntryGenerator.getInstance(index).setAllProperties(indexEntry, source);
+     * IndexEntryGenerator.getIndexAccess(index).copyFromMaster(indexEntry, master);
      * 
* - * The above code can be fixed by saving a local reference to the generator: + * The above code can be fixed by saving a local reference to the accessor: * *
      * StorableIndex index = ...
-     * IndexEntryGenerator generator = IndexEntryGenerator.getInstance(index);
-     * Class indexEntryClass = generator.getIndexEntryClass();
+     * SyntheticStorableReferenceAccess access = IndexEntryGenerator.getIndexAccess(index);
+     * Class indexEntryClass = access.getReferenceClass();
      * ...
      * Storable indexEntry = instance of indexEntryClass
-     * generator.setAllProperties(indexEntry, source);
+     * access.copyFromMaster(indexEntry, master);
      * 
* * @throws SupportException if any non-primary key property doesn't have a * public read method. */ - public static IndexEntryGenerator - getInstance(StorableIndex index) throws SupportException + public static + SyntheticStorableReferenceAccess getIndexAccess(StorableIndex index) + throws SupportException { - synchronized(cCache) { - IndexEntryGenerator generator; - Reference ref = cCache.get(index); + synchronized (cCache) { + SyntheticStorableReferenceAccess access; + Reference ref = cCache.get(index); if (ref != null) { - generator = ref.get(); - if (generator != null) { - return generator; + access = ref.get(); + if (access != null) { + return access; } } - generator = new IndexEntryGenerator(index); - cCache.put(index, new SoftReference(generator)); - return generator; - } - } - - private SyntheticStorableReferenceAccess mIndexAccess; - /** - * Convenience class for gluing new "builder" style synthetics to the traditional - * generator style. - * @param index Generator style index specification - */ - public IndexEntryGenerator(StorableIndex index) throws SupportException { - // Need to try to find the base type. This is an awkward way to do it, - // but we have nothing better available to us - Class type = index.getProperty(0).getEnclosingType(); + // Need to try to find the base type. This is an awkward way to do + // it, but we have nothing better available to us + Class type = index.getProperty(0).getEnclosingType(); - SyntheticStorableReferenceBuilder builder = - new SyntheticStorableReferenceBuilder(type, index.isUnique()); - - for (int i=0; i builder = + new SyntheticStorableReferenceBuilder(type, index.isUnique()); - builder.build(); - - mIndexAccess = builder.getReferenceAccess(); - } - - /** - * Returns generated index entry class, which is abstract. - * - * @return class of index entry, which is a custom Storable - */ - public Class getIndexEntryClass() { - return mIndexAccess.getReferenceClass(); - } + for (int i=0; i source = index.getProperty(i); + builder.addKeyProperty(source.getName(), index.getPropertyDirection(i)); + } - /** - * Sets all the primary key properties of the given master, using the - * applicable properties of the given index entry. - * - * @param indexEntry source of property values - * @param master master whose primary key properties will be set - */ - public void copyToMasterPrimaryKey(Storable indexEntry, S master) { - mIndexAccess.copyToMasterPrimaryKey(indexEntry, master); - } + builder.build(); + access = builder.getReferenceAccess(); - /** - * Sets all the properties of the given index entry, using the applicable - * properties of the given master. - * - * @param indexEntry index entry whose properties will be set - * @param master source of property values - */ - public void copyFromMaster(Storable indexEntry, S master) { - mIndexAccess.copyFromMaster(indexEntry, master); - } + cCache.put(index, new SoftReference(access)); - /** - * Returns true if the properties of the given index entry match those - * contained in the master. This will always return true after a call to - * setAllProperties. - * - * @param indexEntry index entry whose properties will be tested - * @param master source of property values - */ - public boolean isConsistent(Storable indexEntry, S master) { - return mIndexAccess.isConsistent(indexEntry, master); + return access; + } } - /** - * Returns a comparator for ordering index entries. - */ - public Comparator getComparator() { - return mIndexAccess.getComparator(); + private IndexEntryGenerator() { } } diff --git a/src/main/java/com/amazon/carbonado/repo/indexed/IndexedCursor.java b/src/main/java/com/amazon/carbonado/repo/indexed/IndexedCursor.java index 79895c4..de105cc 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/IndexedCursor.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/IndexedCursor.java @@ -34,6 +34,8 @@ import com.amazon.carbonado.cursor.AbstractCursor; import com.amazon.carbonado.spi.RepairExecutor; +import com.amazon.carbonado.synthetic.SyntheticStorableReferenceAccess; + /** * Wraps another cursor which contains index entries and extracts master * objects from them. @@ -43,16 +45,16 @@ import com.amazon.carbonado.spi.RepairExecutor; class IndexedCursor extends AbstractCursor { private final Cursor mCursor; private final IndexedStorage mStorage; - private final IndexEntryGenerator mGenerator; + private final SyntheticStorableReferenceAccess mAccessor; private S mNext; IndexedCursor(Cursor indexEntryCursor, IndexedStorage storage, - IndexEntryGenerator indexEntryGenerator) { + SyntheticStorableReferenceAccess indexAccessor) { mCursor = indexEntryCursor; mStorage = storage; - mGenerator = indexEntryGenerator; + mAccessor = indexAccessor; } public void close() throws FetchException { @@ -68,13 +70,13 @@ class IndexedCursor extends AbstractCursor { final Storable indexEntry = mCursor.next(); S master = mStorage.mMasterStorage.prepare(); - mGenerator.copyToMasterPrimaryKey(indexEntry, master); + mAccessor.copyToMasterPrimaryKey(indexEntry, master); if (!master.tryLoad()) { LogFactory.getLog(getClass()).warn ("Master is missing for index entry: " + indexEntry); } else { - if (mGenerator.isConsistent(indexEntry, master)) { + if (mAccessor.isConsistent(indexEntry, master)) { mNext = master; return true; } @@ -85,9 +87,9 @@ class IndexedCursor extends AbstractCursor { try { final IndexedRepository repo = mStorage.mRepository; final Storage indexEntryStorage = - repo.getIndexEntryStorageFor(mGenerator.getIndexEntryClass()); + repo.getIndexEntryStorageFor(mAccessor.getReferenceClass()); Storable newIndexEntry = indexEntryStorage.prepare(); - mGenerator.copyFromMaster(newIndexEntry, master); + mAccessor.copyFromMaster(newIndexEntry, master); if (newIndexEntry.tryLoad()) { // Good, the correct index entry exists. We'll see @@ -108,11 +110,11 @@ class IndexedCursor extends AbstractCursor { try { // Reload master and verify inconsistency. S master = mStorage.mMasterStorage.prepare(); - mGenerator.copyToMasterPrimaryKey(indexEntry, master); + mAccessor.copyToMasterPrimaryKey(indexEntry, master); if (master.tryLoad()) { Storable newIndexEntry = indexEntryStorage.prepare(); - mGenerator.copyFromMaster(newIndexEntry, master); + mAccessor.copyFromMaster(newIndexEntry, master); newIndexEntry.tryInsert(); diff --git a/src/main/java/com/amazon/carbonado/repo/indexed/IndexedStorage.java b/src/main/java/com/amazon/carbonado/repo/indexed/IndexedStorage.java index 1abb064..b4440c9 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/IndexedStorage.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/IndexedStorage.java @@ -356,7 +356,7 @@ class IndexedStorage implements Storage, StorageAccess } Class indexEntryClass = - IndexEntryGenerator.getInstance(index).getIndexEntryClass(); + IndexEntryGenerator.getIndexAccess(index).getReferenceClass(); Storage indexEntryStorage; try { diff --git a/src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java b/src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java index 2d0617e..8219ac1 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java @@ -52,6 +52,8 @@ import com.amazon.carbonado.cursor.MergeSortBuffer; import com.amazon.carbonado.spi.RepairExecutor; +import com.amazon.carbonado.synthetic.SyntheticStorableReferenceAccess; + import com.amazon.carbonado.util.Throttle; /** @@ -85,7 +87,7 @@ class ManagedIndex implements IndexEntryAccessor { private final IndexedRepository mRepository; private final Storage mMasterStorage; private final StorableIndex mIndex; - private final IndexEntryGenerator mGenerator; + private final SyntheticStorableReferenceAccess mAccessor; private final Storage mIndexEntryStorage; private Query mSingleMatchQuery; @@ -93,14 +95,14 @@ class ManagedIndex implements IndexEntryAccessor { ManagedIndex(IndexedRepository repository, Storage masterStorage, StorableIndex index, - IndexEntryGenerator generator, + SyntheticStorableReferenceAccess accessor, Storage indexEntryStorage) throws SupportException { mRepository = repository; mMasterStorage = masterStorage; mIndex = index; - mGenerator = generator; + mAccessor = accessor; mIndexEntryStorage = indexEntryStorage; } @@ -145,17 +147,17 @@ class ManagedIndex implements IndexEntryAccessor { // Required by IndexEntryAccessor interface. public void copyToMasterPrimaryKey(Storable indexEntry, S master) { - mGenerator.copyToMasterPrimaryKey(indexEntry, master); + mAccessor.copyToMasterPrimaryKey(indexEntry, master); } // Required by IndexEntryAccessor interface. public void copyFromMaster(Storable indexEntry, S master) { - mGenerator.copyFromMaster(indexEntry, master); + mAccessor.copyFromMaster(indexEntry, master); } // Required by IndexEntryAccessor interface. public boolean isConsistent(Storable indexEntry, S master) { - return mGenerator.isConsistent(indexEntry, master); + return mAccessor.isConsistent(indexEntry, master); } // Required by IndexEntryAccessor interface. @@ -165,7 +167,7 @@ class ManagedIndex implements IndexEntryAccessor { // Required by IndexEntryAccessor interface. public Comparator getComparator() { - return mGenerator.getComparator(); + return mAccessor.getComparator(); } Cursor fetchOne(IndexedStorage storage, Object[] identityValues) @@ -188,7 +190,7 @@ class ManagedIndex implements IndexEntryAccessor { Cursor fetchFromIndexEntryQuery(IndexedStorage storage, Query indexEntryQuery) throws FetchException { - return new IndexedCursor(indexEntryQuery.fetch(), storage, mGenerator); + return new IndexedCursor(indexEntryQuery.fetch(), storage, mAccessor); } @Override @@ -534,7 +536,7 @@ class ManagedIndex implements IndexEntryAccessor { private Storable makeIndexEntry(S userStorable) throws PersistException { try { Storable indexEntry = mIndexEntryStorage.prepare(); - mGenerator.copyFromMaster(indexEntry, userStorable); + mAccessor.copyFromMaster(indexEntry, userStorable); return indexEntry; } catch (UndeclaredThrowableException e) { Throwable cause = e.getCause(); @@ -561,7 +563,7 @@ class ManagedIndex implements IndexEntryAccessor { // If index entry already exists, then index might be corrupt. { Storable freshEntry = mIndexEntryStorage.prepare(); - mGenerator.copyFromMaster(freshEntry, userStorable); + mAccessor.copyFromMaster(freshEntry, userStorable); indexEntry.copyVersionProperty(freshEntry); if (freshEntry.equals(indexEntry)) { // Existing entry is exactly what we expect. Return false @@ -591,7 +593,7 @@ class ManagedIndex implements IndexEntryAccessor { } Storable freshEntry = mIndexEntryStorage.prepare(); - mGenerator.copyFromMaster(freshEntry, freshUserStorable); + mAccessor.copyFromMaster(freshEntry, freshUserStorable); // Blow it away entry and re-insert. Don't simply update // the entry, since record version number may prevent -- cgit v1.2.3