From a05e568387db065a709530b72744174dbe9b9802 Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Thu, 30 Jun 2011 23:38:06 +0000 Subject: Skip corrupt master entries, allow existing index entry. --- .../carbonado/repo/indexed/IndexedCursor.java | 140 +++++++++++---------- .../carbonado/repo/indexed/ManagedIndex.java | 49 +------- 2 files changed, 78 insertions(+), 111 deletions(-) (limited to 'src/main/java/com/amazon/carbonado') 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 adafb34..bce6975 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/IndexedCursor.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/IndexedCursor.java @@ -22,6 +22,7 @@ import java.util.NoSuchElementException; import org.apache.commons.logging.LogFactory; +import com.amazon.carbonado.CorruptEncodingException; import com.amazon.carbonado.Cursor; import com.amazon.carbonado.FetchException; import com.amazon.carbonado.PersistException; @@ -72,84 +73,91 @@ class IndexedCursor extends AbstractCursor { S master = mStorage.mMasterStorage.prepare(); mAccessor.copyToMasterPrimaryKey(indexEntry, master); - if (!master.tryLoad()) { - LogFactory.getLog(getClass()).warn - ("Master is missing for index entry: " + indexEntry); - } else { - if (mAccessor.isConsistent(indexEntry, master)) { + try { + if (!master.tryLoad()) { + LogFactory.getLog(getClass()).warn + ("Master is missing for index entry: " + indexEntry); + continue; + } + } catch (CorruptEncodingException e) { + LogFactory.getLog(getClass()).error + ("Master record for index entry is corrupt: " + indexEntry, e); + continue; + } + + if (mAccessor.isConsistent(indexEntry, master)) { + mNext = master; + return true; + } + + // This index entry is stale. Repair is needed. + + // Insert a correct index entry, just to be sure. + try { + final IndexedRepository repo = mStorage.mRepository; + final Storage indexEntryStorage = + repo.getIndexEntryStorageFor(mAccessor.getReferenceClass()); + Storable newIndexEntry = indexEntryStorage.prepare(); + mAccessor.copyFromMaster(newIndexEntry, master); + + if (newIndexEntry.tryLoad()) { + // Good, the correct index entry exists. We'll see + // the master record eventually, so skip. + } else { + // We have no choice but to return the master, at + // the risk of seeing it multiple times. This is + // better than seeing it never. + LogFactory.getLog(getClass()).warn + ("Inconsistent index entry: " + indexEntry + ", " + master); mNext = master; - return true; } - // This index entry is stale. Repair is needed. - - // Insert a correct index entry, just to be sure. - try { - final IndexedRepository repo = mStorage.mRepository; - final Storage indexEntryStorage = - repo.getIndexEntryStorageFor(mAccessor.getReferenceClass()); - Storable newIndexEntry = indexEntryStorage.prepare(); - mAccessor.copyFromMaster(newIndexEntry, master); - - if (newIndexEntry.tryLoad()) { - // Good, the correct index entry exists. We'll see - // the master record eventually, so skip. - } else { - // We have no choice but to return the master, at - // the risk of seeing it multiple times. This is - // better than seeing it never. - LogFactory.getLog(getClass()).warn - ("Inconsistent index entry: " + indexEntry + ", " + master); - mNext = master; - } + // Repair the stale index entry. + RepairExecutor.execute(new Runnable() { + public void run() { + Transaction txn = repo.enterTransaction(); + try { + // Reload master and verify inconsistency. + S master = mStorage.mMasterStorage.prepare(); + mAccessor.copyToMasterPrimaryKey(indexEntry, master); + + if (master.tryLoad()) { + Storable newIndexEntry = indexEntryStorage.prepare(); + mAccessor.copyFromMaster(newIndexEntry, master); - // Repair the stale index entry. - RepairExecutor.execute(new Runnable() { - public void run() { - Transaction txn = repo.enterTransaction(); + newIndexEntry.tryInsert(); + + indexEntry.tryDelete(); + txn.commit(); + } + } catch (FetchException fe) { + LogFactory.getLog(IndexedCursor.class).warn + ("Unable to check if repair required for " + + "inconsistent index entry " + + indexEntry, fe); + } catch (PersistException pe) { + LogFactory.getLog(IndexedCursor.class).error + ("Unable to repair inconsistent index entry " + + indexEntry, pe); + } finally { try { - // Reload master and verify inconsistency. - S master = mStorage.mMasterStorage.prepare(); - mAccessor.copyToMasterPrimaryKey(indexEntry, master); - - if (master.tryLoad()) { - Storable newIndexEntry = indexEntryStorage.prepare(); - mAccessor.copyFromMaster(newIndexEntry, master); - - newIndexEntry.tryInsert(); - - indexEntry.tryDelete(); - txn.commit(); - } - } catch (FetchException fe) { - LogFactory.getLog(IndexedCursor.class).warn - ("Unable to check if repair required for " + - "inconsistent index entry " + - indexEntry, fe); + txn.exit(); } catch (PersistException pe) { LogFactory.getLog(IndexedCursor.class).error ("Unable to repair inconsistent index entry " + indexEntry, pe); - } finally { - try { - txn.exit(); - } catch (PersistException pe) { - LogFactory.getLog(IndexedCursor.class).error - ("Unable to repair inconsistent index entry " + - indexEntry, pe); - } } } - }); - } catch (Exception re) { - LogFactory.getLog(getClass()).error - ("Unable to inspect inconsistent index entry " + - indexEntry, re); - } + } + }); + } catch (Exception re) { + LogFactory.getLog(getClass()).error + ("Unable to inspect inconsistent index entry " + + indexEntry, re); + } - if (mNext != null) { - return true; - } + if (mNext != null) { + return true; } } } catch (NoSuchElementException e) { 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 4e99a06..7a597b6 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java @@ -660,61 +660,20 @@ class ManagedIndex implements IndexEntryAccessor { return true; } - // FIXME: This code effectively does nothing and always returns false. - // If index entry already exists, then index might be corrupt. try { Storable freshEntry = mIndexEntryStorage.prepare(); mAccessor.copyFromMaster(freshEntry, userStorable); + freshEntry.load(); indexEntry.copyVersionProperty(freshEntry); if (freshEntry.equals(indexEntry)) { - // Existing entry is exactly what we expect. Return false if - // alternate key constraint, since this is user error. - return !isUnique(); + // Existing entry is fine. + return true; } } catch (FetchException e) { throw e.toPersistException(); } - // Run the repair outside a transaction. - - RepairExecutor.execute(new Runnable() { - public void run() { - try { - // Blow it away entry and re-insert. Don't simply update - // the entry, since record version number may prevent - // update. - - // Since we may be running outside transaction now, user - // storable may have changed. Reload to get latest data. - - S freshUserStorable = (S) userStorable.copy(); - if (!freshUserStorable.tryLoad()) { - // Gone now, nothing we can do. Assume index entry - // was properly deleted. - return; - } - - Storable freshEntry = mIndexEntryStorage.prepare(); - mAccessor.copyFromMaster(freshEntry, freshUserStorable); - - // Blow it away entry and re-insert. Don't simply update - // the entry, since record version number may prevent - // update. - freshEntry.tryDelete(); - freshEntry.tryInsert(); - } catch (FetchException fe) { - LogFactory.getLog(IndexedStorage.class).warn - ("Unable to check if repair is required: " + - userStorable.toStringKeyOnly(), fe); - } catch (PersistException pe) { - LogFactory.getLog(IndexedStorage.class).error - ("Unable to repair index entry for " + - userStorable.toStringKeyOnly(), pe); - } - } - }); - - return true; + return false; } } -- cgit v1.2.3