SOLR-1068 -- Use fsync on replicated index and configuration files

git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@757209 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Shalin Shekhar Mangar 2009-03-22 16:33:46 +00:00
parent ed946926a3
commit d0573099bc
3 changed files with 52 additions and 4 deletions

View File

@ -365,6 +365,8 @@ Other Changes
21. Upgraded to Lucene 2.9-dev r752164 (shalin) 21. Upgraded to Lucene 2.9-dev r752164 (shalin)
22. SOLR-1068: Use fsync on replicated index and configuration files (yonik, shalin)
Build Build
---------------------- ----------------------
1. SOLR-776: Added in ability to sign artifacts via Ant for releases (gsingers) 1. SOLR-776: Added in ability to sign artifacts via Ant for releases (gsingers)

View File

@ -19,6 +19,7 @@ package org.apache.solr.common.util;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile;
/** /**
* @version $Id$ * @version $Id$
@ -29,10 +30,10 @@ public class FileUtils {
* Resolves a path relative a base directory. * Resolves a path relative a base directory.
* *
* <p> * <p>
* This method does what "new File(base,path)" <b>Should</b> do, it wasn't * This method does what "new File(base,path)" <b>Should</b> do, it wasn't
* completely lame: If path is absolute, then a File for that path is returned; * completely lame: If path is absolute, then a File for that path is returned;
* if it's not absoluve, then a File is returnd using "path" as a child * if it's not absoluve, then a File is returnd using "path" as a child
* of "base") * of "base")
* </p> * </p>
*/ */
public static File resolvePath(File base, String path) throws IOException { public static File resolvePath(File base, String path) throws IOException {
@ -40,4 +41,44 @@ public class FileUtils {
return r.isAbsolute() ? r : new File(base, path); return r.isAbsolute() ? r : new File(base, path);
} }
/**
* Copied from Lucene's {@link org.apache.lucene.store.FSDirectory#sync(String)}
*
* @see org.apache.lucene.store.FSDirectory#sync(String)
*
* @param fullFile the File to be synced to disk
* @throws IOException if the file could not be synced
*/
public static void sync(File fullFile) throws IOException {
boolean success = false;
int retryCount = 0;
IOException exc = null;
while(!success && retryCount < 5) {
retryCount++;
RandomAccessFile file = null;
try {
try {
file = new RandomAccessFile(fullFile, "rw");
file.getFD().sync();
success = true;
} finally {
if (file != null)
file.close();
}
} catch (IOException ioe) {
if (exc == null)
exc = ioe;
try {
// Pause 5 msec
Thread.sleep(5);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
}
if (!success)
// Throw original exception
throw exc;
}
} }

View File

@ -23,6 +23,7 @@ import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.FastInputStream; import org.apache.solr.common.util.FastInputStream;
import org.apache.solr.common.util.JavaBinCodec; import org.apache.solr.common.util.JavaBinCodec;
import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.FileUtils;
import org.apache.solr.core.SolrCore; import org.apache.solr.core.SolrCore;
import static org.apache.solr.handler.ReplicationHandler.*; import static org.apache.solr.handler.ReplicationHandler.*;
import org.apache.solr.search.SolrIndexSearcher; import org.apache.solr.search.SolrIndexSearcher;
@ -475,7 +476,7 @@ public class SnapPuller {
/** /**
* Copy all index files from the temp index dir to the actual index. The segments_N file is copied last. * Copy all index files from the temp index dir to the actual index. The segments_N file is copied last.
*/ */
private boolean copyIndexFiles(File snapDir, File indexDir) { private boolean copyIndexFiles(File snapDir, File indexDir) throws IOException {
String segmentsFile = null; String segmentsFile = null;
List<String> copiedfiles = new ArrayList<String>(); List<String> copiedfiles = new ArrayList<String>();
for (Map<String, Object> f : filesDownloaded) { for (Map<String, Object> f : filesDownloaded) {
@ -490,11 +491,13 @@ public class SnapPuller {
continue; continue;
} }
if (!copyAFile(snapDir, indexDir, fname, copiedfiles)) return false; if (!copyAFile(snapDir, indexDir, fname, copiedfiles)) return false;
FileUtils.sync(new File(indexDir, fname));
copiedfiles.add(fname); copiedfiles.add(fname);
} }
//copy the segments file last //copy the segments file last
if (segmentsFile != null) { if (segmentsFile != null) {
if (!copyAFile(snapDir, indexDir, segmentsFile, copiedfiles)) return false; if (!copyAFile(snapDir, indexDir, segmentsFile, copiedfiles)) return false;
FileUtils.sync(new File(indexDir, segmentsFile));
} }
return true; return true;
} }
@ -516,7 +519,9 @@ public class SnapPuller {
} }
} }
boolean status = file.renameTo(oldFile); boolean status = file.renameTo(oldFile);
if (!status) { if (status) {
FileUtils.sync(oldFile);
} else {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
"Unable to rename: " + file + " to: " + oldFile); "Unable to rename: " + file + " to: " + oldFile);
} }