package jane.tool; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.util.AbstractMap.SimpleEntry; import java.util.ArrayList; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; import jane.core.Octets; import jane.core.OctetsStream; import jane.core.StorageLevelDB; public final class LevelDBImport { private static final Pattern s_patHex = Pattern.compile("\\\\x(..)"); private static final Charset s_cs88591 = Charset.forName("ISO-8859-1"); private static final OctetsStream s_deleted = OctetsStream.wrap(Octets.EMPTY); private LevelDBImport() { } private static OctetsStream str2Oct(String str) { String matchStr = ""; try { Matcher mat = s_patHex.matcher(str); if(!mat.find()) return OctetsStream.wrap(str.getBytes(s_cs88591)); StringBuffer sb = new StringBuffer(str.length()); do { matchStr = mat.group(1); mat.appendReplacement(sb, Matcher.quoteReplacement(String.valueOf((char)(Integer.parseInt(matchStr, 16))))); } while(mat.find()); return OctetsStream.wrap(mat.appendTail(sb).toString().getBytes(s_cs88591)); } catch(RuntimeException e) { System.err.println("ERROR: parse failed: '" + matchStr + "' in '" + str + '\''); throw e; } } public static void main(String[] args) throws Exception { if(args.length < 1) { System.err.println("USAGE: java jane.tool.LevelDBImport <databasePath.ld> <dumpFile>"); return; } String pathname = args[0].trim(); String dumpname = args[1].trim(); long t = System.currentTimeMillis(); long count = 0; long db; ArrayList<Entry<Octets, Octets>> buf = new ArrayList<>(10000); try(BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(dumpname), s_cs88591))) { System.err.println("INFO: opening " + pathname + " ..."); db = StorageLevelDB.leveldb_open(pathname, 0, 0, true); if(db == 0) { System.err.println("ERROR: leveldb_open failed"); br.close(); return; } System.err.println("INFO: importing db ..."); Pattern patPut1 = Pattern.compile("put '(.*)' '(.*)'"); // the official leveldb log dump file Pattern patPut2 = Pattern.compile("'(.*)' @ \\d+ : val => '(.*)'"); // the official leveldb ldb dump file Pattern patPut3 = Pattern.compile("[\"(.*)\"]=\"(.*)\""); // LevelDBExport dump file Pattern patDel1 = Pattern.compile("del '(.*)'"); // the official leveldb log dump file Pattern patDel2 = Pattern.compile("'(.*)' @ \\d+ : del"); // the official leveldb ldb dump file String line; while((line = br.readLine()) != null) { Matcher mat; OctetsStream v; if((mat = patPut1.matcher(line)).find()) v = str2Oct(mat.group(2)); else if((mat = patPut2.matcher(line)).find()) v = str2Oct(mat.group(2)); else if((mat = patPut3.matcher(line)).find()) v = str2Oct(mat.group(2)); else if((mat = patDel1.matcher(line)).find()) v = s_deleted; else if((mat = patDel2.matcher(line)).find()) v = s_deleted; else continue; buf.add(new SimpleEntry<Octets, Octets>(str2Oct(mat.group(1)), v)); if(buf.size() >= 10000) { count += buf.size(); StorageLevelDB.leveldb_write(db, buf.iterator()); buf.clear(); } } } if(!buf.isEmpty()) { count += buf.size(); StorageLevelDB.leveldb_write(db, buf.iterator()); buf.clear(); } System.err.println("INFO: closing db ..."); StorageLevelDB.leveldb_close(db); System.err.println("INFO: done! (count=" + count + ") (" + (System.currentTimeMillis() - t) + " ms)"); } }