forked from I2P_Developers/i2p.i2p
Blockfile: Fixes for finishing interrupted database migration
by tracking version of each list, and catching some exceptions
This commit is contained in:
@ -121,6 +121,7 @@ public class BlockfileNamingService extends DummyNamingService {
|
|||||||
private static final String REVERSE_SKIPLIST = "%%__REVERSE__%%";
|
private static final String REVERSE_SKIPLIST = "%%__REVERSE__%%";
|
||||||
private static final String PROP_INFO = "info";
|
private static final String PROP_INFO = "info";
|
||||||
private static final String PROP_VERSION = "version";
|
private static final String PROP_VERSION = "version";
|
||||||
|
private static final String PROP_LISTVERSION = "listversion";
|
||||||
private static final String PROP_LISTS = "lists";
|
private static final String PROP_LISTS = "lists";
|
||||||
private static final String PROP_CREATED = "created";
|
private static final String PROP_CREATED = "created";
|
||||||
private static final String PROP_UPGRADED = "upgraded";
|
private static final String PROP_UPGRADED = "upgraded";
|
||||||
@ -406,12 +407,29 @@ public class BlockfileNamingService extends DummyNamingService {
|
|||||||
// version 3 -> version 4
|
// version 3 -> version 4
|
||||||
// support multiple destinations per hostname
|
// support multiple destinations per hostname
|
||||||
if (VersionComparator.comp(_version, "4") < 0) {
|
if (VersionComparator.comp(_version, "4") < 0) {
|
||||||
|
SkipList<String, Properties> hdr = _bf.getIndex(INFO_SKIPLIST, _stringSerializer, _infoSerializer);
|
||||||
|
if (hdr == null)
|
||||||
|
throw new IOException("No db header");
|
||||||
|
Properties info = hdr.get(PROP_INFO);
|
||||||
|
if (info == null)
|
||||||
|
throw new IOException("No header info");
|
||||||
for (String list : _lists) {
|
for (String list : _lists) {
|
||||||
try {
|
try {
|
||||||
if (_log.shouldWarn())
|
// so that we can handle an aborted upgrade,
|
||||||
_log.warn("Upgrading " + list + " from database version 3 to 4");
|
// we keep track of the version of each list
|
||||||
_bf.reformatIndex(list, _stringSerializer, _destSerializerV1,
|
String vprop = PROP_LISTVERSION + '_' + list;
|
||||||
_stringSerializer, _destSerializerV4);
|
String listVersion = info.getProperty(vprop);
|
||||||
|
if (listVersion == null || VersionComparator.comp(listVersion, "4") < 0) {
|
||||||
|
if (_log.shouldWarn())
|
||||||
|
_log.warn("Upgrading " + list + " from database version 3 to 4");
|
||||||
|
_bf.reformatIndex(list, _stringSerializer, _destSerializerV1,
|
||||||
|
_stringSerializer, _destSerializerV4);
|
||||||
|
info.setProperty(vprop, "4");
|
||||||
|
hdr.put(PROP_INFO, info);
|
||||||
|
} else {
|
||||||
|
if (_log.shouldWarn())
|
||||||
|
_log.warn("Partial upgrade, " + list + " already at version " + listVersion);
|
||||||
|
}
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
_log.error("Failed upgrade of list " + list + " to version 4", ioe);
|
_log.error("Failed upgrade of list " + list + " to version 4", ioe);
|
||||||
}
|
}
|
||||||
@ -1537,7 +1555,6 @@ public class BlockfileNamingService extends DummyNamingService {
|
|||||||
ctxProps.setProperty(PROP_FORCE, "true");
|
ctxProps.setProperty(PROP_FORCE, "true");
|
||||||
I2PAppContext ctx = new I2PAppContext(ctxProps);
|
I2PAppContext ctx = new I2PAppContext(ctxProps);
|
||||||
BlockfileNamingService bns = new BlockfileNamingService(ctx);
|
BlockfileNamingService bns = new BlockfileNamingService(ctx);
|
||||||
/****
|
|
||||||
Properties sprops = new Properties();
|
Properties sprops = new Properties();
|
||||||
String lname = "privatehosts.txt";
|
String lname = "privatehosts.txt";
|
||||||
sprops.setProperty("list", lname);
|
sprops.setProperty("list", lname);
|
||||||
@ -1549,6 +1566,7 @@ public class BlockfileNamingService extends DummyNamingService {
|
|||||||
sprops.setProperty("list", lname);
|
sprops.setProperty("list", lname);
|
||||||
System.out.println("List " + lname + " contains " + bns.size(sprops));
|
System.out.println("List " + lname + " contains " + bns.size(sprops));
|
||||||
|
|
||||||
|
/****
|
||||||
List<String> names = null;
|
List<String> names = null;
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
try {
|
try {
|
||||||
|
@ -36,8 +36,8 @@ import java.io.IOException;
|
|||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
|
|
||||||
public class RAIFile implements RandomAccessInterface, DataInput, DataOutput {
|
public class RAIFile implements RandomAccessInterface, DataInput, DataOutput {
|
||||||
private File f;
|
private final File f;
|
||||||
private RandomAccessFile delegate;
|
private final RandomAccessFile delegate;
|
||||||
private final boolean r, w;
|
private final boolean r, w;
|
||||||
|
|
||||||
public RAIFile(RandomAccessFile file) throws FileNotFoundException {
|
public RAIFile(RandomAccessFile file) throws FileNotFoundException {
|
||||||
|
@ -36,6 +36,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import net.metanotion.io.RAIFile;
|
import net.metanotion.io.RAIFile;
|
||||||
@ -526,7 +527,12 @@ public class BlockFile implements Closeable {
|
|||||||
return;
|
return;
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
String tmpName = "---tmp---" + name + "---tmp---";
|
String tmpName = "---tmp---" + name + "---tmp---";
|
||||||
BSkipList<K, V> tmp = makeIndex(tmpName, newKey, newVal);
|
BSkipList<K, V> tmp = getIndex(tmpName, newKey, newVal);
|
||||||
|
if (tmp != null) {
|
||||||
|
log.logAlways(Log.WARN, "Continuing on aborted reformat of list " + name);
|
||||||
|
} else {
|
||||||
|
tmp = makeIndex(tmpName, newKey, newVal);
|
||||||
|
}
|
||||||
|
|
||||||
// It could be much more efficient to do this at the
|
// It could be much more efficient to do this at the
|
||||||
// SkipSpan layer but that's way too hard.
|
// SkipSpan layer but that's way too hard.
|
||||||
@ -536,8 +542,12 @@ public class BlockFile implements Closeable {
|
|||||||
while (true) {
|
while (true) {
|
||||||
SkipIterator<K, V> iter = old.iterator();
|
SkipIterator<K, V> iter = old.iterator();
|
||||||
for (int i = 0; iter.hasNext() && i < loop; i++) {
|
for (int i = 0; iter.hasNext() && i < loop; i++) {
|
||||||
keys.add(iter.nextKey());
|
try {
|
||||||
vals.add(iter.next());
|
keys.add(iter.nextKey());
|
||||||
|
vals.add(iter.next());
|
||||||
|
} catch (NoSuchElementException nsee) {
|
||||||
|
throw new IOException("Unable to reformat corrupt list " + name, nsee);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// save state, as deleting corrupts the iterator
|
// save state, as deleting corrupts the iterator
|
||||||
boolean done = !iter.hasNext();
|
boolean done = !iter.hasNext();
|
||||||
|
@ -104,7 +104,8 @@ public class BSkipList<K extends Comparable<? super K>, V> extends SkipList<K, V
|
|||||||
if (bf.file.canWrite() &&
|
if (bf.file.canWrite() &&
|
||||||
(levelCount != levelHash.size() || spans != spanHash.size() || size != total)) {
|
(levelCount != levelHash.size() || spans != spanHash.size() || size != total)) {
|
||||||
if (bf.log.shouldLog(Log.WARN))
|
if (bf.log.shouldLog(Log.WARN))
|
||||||
bf.log.warn("On-disk counts were " + levelCount + " / " + spans + " / " + size + ", correcting");
|
bf.log.warn("On-disk counts were " + levelCount + " levels / " + spans +
|
||||||
|
" spans / " + size + " entries, correcting to " + total + " entries");
|
||||||
size = total;
|
size = total;
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
13
history.txt
13
history.txt
@ -1,3 +1,16 @@
|
|||||||
|
2016-04-20 zzz
|
||||||
|
* Addressbook:
|
||||||
|
- Add sign/verify methods for inner signature
|
||||||
|
- Add preliminary handling of incoming actions
|
||||||
|
* Blockfile:
|
||||||
|
- Add generics
|
||||||
|
- Add method to change serialization schema for a skiplist
|
||||||
|
- Fix delIndex() method
|
||||||
|
* BlockfileNamingService:
|
||||||
|
- New database version 4, for multiple destinations per hostname
|
||||||
|
- Disallow database version higher than supported
|
||||||
|
* NamingService: Add new API methods for multiple Destinations per hostname
|
||||||
|
|
||||||
2016-04-17 zzz
|
2016-04-17 zzz
|
||||||
* Addressbook:
|
* Addressbook:
|
||||||
- Several cleanups and refactoring
|
- Several cleanups and refactoring
|
||||||
|
@ -18,7 +18,7 @@ public class RouterVersion {
|
|||||||
/** deprecated */
|
/** deprecated */
|
||||||
public final static String ID = "Monotone";
|
public final static String ID = "Monotone";
|
||||||
public final static String VERSION = CoreVersion.VERSION;
|
public final static String VERSION = CoreVersion.VERSION;
|
||||||
public final static long BUILD = 3;
|
public final static long BUILD = 4;
|
||||||
|
|
||||||
/** for example "-test" */
|
/** for example "-test" */
|
||||||
public final static String EXTRA = "";
|
public final static String EXTRA = "";
|
||||||
|
Reference in New Issue
Block a user