You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by mi...@apache.org on 2012/06/11 19:47:48 UTC
svn commit: r1348942 -
/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/SegmentInfos.java
Author: mikemccand
Date: Mon Jun 11 17:47:47 2012
New Revision: 1348942
URL: http://svn.apache.org/viewvc?rev=1348942&view=rev
Log:
LUCENE-4128: be more careful on upgrading a 3.x segments_N file to individual .si files so that OS or JVM crash, or machine power loss, doesn't leave index unusable
Modified:
lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/SegmentInfos.java
Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/SegmentInfos.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/SegmentInfos.java?rev=1348942&r1=1348941&r2=1348942&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/SegmentInfos.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/SegmentInfos.java Mon Jun 11 17:47:47 2012
@@ -337,9 +337,12 @@ public final class SegmentInfos implemen
// before finishCommit is called
ChecksumIndexOutput pendingSegnOutput;
+ private static final String SEGMENT_INFO_UPGRADE_CODEC = "SegmentInfo3xUpgrade";
+ private static final int SEGMENT_INFO_UPGRADE_VERSION = 0;
+
private void write(Directory directory) throws IOException {
- String segmentFileName = getNextSegmentFileName();
+ String segmentsFileName = getNextSegmentFileName();
// Always advance the generation on write:
if (generation == -1) {
@@ -354,7 +357,7 @@ public final class SegmentInfos implemen
final Set<String> upgradedSIFiles = new HashSet<String>();
try {
- segnOutput = new ChecksumIndexOutput(directory.createOutput(segmentFileName, IOContext.DEFAULT));
+ segnOutput = new ChecksumIndexOutput(directory.createOutput(segmentsFileName, IOContext.DEFAULT));
CodecUtil.writeHeader(segnOutput, "segments", VERSION_40);
segnOutput.writeLong(version);
segnOutput.writeInt(counter); // write counter
@@ -373,9 +376,29 @@ public final class SegmentInfos implemen
// "ugprade" to write the .si file for it:
String version = si.getVersion();
if (version == null || StringHelper.getVersionComparator().compare(version, "4.0") < 0) {
- String fileName = IndexFileNames.segmentFileName(si.name, "", Lucene3xSegmentInfoFormat.UPGRADED_SI_EXTENSION);
- if (!directory.fileExists(fileName)) {
- upgradedSIFiles.add(write3xInfo(directory, si, IOContext.DEFAULT));
+
+ if (!segmentWasUpgraded(directory, si)) {
+
+ final String segmentFileName = write3xInfo(directory, si, IOContext.DEFAULT);
+ upgradedSIFiles.add(segmentFileName);
+ directory.sync(Collections.singletonList(segmentFileName));
+
+ String markerFileName = IndexFileNames.segmentFileName(si.name, "upgraded", Lucene3xSegmentInfoFormat.UPGRADED_SI_EXTENSION);
+
+ // Write separate marker file indicating upgrade
+ // is completed. This way, if there is a JVM
+ // kill/crash, OS crash, power loss, etc. while
+ // writing the upgraded file, the marker file
+ // will be missing:
+ si.addFile(markerFileName);
+ IndexOutput out = directory.createOutput(markerFileName, IOContext.DEFAULT);
+ try {
+ CodecUtil.writeHeader(out, SEGMENT_INFO_UPGRADE_CODEC, SEGMENT_INFO_UPGRADE_VERSION);
+ } finally {
+ out.close();
+ }
+ upgradedSIFiles.add(markerFileName);
+ directory.sync(Collections.singletonList(markerFileName));
}
}
}
@@ -399,7 +422,7 @@ public final class SegmentInfos implemen
try {
// Try not to leave a truncated segments_N file in
// the index:
- directory.deleteFile(segmentFileName);
+ directory.deleteFile(segmentsFileName);
} catch (Throwable t) {
// Suppress so we keep throwing the original exception
}
@@ -407,6 +430,27 @@ public final class SegmentInfos implemen
}
}
+ private static boolean segmentWasUpgraded(Directory directory, SegmentInfo si) {
+ // Check marker file:
+ String markerFileName = IndexFileNames.segmentFileName(si.name, "upgraded", Lucene3xSegmentInfoFormat.UPGRADED_SI_EXTENSION);
+ IndexInput in = null;
+ try {
+ in = directory.openInput(markerFileName, IOContext.READONCE);
+ if (CodecUtil.checkHeader(in, SEGMENT_INFO_UPGRADE_CODEC, SEGMENT_INFO_UPGRADE_VERSION, SEGMENT_INFO_UPGRADE_VERSION) == 0) {
+ return true;
+ }
+ } catch (IOException ioe) {
+ // Ignore: if something is wrong w/ the marker file,
+ // we will just upgrade again
+ } finally {
+ if (in != null) {
+ IOUtils.closeWhileHandlingException(in);
+ }
+ }
+ return false;
+ }
+
+
@Deprecated
public static String write3xInfo(Directory dir, SegmentInfo si, IOContext context) throws IOException {