HBASE-648 If mapfile index is empty, run repair
git-svn-id: https://svn.apache.org/repos/asf/hadoop/hbase/trunk@661089 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
6061624031
commit
8d0665881e
|
@ -27,6 +27,7 @@ Hbase Change Log
|
||||||
HBASE-642 Splitting log in a hostile environment -- bad hdfs -- we drop
|
HBASE-642 Splitting log in a hostile environment -- bad hdfs -- we drop
|
||||||
write-ahead-log edits
|
write-ahead-log edits
|
||||||
HBASE-646 EOFException opening HStoreFile info file (spin on HBASE-645and 550)
|
HBASE-646 EOFException opening HStoreFile info file (spin on HBASE-645and 550)
|
||||||
|
HBASE-648 If mapfile index is empty, run repair
|
||||||
|
|
||||||
IMPROVEMENTS
|
IMPROVEMENTS
|
||||||
HBASE-559 MR example job to count table rows
|
HBASE-559 MR example job to count table rows
|
||||||
|
|
|
@ -263,29 +263,14 @@ public class HStore implements HConstants {
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for(Map.Entry<Long, HStoreFile> e: this.storefiles.entrySet()) {
|
for(Map.Entry<Long, HStoreFile> e: this.storefiles.entrySet()) {
|
||||||
MapFile.Reader r = null;
|
MapFile.Reader r = null;
|
||||||
try {
|
if (first) {
|
||||||
if (first) {
|
// Use a block cache (if configured) for the first reader only
|
||||||
// Use a block cache (if configured) for the first reader only
|
// so as to control memory usage.
|
||||||
// so as to control memory usage.
|
r = e.getValue().getReader(this.fs, this.bloomFilter,
|
||||||
r = e.getValue().getReader(this.fs, this.bloomFilter,
|
family.isBlockCacheEnabled());
|
||||||
family.isBlockCacheEnabled());
|
first = false;
|
||||||
first = false;
|
} else {
|
||||||
} else {
|
r = e.getValue().getReader(this.fs, this.bloomFilter);
|
||||||
r = e.getValue().getReader(this.fs, this.bloomFilter);
|
|
||||||
}
|
|
||||||
} catch (EOFException eofe) {
|
|
||||||
LOG.warn("Failed open of reader " + e.toString() + "; attempting fix",
|
|
||||||
eofe);
|
|
||||||
try {
|
|
||||||
// Try fixing this file.. if we can.
|
|
||||||
MapFile.fix(this.fs, e.getValue().getMapFilePath(),
|
|
||||||
HStoreFile.HbaseMapFile.KEY_CLASS,
|
|
||||||
HStoreFile.HbaseMapFile.VALUE_CLASS, false, this.conf);
|
|
||||||
} catch (Exception fixe) {
|
|
||||||
LOG.warn("Failed fix of " + e.toString() +
|
|
||||||
"...continuing; Probable DATA LOSS!!!", fixe);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.readers.put(e.getKey(), r);
|
this.readers.put(e.getKey(), r);
|
||||||
}
|
}
|
||||||
|
@ -377,7 +362,8 @@ public class HStore implements HConstants {
|
||||||
/*
|
/*
|
||||||
* Creates a series of HStoreFiles loaded from the given directory.
|
* Creates a series of HStoreFiles loaded from the given directory.
|
||||||
* There must be a matching 'mapdir' and 'loginfo' pair of files.
|
* There must be a matching 'mapdir' and 'loginfo' pair of files.
|
||||||
* If only one exists, we'll delete it.
|
* If only one exists, we'll delete it. Does other consistency tests
|
||||||
|
* checking files are not zero, etc.
|
||||||
*
|
*
|
||||||
* @param infodir qualified path for info file directory
|
* @param infodir qualified path for info file directory
|
||||||
* @param mapdir qualified path for map file directory
|
* @param mapdir qualified path for map file directory
|
||||||
|
@ -434,7 +420,6 @@ public class HStore implements HConstants {
|
||||||
LOG.info("HSTORE_LOGINFOFILE " + curfile +
|
LOG.info("HSTORE_LOGINFOFILE " + curfile +
|
||||||
" does not contain a sequence number - ignoring");
|
" does not contain a sequence number - ignoring");
|
||||||
}
|
}
|
||||||
|
|
||||||
Path mapfile = curfile.getMapFilePath();
|
Path mapfile = curfile.getMapFilePath();
|
||||||
if (!fs.exists(mapfile)) {
|
if (!fs.exists(mapfile)) {
|
||||||
fs.delete(curfile.getInfoFilePath(), false);
|
fs.delete(curfile.getInfoFilePath(), false);
|
||||||
|
@ -449,6 +434,23 @@ public class HStore implements HConstants {
|
||||||
"Deleting. Continuing...Probable DATA LOSS!!! See HBASE-646.");
|
"Deleting. Continuing...Probable DATA LOSS!!! See HBASE-646.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (isEmptyIndexFile(mapfile)) {
|
||||||
|
try {
|
||||||
|
// Try fixing this file.. if we can. Use the hbase version of fix.
|
||||||
|
// Need to remove the old index file first else fix won't go ahead.
|
||||||
|
this.fs.delete(new Path(mapfile, MapFile.INDEX_FILE_NAME));
|
||||||
|
long count = MapFile.fix(this.fs, mapfile, HStoreFile.HbaseMapFile.KEY_CLASS,
|
||||||
|
HStoreFile.HbaseMapFile.VALUE_CLASS, false, this.conf);
|
||||||
|
if (LOG.isDebugEnabled()) {
|
||||||
|
LOG.debug("Fixed index on " + mapfile.toString() + "; had " +
|
||||||
|
count + " entries");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.warn("Failed fix of " + mapfile.toString() +
|
||||||
|
"...continuing; Probable DATA LOSS!!!", e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Confirm referent exists.
|
// TODO: Confirm referent exists.
|
||||||
|
|
||||||
|
@ -486,9 +488,32 @@ public class HStore implements HConstants {
|
||||||
throws IOException {
|
throws IOException {
|
||||||
// Mapfiles are made of 'data' and 'index' files. Confirm 'data' is
|
// Mapfiles are made of 'data' and 'index' files. Confirm 'data' is
|
||||||
// non-null if it exists (may not have been written to yet).
|
// non-null if it exists (may not have been written to yet).
|
||||||
Path dataFile = new Path(mapfile, "data");
|
return isEmptyFile(new Path(mapfile, MapFile.DATA_FILE_NAME));
|
||||||
return this.fs.exists(dataFile) &&
|
}
|
||||||
this.fs.getFileStatus(dataFile).getLen() == 0;
|
|
||||||
|
/*
|
||||||
|
* @param mapfile
|
||||||
|
* @return True if the passed mapfile has a zero-length index component (its
|
||||||
|
* broken).
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private boolean isEmptyIndexFile(final Path mapfile)
|
||||||
|
throws IOException {
|
||||||
|
// Mapfiles are made of 'data' and 'index' files. Confirm 'data' is
|
||||||
|
// non-null if it exists (may not have been written to yet).
|
||||||
|
return isEmptyFile(new Path(mapfile, MapFile.INDEX_FILE_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @param mapfile
|
||||||
|
* @return True if the passed mapfile has a zero-length index component (its
|
||||||
|
* broken).
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private boolean isEmptyFile(final Path f)
|
||||||
|
throws IOException {
|
||||||
|
return this.fs.exists(f) &&
|
||||||
|
this.fs.getFileStatus(f).getLen() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -622,8 +622,9 @@ public class HStoreFile implements HConstants {
|
||||||
* Hbase customizations of MapFile.
|
* Hbase customizations of MapFile.
|
||||||
*/
|
*/
|
||||||
static class HbaseMapFile extends MapFile {
|
static class HbaseMapFile extends MapFile {
|
||||||
static final Class KEY_CLASS = HStoreKey.class;
|
static final Class<? extends Writable> KEY_CLASS = HStoreKey.class;
|
||||||
static final Class VALUE_CLASS = ImmutableBytesWritable.class;
|
static final Class<? extends Writable> VALUE_CLASS =
|
||||||
|
ImmutableBytesWritable.class;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A reader capable of reading and caching blocks of the data file.
|
* A reader capable of reading and caching blocks of the data file.
|
||||||
|
@ -696,8 +697,6 @@ public class HStoreFile implements HConstants {
|
||||||
* @param conf
|
* @param conf
|
||||||
* @param fs
|
* @param fs
|
||||||
* @param dirName
|
* @param dirName
|
||||||
* @param keyClass
|
|
||||||
* @param valClass
|
|
||||||
* @param compression
|
* @param compression
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue