diff options
author | Brian S. O'Neill <bronee@gmail.com> | 2006-10-31 06:47:36 +0000 |
---|---|---|
committer | Brian S. O'Neill <bronee@gmail.com> | 2006-10-31 06:47:36 +0000 |
commit | 482c0c75a53ecb21325adde950438f879baf0e50 (patch) | |
tree | 9fe5f9a14a378df5358728f440c82d947fe9113c | |
parent | adb506cf387e5ce857f18c5a725f5f93c445b239 (diff) |
Index records no longer use join property to link to master and instead copy key property values. This allows IndexedRepository to properly load master records from the master storage.
5 files changed, 127 insertions, 186 deletions
diff --git a/src/main/java/com/amazon/carbonado/repo/indexed/IndexEntryAccessor.java b/src/main/java/com/amazon/carbonado/repo/indexed/IndexEntryAccessor.java index 16a980d..b107a6e 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/IndexEntryAccessor.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/IndexEntryAccessor.java @@ -40,12 +40,13 @@ public interface IndexEntryAccessor<S extends Storable> extends IndexInfo { Storage<?> getIndexEntryStorage();
/**
- * Loads the master object referenced by the given index entry.
+ * Sets all the primary key properties of the given master, using the
+ * applicable properties of the given index entry.
*
- * @param indexEntry index entry which points to master
- * @return master or null if missing
+ * @param indexEntry source of property values
+ * @param master master whose primary key properties will be set
*/
- S loadMaster(Storable indexEntry) throws FetchException;
+ void copyToMasterPrimaryKey(Storable indexEntry, S master);
/**
* Sets all the properties of the given index entry, using the applicable
@@ -54,7 +55,7 @@ public interface IndexEntryAccessor<S extends Storable> extends IndexInfo { * @param indexEntry index entry whose properties will be set
* @param master source of property values
*/
- void setAllProperties(Storable indexEntry, S master);
+ void copyFromMaster(Storable indexEntry, S master);
/**
* Returns true if the properties of the given index entry match those
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 3da1a5b..4059ac3 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/IndexEntryGenerator.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/IndexEntryGenerator.java @@ -132,13 +132,14 @@ class IndexEntryGenerator <S extends Storable> { }
/**
- * Loads the master object referenced by the given index entry.
+ * Sets all the primary key properties of the given master, using the
+ * applicable properties of the given index entry.
*
- * @param indexEntry index entry which points to master
- * @return master or null if missing
+ * @param indexEntry source of property values
+ * @param master master whose primary key properties will be set
*/
- public S loadMaster(Storable ref) throws FetchException {
- return mBuilder.loadMaster(ref);
+ public void copyToMasterPrimaryKey(Storable indexEntry, S master) {
+ mBuilder.copyToMasterPrimaryKey(indexEntry, master);
}
/**
@@ -148,8 +149,8 @@ class IndexEntryGenerator <S extends Storable> { * @param indexEntry index entry whose properties will be set
* @param master source of property values
*/
- public void setAllProperties(Storable indexEntry, S master) {
- mBuilder.setAllProperties(indexEntry, master);
+ public void copyFromMaster(Storable indexEntry, S master) {
+ mBuilder.copyFromMaster(indexEntry, master);
}
/**
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 3a50a84..892af49 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/IndexedCursor.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/IndexedCursor.java @@ -65,8 +65,11 @@ class IndexedCursor<S extends Storable> extends AbstractCursor<S> { }
while (mCursor.hasNext()) {
final Storable indexEntry = mCursor.next();
- S master = mGenerator.loadMaster(indexEntry);
- if (master == null) {
+
+ S master = mStorage.mMasterStorage.prepare();
+ mGenerator.copyToMasterPrimaryKey(indexEntry, master);
+
+ if (!master.tryLoad()) {
LogFactory.getLog(getClass()).warn
("Master is missing for index entry: " + indexEntry);
} else {
@@ -83,7 +86,7 @@ class IndexedCursor<S extends Storable> extends AbstractCursor<S> { final Storage<?> indexEntryStorage =
repo.getIndexEntryStorageFor(mGenerator.getIndexEntryClass());
Storable newIndexEntry = indexEntryStorage.prepare();
- mGenerator.setAllProperties(newIndexEntry, master);
+ mGenerator.copyFromMaster(newIndexEntry, master);
if (newIndexEntry.tryLoad()) {
// Good, the correct index entry exists. We'll see
@@ -103,18 +106,18 @@ class IndexedCursor<S extends Storable> extends AbstractCursor<S> { Transaction txn = repo.enterTransaction();
try {
// Reload master and verify inconsistency.
- S master = mGenerator.loadMaster(indexEntry);
- if (mGenerator.isConsistent(indexEntry, master)) {
- return;
- }
+ S master = mStorage.mMasterStorage.prepare();
+ mGenerator.copyToMasterPrimaryKey(indexEntry, master);
- Storable newIndexEntry = indexEntryStorage.prepare();
- mGenerator.setAllProperties(newIndexEntry, master);
+ if (master.tryLoad()) {
+ Storable newIndexEntry = indexEntryStorage.prepare();
+ mGenerator.copyFromMaster(newIndexEntry, master);
- newIndexEntry.tryInsert();
+ newIndexEntry.tryInsert();
- indexEntry.tryDelete();
- txn.commit();
+ indexEntry.tryDelete();
+ txn.commit();
+ }
} catch (FetchException fe) {
LogFactory.getLog(IndexedCursor.class).warn
("Unable to check if repair required for " +
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 cfc399b..80ad172 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java @@ -126,13 +126,13 @@ class ManagedIndex<S extends Storable> implements IndexEntryAccessor<S> { }
// Required by IndexEntryAccessor interface.
- public S loadMaster(Storable indexEntry) throws FetchException {
- return mGenerator.loadMaster(indexEntry);
+ public void copyToMasterPrimaryKey(Storable indexEntry, S master) {
+ mGenerator.copyToMasterPrimaryKey(indexEntry, master);
}
// Required by IndexEntryAccessor interface.
- public void setAllProperties(Storable indexEntry, S master) {
- mGenerator.setAllProperties(indexEntry, master);
+ public void copyFromMaster(Storable indexEntry, S master) {
+ mGenerator.copyFromMaster(indexEntry, master);
}
// Required by IndexEntryAccessor interface.
@@ -388,7 +388,7 @@ class ManagedIndex<S extends Storable> implements IndexEntryAccessor<S> { private Storable makeIndexEntry(S userStorable) {
Storable indexEntry = mIndexEntryStorage.prepare();
- mGenerator.setAllProperties(indexEntry, userStorable);
+ mGenerator.copyFromMaster(indexEntry, userStorable);
return indexEntry;
}
@@ -403,7 +403,7 @@ class ManagedIndex<S extends Storable> implements IndexEntryAccessor<S> { // If index entry already exists, then index might be corrupt.
{
Storable freshEntry = mIndexEntryStorage.prepare();
- mGenerator.setAllProperties(freshEntry, userStorable);
+ mGenerator.copyFromMaster(freshEntry, userStorable);
indexEntry.copyVersionProperty(freshEntry);
if (freshEntry.equals(indexEntry)) {
// Existing entry is exactly what we expect. Return false
@@ -433,7 +433,7 @@ class ManagedIndex<S extends Storable> implements IndexEntryAccessor<S> { }
Storable freshEntry = mIndexEntryStorage.prepare();
- mGenerator.setAllProperties(freshEntry, freshUserStorable);
+ mGenerator.copyFromMaster(freshEntry, freshUserStorable);
// Blow it away entry and re-insert. Don't simply update
// the entry, since record version number may prevent
diff --git a/src/main/java/com/amazon/carbonado/synthetic/SyntheticStorableReferenceBuilder.java b/src/main/java/com/amazon/carbonado/synthetic/SyntheticStorableReferenceBuilder.java index 443d826..78bf22e 100644 --- a/src/main/java/com/amazon/carbonado/synthetic/SyntheticStorableReferenceBuilder.java +++ b/src/main/java/com/amazon/carbonado/synthetic/SyntheticStorableReferenceBuilder.java @@ -29,8 +29,6 @@ import java.util.Map; import java.util.Set;
import com.amazon.carbonado.FetchException;
-import com.amazon.carbonado.Join;
-import com.amazon.carbonado.Nullable;
import com.amazon.carbonado.Storable;
import com.amazon.carbonado.SupportException;
import com.amazon.carbonado.info.Direction;
@@ -73,10 +71,10 @@ import org.cojen.util.BeanComparator; public class SyntheticStorableReferenceBuilder<S extends Storable>
implements SyntheticBuilder {
- // The property setter will be called something like "setAllProperties_0"
- private static final String ALL_PROPERTIES_PREFIX = "setAllProperties_";
+ // The property setter will be called something like "copyFromMaster_0"
+ private static final String COPY_FROM_MASTER_PREFIX = "copyFromMaster_";
- private static final String MASTER_PROPERTY_PREFIX = "master_";
+ private static final String COPY_TO_MASTER_PK_PREFIX = "copyToMasterPk_";
private static final String IS_CONSISTENT_PREFIX = "getIsConsistent_";
@@ -112,23 +110,14 @@ public class SyntheticStorableReferenceBuilder<S extends Storable> // are retrieved from the master.
private List<StorableProperty> mCommonProps;
- // The builder generates and retains a reference to various
- // methods which make it possible to implement the "StorableReferenceBean"
- // interface
- // (if there were any need to formalize it): loadMaster,
- // copyCommonProperties,
- // setAllProperties, and isConsistent
- private String mNameForSetAllPropertiesMethod;
-
- private Method mSetAllPropertiesMethod;
-
- private String mNameForIsConsistentMethod;
+ private String mCopyFromMasterMethodName;
+ private Method mCopyFromMasterMethod;
+ private String mIsConsistentMethodName;
private Method mIsConsistentMethod;
- private String mNameForGetMasterMethod;
-
- private Method mGetMasterMethod;
+ private String mCopyToMasterPkMethodName;
+ private Method mCopyToMasterPkMethod;
private Comparator<? extends Storable> mComparator;
@@ -227,7 +216,7 @@ public class SyntheticStorableReferenceBuilder<S extends Storable> * @see com.amazon.carbonado.synthetic.SyntheticBuilder#getStorableClass()
*/
public Class<? extends Storable> getStorableClass() throws IllegalStateException {
- if (null == mSyntheticClass) {
+ if (mSyntheticClass == null) {
mSyntheticClass = mBuilder.getStorableClass();
// We need a comparator which follows the same order as the generated
@@ -265,7 +254,7 @@ public class SyntheticStorableReferenceBuilder<S extends Storable> */
public SyntheticProperty addKeyProperty(String name, Direction direction) {
StorableProperty<S> prop = mMasterStorableInfo.getAllProperties().get(name);
- if (null == prop) {
+ if (prop == null) {
throw new IllegalArgumentException(name + " is not a property of "
+ mMasterStorableInfo.getName());
}
@@ -355,28 +344,26 @@ public class SyntheticStorableReferenceBuilder<S extends Storable> }
/**
- * Loads the master object referenced by the given index entry.
+ * Sets all the primary key properties of the given master, using the
+ * applicable properties of the given index entry.
*
- * @param indexEntry
- * index entry which points to master
- * @return master or null if missing
+ * @param indexEntry source of property values
+ * @param master master whose primary key properties will be set
*/
- public S loadMaster(Storable indexEntry) throws FetchException {
- if (null == mGetMasterMethod) {
+ public void copyToMasterPrimaryKey(Storable indexEntry, S master) {
+ if (mCopyToMasterPkMethod == null) {
try {
- mGetMasterMethod = getStorableClass().getMethod(mNameForGetMasterMethod,
- (Class[]) null);
+ mCopyToMasterPkMethod =
+ mSyntheticClass.getMethod(mCopyToMasterPkMethodName, mMasterStorableClass);
} catch (NoSuchMethodException e) {
throw new UndeclaredThrowableException(e);
}
}
try {
- return (S) mGetMasterMethod.invoke(indexEntry, (Object[]) null);
+ mCopyToMasterPkMethod.invoke(indexEntry, master);
} catch (Exception e) {
- ThrowUnchecked.fireFirstDeclaredCause(e, FetchException.class);
- // Not reached.
- return null;
+ ThrowUnchecked.fireFirstDeclaredCause(e);
}
}
@@ -384,24 +371,21 @@ public class SyntheticStorableReferenceBuilder<S extends Storable> * 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
+ * @param indexEntry index entry whose properties will be set
+ * @param master source of property values
*/
- public void setAllProperties(Storable indexEntry, S master) {
-
- if (null == mSetAllPropertiesMethod) {
+ public void copyFromMaster(Storable indexEntry, S master) {
+ if (mCopyFromMasterMethod == null) {
try {
- mSetAllPropertiesMethod = mSyntheticClass.getMethod(mNameForSetAllPropertiesMethod,
- mMasterStorableClass);
+ mCopyFromMasterMethod =
+ mSyntheticClass.getMethod(mCopyFromMasterMethodName, mMasterStorableClass);
} catch (NoSuchMethodException e) {
throw new UndeclaredThrowableException(e);
}
}
try {
- mSetAllPropertiesMethod.invoke(indexEntry, master);
+ mCopyFromMasterMethod.invoke(indexEntry, master);
} catch (Exception e) {
ThrowUnchecked.fireFirstDeclaredCause(e);
}
@@ -410,7 +394,7 @@ public class SyntheticStorableReferenceBuilder<S extends Storable> /**
* Returns true if the properties of the given index entry match those
* contained in the master, excluding any version property. This will
- * always return true after a call to setAllProperties.
+ * always return true after a call to copyFromMaster.
*
* @param indexEntry
* index entry whose properties will be tested
@@ -418,11 +402,10 @@ public class SyntheticStorableReferenceBuilder<S extends Storable> * source of property values
*/
public boolean isConsistent(Storable indexEntry, S master) {
-
- if (null == mIsConsistentMethod) {
+ if (mIsConsistentMethod == null) {
try {
- mIsConsistentMethod = mSyntheticClass.getMethod(mNameForIsConsistentMethod,
- mMasterStorableClass);
+ mIsConsistentMethod =
+ mSyntheticClass.getMethod(mIsConsistentMethodName, mMasterStorableClass);
} catch (NoSuchMethodException e) {
throw new UndeclaredThrowableException(e);
}
@@ -445,96 +428,35 @@ public class SyntheticStorableReferenceBuilder<S extends Storable> }
/**
- * Create methods for copying properties to and from and for looking up the
- * master object
+ * Create methods for copying properties and testing properties.
*
* @throws amazon.carbonado.SupportException
*/
private void addSpecialMethods(ClassFile cf) throws SupportException {
- TypeDesc masterStorableType = TypeDesc.forClass(mMasterStorableClass);
- // The set master method is used to load the master object and set it
- // into the master property of this reference storable
- String nameForSetMasterMethod;
-
// Generate safe names for special methods.
{
- String safeName = generateSafePropertyName(mMasterStorableInfo,
- MASTER_PROPERTY_PREFIX);
- // Don't need to pass the class in, it's not a boolean so we'll get
- // a "get<foo>" flavor read method
- mNameForGetMasterMethod = SyntheticProperty.makeReadMethodName(safeName,
- Object.class);
- nameForSetMasterMethod = SyntheticProperty.makeWriteMethodName(safeName);
- mNameForSetAllPropertiesMethod = generateSafeMethodName(mMasterStorableInfo,
- ALL_PROPERTIES_PREFIX);
- mNameForIsConsistentMethod = generateSafeMethodName(mMasterStorableInfo, IS_CONSISTENT_PREFIX);
- }
+ mCopyToMasterPkMethodName =
+ generateSafeMethodName(mMasterStorableInfo, COPY_TO_MASTER_PK_PREFIX);
- // Add a method which sets all properties of index entry object from
- // master object.
- {
- // void setAllProperties(Storable master)
- TypeDesc[] params = new TypeDesc[] { masterStorableType };
- MethodInfo mi = cf.addMethod(Modifiers.PUBLIC,
- mNameForSetAllPropertiesMethod,
- null,
- params);
- CodeBuilder b = new CodeBuilder(mi);
+ mCopyFromMasterMethodName =
+ generateSafeMethodName(mMasterStorableInfo, COPY_FROM_MASTER_PREFIX);
- // Set Join property: this.setMaster(master)
- // (stash a reference to the master object)
- b.loadThis();
- b.loadLocal(b.getParameter(0));
- b.invokeVirtual(nameForSetMasterMethod, null, params);
-
- // Copy across all the properties. At this point they've
- // all been added to the property list
- for (StorableProperty prop : mCommonProps) {
- if (prop.isPrimaryKeyMember()) {
- // No need to set this property, since setting join to
- // master already took care of it.
- continue;
- }
- b.loadThis();
- b.loadLocal(b.getParameter(0));
- if (prop.getReadMethod() == null) {
- throw new SupportException("Property does not have a public accessor method: "
- + prop);
- }
- b.invoke(prop.getReadMethod());
- b.invokeVirtual(prop.getWriteMethodName(),
- null,
- new TypeDesc[] { TypeDesc.forClass(prop.getType()) });
-
- }
- b.returnVoid();
+ mIsConsistentMethodName =
+ generateSafeMethodName(mMasterStorableInfo, IS_CONSISTENT_PREFIX);
}
- // Add a join property for looking up master object. Since binding is
- // based on primary key properties which match to index entry object,
- // the join is natural -- no need to specify internal and external
- // properties.
- {
- MethodInfo mi = cf.addMethod(Modifiers.PUBLIC_ABSTRACT,
- mNameForGetMasterMethod,
- masterStorableType,
- null);
- mi.addException(TypeDesc.forClass(FetchException.class));
- mi.addRuntimeVisibleAnnotation(TypeDesc.forClass(Join.class));
- mi.addRuntimeVisibleAnnotation(TypeDesc.forClass(Nullable.class));
-
- cf.addMethod(Modifiers.PUBLIC_ABSTRACT,
- nameForSetMasterMethod,
- null,
- new TypeDesc[] { masterStorableType });
- }
+ // Add methods which copies properties between master and index entry.
+ addCopyMethod(cf, mCopyFromMasterMethodName);
+ addCopyMethod(cf, mCopyToMasterPkMethodName);
+
+ TypeDesc masterStorableType = TypeDesc.forClass(mMasterStorableClass);
// Add a method which tests all properties of index entry object
// against master object, excluding the version property.
{
TypeDesc[] params = new TypeDesc[] {masterStorableType};
MethodInfo mi = cf.addMethod
- (Modifiers.PUBLIC, mNameForIsConsistentMethod, TypeDesc.BOOLEAN, params);
+ (Modifiers.PUBLIC, mIsConsistentMethodName, TypeDesc.BOOLEAN, params);
CodeBuilder b = new CodeBuilder(mi);
for (StorableProperty prop : mCommonProps) {
@@ -549,9 +471,56 @@ public class SyntheticStorableReferenceBuilder<S extends Storable> b.loadConstant(true);
b.returnValue(TypeDesc.BOOLEAN);
}
+ }
+ private void addCopyMethod(ClassFile cf, String methodName) throws SupportException {
+ TypeDesc masterStorableType = TypeDesc.forClass(mMasterStorableClass);
+ // void copyXxMaster(Storable master)
+ TypeDesc[] params = new TypeDesc[] { masterStorableType };
+ MethodInfo mi = cf.addMethod(Modifiers.PUBLIC, methodName, null, params);
+ CodeBuilder b = new CodeBuilder(mi);
+
+ boolean toMasterPk;
+ if (methodName.equals(mCopyToMasterPkMethodName)) {
+ toMasterPk = true;
+ } else if (methodName.equals(mCopyFromMasterMethodName)) {
+ toMasterPk = false;
+ } else {
+ throw new IllegalArgumentException();
+ }
+ for (StorableProperty prop : mCommonProps) {
+ if (toMasterPk && !prop.isPrimaryKeyMember()) {
+ continue;
+ }
+
+ if (prop.getReadMethod() == null) {
+ throw new SupportException
+ ("Property does not have a public accessor method: " + prop);
+ }
+ if (prop.getWriteMethod() == null) {
+ throw new SupportException
+ ("Property does not have a public mutator method: " + prop);
+ }
+
+ TypeDesc propType = TypeDesc.forClass(prop.getType());
+
+ if (toMasterPk) {
+ b.loadLocal(b.getParameter(0));
+ b.loadThis();
+ b.invokeVirtual(prop.getReadMethodName(), propType, null);
+ b.invoke(prop.getWriteMethod());
+ } else if (methodName.equals(mCopyFromMasterMethodName)) {
+ b.loadThis();
+ b.loadLocal(b.getParameter(0));
+ b.invoke(prop.getReadMethod());
+ b.invokeVirtual(prop.getWriteMethodName(), null, new TypeDesc[] {propType});
+ }
+
+ }
+
+ b.returnVoid();
}
/**
@@ -589,10 +558,6 @@ public class SyntheticStorableReferenceBuilder<S extends Storable> private String generateSafeMethodName(StorableInfo info, String prefix) {
Class type = info.getStorableType();
-// if (!methodExists(type, prefix)) {
-// return prefix;
-// }
-
// Try a few times to generate a unique name. There's nothing special
// about choosing 100 as the limit.
int value = 0;
@@ -609,35 +574,6 @@ public class SyntheticStorableReferenceBuilder<S extends Storable> }
/**
- * Generates a property name which doesn't clash with any already defined.
- */
- protected String generateSafePropertyName(StorableInfo info, String prefix)
- {
- Map<String, ? extends StorableProperty> properties = info.getAllProperties();
- Class type = info.getStorableType();
-
- // Try a few times to generate unique name. There's nothing special
- // about choosing 100 as the limit.
- for (int i = 0; i < 100; i++) {
- String name = prefix + i;
- if (properties.containsKey(name)) {
- continue;
- }
- if (methodExists(type, SyntheticProperty.makeReadMethodName(name,
- type))) {
- continue;
- }
- if (methodExists(type, SyntheticProperty.makeWriteMethodName(name))) {
- continue;
- }
- return name;
- }
-
- throw new InternalError("Unable to create unique property name starting with: "
- + prefix);
- }
-
- /**
* Look for conflicting method names
*/
private boolean methodExists(Class clazz, String name) {
|