diff options
Diffstat (limited to 'src/main/java/com/amazon')
8 files changed, 111 insertions, 12 deletions
diff --git a/src/main/java/com/amazon/carbonado/Authoritative.java b/src/main/java/com/amazon/carbonado/Authoritative.java new file mode 100644 index 0000000..70de7c2 --- /dev/null +++ b/src/main/java/com/amazon/carbonado/Authoritative.java @@ -0,0 +1,58 @@ +/*
+ * Copyright 2006 Amazon Technologies, Inc. or its affiliates.
+ * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
+ * of Amazon Technologies, Inc. or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.amazon.carbonado;
+
+import java.lang.annotation.*;
+
+/**
+ * Indicates that all accesses to this {@link Storable} must come from an
+ * authoritative source. When reading or writing the Storable, the {@link
+ * Repository} must guarantee that it is operating on the latest, correct
+ * version of the Storable.
+ *
+ * <p>Repositories that cache potentially stale Storables are required to
+ * ensure the cache is always up-to-date or bypass the cache
+ * altogether. Replicating repositories which may have a propagation delay must
+ * always access the master repository.
+ *
+ * <p>Repositories which provide eventual consistency but don't rely on a
+ * master <i>must</i> throw {@link UnsupportedTypeException}, as there is no
+ * authoritative source.
+ *
+ * <p>Example:<pre>
+ * <b>@Authoritative</b>
+ * @PrimaryKey("sequenceName")
+ * public interface SequenceValue extends Storable<SequenceValue> {
+ * String getSequenceName();
+ * void setSequenceName(String name);
+ *
+ * long getNextValue();
+ * void setNextValue(long value);
+ *
+ * ...
+ * }
+ * </pre>
+ *
+ * @author Brian S O'Neill
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface Authoritative {
+}
diff --git a/src/main/java/com/amazon/carbonado/UnsupportedTypeException.java b/src/main/java/com/amazon/carbonado/UnsupportedTypeException.java index 46535a4..fcc576c 100644 --- a/src/main/java/com/amazon/carbonado/UnsupportedTypeException.java +++ b/src/main/java/com/amazon/carbonado/UnsupportedTypeException.java @@ -19,8 +19,8 @@ package com.amazon.carbonado;
/**
- * Thrown by a dependent {@link Repository} which cannot support an {@link
- * Independent} {@link Storable}.
+ * Thrown by a {@link Repository} which cannot support a {@link Storable} which
+ * is declared as {@link Independent} or {@link Authoritative}.
*
* @author Brian S O'Neill
*/
diff --git a/src/main/java/com/amazon/carbonado/info/StorableInfo.java b/src/main/java/com/amazon/carbonado/info/StorableInfo.java index 1d6ed3e..796efb4 100644 --- a/src/main/java/com/amazon/carbonado/info/StorableInfo.java +++ b/src/main/java/com/amazon/carbonado/info/StorableInfo.java @@ -126,4 +126,9 @@ public interface StorableInfo<S extends Storable> { * @see com.amazon.carbonado.Independent
*/
boolean isIndependent();
+
+ /**
+ * @see com.amazon.carbonado.Authoritative
+ */
+ boolean isAuthoritative();
}
diff --git a/src/main/java/com/amazon/carbonado/info/StorableIntrospector.java b/src/main/java/com/amazon/carbonado/info/StorableIntrospector.java index 8da9c3e..29158f1 100644 --- a/src/main/java/com/amazon/carbonado/info/StorableIntrospector.java +++ b/src/main/java/com/amazon/carbonado/info/StorableIntrospector.java @@ -48,6 +48,7 @@ import org.cojen.util.WeakIdentityMap; import com.amazon.carbonado.Alias;
import com.amazon.carbonado.AlternateKeys;
+import com.amazon.carbonado.Authoritative;
import com.amazon.carbonado.FetchException;
import com.amazon.carbonado.Index;
import com.amazon.carbonado.Indexes;
@@ -220,7 +221,8 @@ public class StorableIntrospector { info = new Info<S>(type, aliases, indexes, properties,
primaryKey, alternateKeys,
- type.getAnnotation(Independent.class) != null);
+ type.getAnnotation(Independent.class) != null,
+ type.getAnnotation(Authoritative.class) != null);
cCache.put(type, new SoftReference<StorableInfo<?>>(info));
// Finish resolving join properties, after properties have been
@@ -1121,6 +1123,7 @@ public class StorableIntrospector { private final StorableKey<S> mPrimaryKey;
private final StorableKey<S>[] mAltKeys;
private final boolean mIndependent;
+ private final boolean mAuthoritative;
private transient String mName;
private transient Map<String, StorableProperty<S>> mPrimaryKeyProperties;
@@ -1131,7 +1134,8 @@ public class StorableIntrospector { Map<String, StorableProperty<S>> properties,
StorableKey<S> primaryKey,
StorableKey<S>[] altKeys,
- boolean independent)
+ boolean independent,
+ boolean authoritative)
{
mType = type;
mAliases = aliases;
@@ -1140,6 +1144,7 @@ public class StorableIntrospector { mPrimaryKey = primaryKey;
mAltKeys = altKeys;
mIndependent = independent;
+ mAuthoritative = authoritative;
}
public String getName() {
@@ -1282,6 +1287,10 @@ public class StorableIntrospector { public final boolean isIndependent() {
return mIndependent;
}
+
+ public final boolean isAuthoritative() {
+ return mAuthoritative;
+ }
}
private static class SKey<S extends Storable> implements StorableKey<S> {
diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableIntrospector.java b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableIntrospector.java index a12e0c9..c8ebfa8 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableIntrospector.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableIntrospector.java @@ -1020,6 +1020,10 @@ public class JDBCStorableIntrospector extends StorableIntrospector { return mMainInfo.isIndependent();
}
+ public boolean isAuthoritative() {
+ return mMainInfo.isAuthoritative();
+ }
+
public boolean isSupported() {
return mTableName != null;
}
diff --git a/src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedRepository.java b/src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedRepository.java index ebfd87f..11c11b6 100644 --- a/src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedRepository.java +++ b/src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedRepository.java @@ -50,6 +50,7 @@ import com.amazon.carbonado.capability.ShutdownCapability; import com.amazon.carbonado.capability.StorableInfoCapability;
import com.amazon.carbonado.info.Direction;
+import com.amazon.carbonado.info.StorableInfo;
import com.amazon.carbonado.info.StorableIntrospector;
import com.amazon.carbonado.spi.StorageCollection;
@@ -152,13 +153,31 @@ class ReplicatedRepository protected <S extends Storable> Storage<S> createStorage(Class<S> type)
throws SupportException, RepositoryException
{
- Storage<S> replicaStorage = mReplicaRepository.storageFor(type);
+ StorableInfo<S> info = StorableIntrospector.examine(type);
- try {
- return new ReplicatedStorage<S>(ReplicatedRepository.this, replicaStorage);
- } catch (UnsupportedTypeException e) {
- // Okay, no master.
- return replicaStorage;
+ if (info.isAuthoritative()) {
+ // Cannot rely on replica to be up-to-date, so always go to master.
+ try {
+ return mMasterRepository.storageFor(type);
+ } catch (UnsupportedTypeException e) {
+ if (info.isIndependent()) {
+ // Okay, no master. A standalone replica is
+ // considered to be authoritative.
+ return mReplicaRepository.storageFor(type);
+ }
+ throw e;
+ }
+ } else {
+ Storage<S> replicaStorage = mReplicaRepository.storageFor(type);
+ try {
+ return new ReplicatedStorage<S>(ReplicatedRepository.this, replicaStorage);
+ } catch (UnsupportedTypeException e) {
+ if (info.isIndependent()) {
+ // Okay, no master.
+ return replicaStorage;
+ }
+ throw e;
+ }
}
}
};
diff --git a/src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedStorage.java b/src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedStorage.java index 38c57c4..34b6880 100644 --- a/src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedStorage.java +++ b/src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedStorage.java @@ -64,7 +64,7 @@ class ReplicatedStorage<S extends Storable> implements Storage<S> { Storage<S> masterStorage =
creator.get(ReplicatedRepositoryBuilder.DEFAULT_MASTER_TIMEOUT_MILLIS);
mTrigger = new ReplicationTrigger<S>(aRepository, mReplicaStorage, masterStorage);
- addTrigger(mTrigger);
+ mReplicaStorage.addTrigger(mTrigger);
}
/**
@@ -76,7 +76,7 @@ class ReplicatedStorage<S extends Storable> implements Storage<S> { {
mReplicaStorage = replicaStorage;
mTrigger = new ReplicationTrigger<S>(aRepository, mReplicaStorage, masterStorage);
- addTrigger(mTrigger);
+ mReplicaStorage.addTrigger(mTrigger);
}
public Class<S> getStorableType() {
@@ -100,10 +100,12 @@ class ReplicatedStorage<S extends Storable> implements Storage<S> { }
public boolean addTrigger(Trigger<? super S> trigger) {
+ // FIXME: Should trigger be added to master?
return mReplicaStorage.addTrigger(trigger);
}
public boolean removeTrigger(Trigger<? super S> trigger) {
+ // FIXME: Should trigger be added to master?
return mReplicaStorage.removeTrigger(trigger);
}
diff --git a/src/main/java/com/amazon/carbonado/spi/StoredSequence.java b/src/main/java/com/amazon/carbonado/spi/StoredSequence.java index 0a5a19e..97f18ab 100644 --- a/src/main/java/com/amazon/carbonado/spi/StoredSequence.java +++ b/src/main/java/com/amazon/carbonado/spi/StoredSequence.java @@ -19,6 +19,7 @@ package com.amazon.carbonado.spi;
import com.amazon.carbonado.Alias;
+import com.amazon.carbonado.Authoritative;
import com.amazon.carbonado.Independent;
import com.amazon.carbonado.PrimaryKey;
import com.amazon.carbonado.Storable;
@@ -29,6 +30,7 @@ import com.amazon.carbonado.Storable; * @author Brian S O'Neill
*/
@PrimaryKey("name")
+@Authoritative
@Independent
@Alias("CARBONADO_SEQUENCE")
public interface StoredSequence extends Storable<StoredSequence> {
|