From cee2677c3d2d2d31a5a921b625050fbb4ea45d59 Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Thu, 7 Dec 2006 08:12:31 +0000 Subject: Added @Authoritative annotation. --- .../java/com/amazon/carbonado/Authoritative.java | 58 ++++++++++++++++++++++ .../amazon/carbonado/UnsupportedTypeException.java | 4 +- .../com/amazon/carbonado/info/StorableInfo.java | 5 ++ .../carbonado/info/StorableIntrospector.java | 13 ++++- .../repo/jdbc/JDBCStorableIntrospector.java | 4 ++ .../repo/replicated/ReplicatedRepository.java | 31 +++++++++--- .../repo/replicated/ReplicatedStorage.java | 6 ++- .../com/amazon/carbonado/spi/StoredSequence.java | 2 + 8 files changed, 111 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/amazon/carbonado/Authoritative.java (limited to 'src/main/java') 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. + * + *

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. + * + *

Repositories which provide eventual consistency but don't rely on a + * master must throw {@link UnsupportedTypeException}, as there is no + * authoritative source. + * + *

Example:

+ * @Authoritative
+ * @PrimaryKey("sequenceName")
+ * public interface SequenceValue extends Storable<SequenceValue> {
+ *     String getSequenceName();
+ *     void setSequenceName(String name);
+ *
+ *     long getNextValue();
+ *     void setNextValue(long value);
+ *
+ *     ...
+ * }
+ * 
+ * + * @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 { * @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(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>(info)); // Finish resolving join properties, after properties have been @@ -1121,6 +1123,7 @@ public class StorableIntrospector { private final StorableKey mPrimaryKey; private final StorableKey[] mAltKeys; private final boolean mIndependent; + private final boolean mAuthoritative; private transient String mName; private transient Map> mPrimaryKeyProperties; @@ -1131,7 +1134,8 @@ public class StorableIntrospector { Map> properties, StorableKey primaryKey, StorableKey[] 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 implements StorableKey { 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 Storage createStorage(Class type) throws SupportException, RepositoryException { - Storage replicaStorage = mReplicaRepository.storageFor(type); + StorableInfo info = StorableIntrospector.examine(type); - try { - return new ReplicatedStorage(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 replicaStorage = mReplicaRepository.storageFor(type); + try { + return new ReplicatedStorage(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 implements Storage { Storage masterStorage = creator.get(ReplicatedRepositoryBuilder.DEFAULT_MASTER_TIMEOUT_MILLIS); mTrigger = new ReplicationTrigger(aRepository, mReplicaStorage, masterStorage); - addTrigger(mTrigger); + mReplicaStorage.addTrigger(mTrigger); } /** @@ -76,7 +76,7 @@ class ReplicatedStorage implements Storage { { mReplicaStorage = replicaStorage; mTrigger = new ReplicationTrigger(aRepository, mReplicaStorage, masterStorage); - addTrigger(mTrigger); + mReplicaStorage.addTrigger(mTrigger); } public Class getStorableType() { @@ -100,10 +100,12 @@ class ReplicatedStorage implements Storage { } public boolean addTrigger(Trigger trigger) { + // FIXME: Should trigger be added to master? return mReplicaStorage.addTrigger(trigger); } public boolean removeTrigger(Trigger 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 { -- cgit v1.2.3