From 7283752c177a5d38776905f0fa115c2405ae2175 Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Thu, 26 Aug 2010 00:31:18 +0000 Subject: More robust corruption repairs. --- .../carbonado/repo/indexed/ManagedIndex.java | 38 ++++++++++++++++++---- .../repo/replicated/ReplicationTrigger.java | 25 +++++++++++++- 2 files changed, 55 insertions(+), 8 deletions(-) (limited to 'src/main') 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 1b6fe8d..2bb2f49 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java @@ -207,7 +207,18 @@ class ManagedIndex implements IndexEntryAccessor { /** Assumes caller is in a transaction */ boolean deleteIndexEntry(S userStorable) throws PersistException { - return makeIndexEntry(userStorable).tryDelete(); + try { + return makeIndexEntry(userStorable).tryDelete(); + } catch (PersistException e) { + Throwable cause = e.getCause(); + if (cause instanceof IllegalArgumentException) { + // Can be caused by a corrupt master record, which is + // attempting do assign an illegal value to the index. There's + // no way to find the old index entry to delete. + return false; + } + throw e; + } } /** Assumes caller is in a transaction */ @@ -219,13 +230,26 @@ class ManagedIndex implements IndexEntryAccessor { boolean updateIndexEntry(S userStorable, S oldUserStorable) throws PersistException { Storable newIndexEntry = makeIndexEntry(userStorable); - if (oldUserStorable != null) { - Storable oldIndexEntry = makeIndexEntry(oldUserStorable); + if (oldUserStorable != null) deleteOldEntry: { + Storable oldIndexEntry; + try { + oldIndexEntry = makeIndexEntry(oldUserStorable); + } catch (PersistException e) { + Throwable cause = e.getCause(); + if (cause instanceof IllegalArgumentException) { + // Can be caused by a corrupt master record, which is + // attempting do assign an illegal value to the index. There's + // no way to find the old index entry to delete. + break deleteOldEntry; + } + throw e; + } + if (oldIndexEntry.equalPrimaryKeys(newIndexEntry)) { - // Index entry didn't change, so nothing to do. If the - // index entry has a version, it will lag behind the - // master's version until the index entry changes, at which - // point the version will again match the master. + // Index entry didn't change, so nothing to do. If the index + // entry has a version, it will lag behind the master's version + // until the index entry changes, at which point the version + // will again match the master. return true; } diff --git a/src/main/java/com/amazon/carbonado/repo/replicated/ReplicationTrigger.java b/src/main/java/com/amazon/carbonado/repo/replicated/ReplicationTrigger.java index 0e9281e..d29d568 100644 --- a/src/main/java/com/amazon/carbonado/repo/replicated/ReplicationTrigger.java +++ b/src/main/java/com/amazon/carbonado/repo/replicated/ReplicationTrigger.java @@ -18,6 +18,8 @@ package com.amazon.carbonado.repo.replicated; +import java.util.Map; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -343,7 +345,28 @@ class ReplicationTrigger extends Trigger { // properties. Be sure not to copy nulls from old replica to new // replica, in case new non-nullable properties have been added. This // is why copyUnequalProperties is called instead of copyAllProperties. - replicaEntry.copyUnequalProperties(newReplicaEntry); + try { + replicaEntry.copyUnequalProperties(newReplicaEntry); + } catch (IllegalArgumentException e) { + // Some property cannot be copied, so copy one at a time and skip + // the broken one. + Map propertyMap = replicaEntry.propertyMap(); + for (Map.Entry entry : propertyMap.entrySet()) { + String name = entry.getKey(); + Object oldValue = entry.getValue(); + try { + Object newValue = newReplicaEntry.getPropertyValue(name); + if (oldValue == null ? newValue != null : !oldValue.equals(newValue)) { + newReplicaEntry.setPropertyValue(name, oldValue); + } + } catch (IllegalArgumentException e2) { + // Skip it. + } catch (UnsupportedOperationException e2) { + // Skip it. + } + } + } + // Calling copyAllProperties will skip unsupported independent // properties in master, thus preserving old independent property values. masterEntry.copyAllProperties(newReplicaEntry); -- cgit v1.2.3