summaryrefslogtreecommitdiff
path: root/src/main/java/com/amazon/carbonado
diff options
context:
space:
mode:
authorBrian S. O'Neill <bronee@gmail.com>2006-10-31 06:47:36 +0000
committerBrian S. O'Neill <bronee@gmail.com>2006-10-31 06:47:36 +0000
commit482c0c75a53ecb21325adde950438f879baf0e50 (patch)
tree9fe5f9a14a378df5358728f440c82d947fe9113c /src/main/java/com/amazon/carbonado
parentadb506cf387e5ce857f18c5a725f5f93c445b239 (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.
Diffstat (limited to 'src/main/java/com/amazon/carbonado')
-rw-r--r--src/main/java/com/amazon/carbonado/repo/indexed/IndexEntryAccessor.java11
-rw-r--r--src/main/java/com/amazon/carbonado/repo/indexed/IndexEntryGenerator.java15
-rw-r--r--src/main/java/com/amazon/carbonado/repo/indexed/IndexedCursor.java27
-rw-r--r--src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java14
-rw-r--r--src/main/java/com/amazon/carbonado/synthetic/SyntheticStorableReferenceBuilder.java246
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) {