From 332cccc96e2a9014cbc1d614fedc35048315b53a Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Tue, 31 Oct 2006 18:04:54 +0000 Subject: Cope with errors during resync. --- .../com/amazon/carbonado/layout/LayoutFactory.java | 150 +++++++++++++-------- .../carbonado/repo/sleepycat/BDBStorage.java | 44 +++--- 2 files changed, 119 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/main/java/com/amazon/carbonado/layout/LayoutFactory.java b/src/main/java/com/amazon/carbonado/layout/LayoutFactory.java index 89e139d..6deb3ee 100644 --- a/src/main/java/com/amazon/carbonado/layout/LayoutFactory.java +++ b/src/main/java/com/amazon/carbonado/layout/LayoutFactory.java @@ -33,6 +33,9 @@ import com.amazon.carbonado.RepositoryException; import com.amazon.carbonado.Storable; import com.amazon.carbonado.Storage; import com.amazon.carbonado.Transaction; +import com.amazon.carbonado.UniqueConstraintException; + +import com.amazon.carbonado.capability.ResyncCapability; import com.amazon.carbonado.info.StorableInfo; import com.amazon.carbonado.info.StorableIntrospector; @@ -86,73 +89,102 @@ public class LayoutFactory implements LayoutCapability { StorableInfo info = StorableIntrospector.examine(type); - Transaction txn = mRepository.enterTopTransaction(IsolationLevel.READ_COMMITTED); - txn.setForUpdate(true); - try { - // If type represents a new generation, then a new layout needs to - // be inserted. - Layout newLayout = null; - - for (int i=0; i= HASH_MULTIPLIERS.length - 1) { + // No more rehashes to attempt. This should be extremely, + // extremely rare, unless there is a bug somewhere. + throw new FetchException + ("Unable to generate unique layout identifier"); + } + } + + // If this point is reached, then type represents a new + // generation. Calculate next generation value and insert. + + assert(newLayout != null); + int generation = 0; + + Cursor cursor = mLayoutStorage + .query("storableTypeName = ?") + .with(info.getStorableType().getName()) + .orderBy("-generation") + .fetch(); + + try { + if (cursor.hasNext()) { + generation = cursor.next().getGeneration() + 1; + } + } finally { + cursor.close(); + } + + newLayout.insert(generation); + layout = newLayout; + + txn.commit(); + } finally { + txn.exit(); } - // If this point is reached, then there was a hash collision in - // the generated layout ID. This should be extremely rare. - // Rehash and try again. - - if (i >= HASH_MULTIPLIERS.length - 1) { - // No more rehashes to attempt. This should be extremely, - // extremely rare, unless there is a bug somewhere. - throw new FetchException("Unable to generate unique layout identifier"); - } + break; + } catch (UniqueConstraintException e) { + // This might be caused by a transient replication error. Retry + // a few times before throwing exception. Wait up to a second + // before each retry. + retryCount = e.backoff(e, retryCount, 1000); + resyncCap = mRepository.getCapability(ResyncCapability.class); } + } - // If this point is reached, then type represents a new - // generation. Calculate next generation value and insert. - - assert(newLayout != null); - int generation = 0; - - Cursor cursor = mLayoutStorage - .query("storableTypeName = ?") - .with(info.getStorableType().getName()) - .orderBy("-generation") - .fetch(); - + if (resyncCap != null) { + // Make sure that all layout records are sync'd. try { - if (cursor.hasNext()) { - generation = cursor.next().getGeneration() + 1; - } - } finally { - cursor.close(); + resyncCap.resync(StoredLayoutProperty.class, 1.0, null); + } catch (RepositoryException e) { + throw e.toPersistException(); } - - newLayout.insert(generation); - txn.commit(); - - return newLayout; - } finally { - txn.exit(); } + + return layout; } /** diff --git a/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBStorage.java b/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBStorage.java index 331c7b0..d8a3066 100644 --- a/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBStorage.java +++ b/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBStorage.java @@ -36,6 +36,7 @@ import com.amazon.carbonado.Storage; import com.amazon.carbonado.SupportException; import com.amazon.carbonado.Transaction; import com.amazon.carbonado.Trigger; +import com.amazon.carbonado.UniqueConstraintException; import com.amazon.carbonado.capability.IndexInfo; @@ -721,24 +722,35 @@ abstract class BDBStorage implements Storage, Storag } info.setDatabaseName(getStorableType().getName()); - Transaction txn = repo.enterTopTransaction(IsolationLevel.READ_COMMITTED); - txn.setForUpdate(true); - try { - if (!info.tryLoad()) { - if (layout == null) { - info.setEvolutionStrategy(StoredDatabaseInfo.EVOLUTION_NONE); - } else { - info.setEvolutionStrategy(StoredDatabaseInfo.EVOLUTION_STANDARD); - } - info.setCreationTimestamp(System.currentTimeMillis()); - info.setVersionNumber(0); - if (!readOnly) { - info.insert(); + // Try to insert metadata up to three times. + for (int retryCount = 3;;) { + try { + Transaction txn = repo.enterTopTransaction(IsolationLevel.READ_COMMITTED); + txn.setForUpdate(true); + try { + if (!info.tryLoad()) { + if (layout == null) { + info.setEvolutionStrategy(StoredDatabaseInfo.EVOLUTION_NONE); + } else { + info.setEvolutionStrategy(StoredDatabaseInfo.EVOLUTION_STANDARD); + } + info.setCreationTimestamp(System.currentTimeMillis()); + info.setVersionNumber(0); + if (!readOnly) { + info.insert(); + } + } + txn.commit(); + } finally { + txn.exit(); } + break; + } catch (UniqueConstraintException e) { + // This might be caused by a transient replication error. Retry + // a few times before throwing exception. Wait up to a second + // before each retry. + retryCount = e.backoff(e, retryCount, 1000); } - txn.commit(); - } finally { - txn.exit(); } return info; -- cgit v1.2.3