package com.sleepycat.je.util; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Date; import java.util.logging.Level; import com.sleepycat.je.Database; import com.sleepycat.je.DatabaseConfig; import com.sleepycat.je.DatabaseEntry; import com.sleepycat.je.DatabaseException; import com.sleepycat.je.DbInternal; import com.sleepycat.je.Environment; import com.sleepycat.je.EnvironmentConfig; import com.sleepycat.je.JEVersion; import com.sleepycat.je.OperationStatus; import com.sleepycat.je.utilint.CmdUtil; import com.sleepycat.je.utilint.Tracer; import de.ovgu.cide.jakutil.*; public class DbLoad { private static final boolean DEBUG=false; protected Environment env; private boolean formatUsingPrintable; private String dbName; private BufferedReader reader; private boolean noOverwrite; private boolean textFileMode; private boolean dupSort; private boolean ignoreUnknownConfig; private boolean commandLine; private long progressInterval; private long totalLoadBytes; private static final String usageString="usage: " + CmdUtil.getJavaCommand(DbLoad.class) + "\n"+ " -h <dir> # environment home directory\n"+ " [-f <fileName>] # input file\n"+ " [-n ] # no overwrite mode\n"+ " [-T] # input file is in text mode\n"+ " [-I] # ignore unknown parameters\n"+ " [-c name=value] # config values\n"+ " [-s <databaseName> ] # database to load\n"+ " [-v] # show progress\n"+ " [-V] # print JE version number"; static public void main( String argv[]) throws DatabaseException, IOException { DbLoad loader=parseArgs(argv); try { loader.load(); } catch ( Throwable e) { e.printStackTrace(); } loader.env.close(); } static private void printUsage( String msg){ System.err.println(msg); System.err.println(usageString); System.exit(-1); } static private DbLoad parseArgs( String argv[]) throws IOException, DatabaseException { boolean noOverwrite=false; boolean textFileMode=false; boolean ignoreUnknownConfig=false; boolean showProgressInterval=false; int argc=0; int nArgs=argv.length; String inputFileName=null; File envHome=null; String dbName=null; long progressInterval=0; DbLoad ret=new DbLoad(); ret.setCommandLine(true); while (argc < nArgs) { String thisArg=argv[argc++].trim(); if (thisArg.equals("-n")) { noOverwrite=true; } else if (thisArg.equals("-T")) { textFileMode=true; } else if (thisArg.equals("-I")) { ignoreUnknownConfig=true; } else if (thisArg.equals("-V")) { System.out.println(JEVersion.CURRENT_VERSION); System.exit(0); } else if (thisArg.equals("-f")) { if (argc < nArgs) { inputFileName=argv[argc++]; } else { printUsage("-f requires an argument"); } } else if (thisArg.equals("-h")) { if (argc < nArgs) { envHome=new File(argv[argc++]); } else { printUsage("-h requires an argument"); } } else if (thisArg.equals("-s")) { if (argc < nArgs) { dbName=argv[argc++]; } else { printUsage("-s requires an argument"); } } else if (thisArg.equals("-c")) { if (argc < nArgs) { try { ret.loadConfigLine(argv[argc++]); } catch ( IllegalArgumentException e) { printUsage("-c: " + e.getMessage()); } } else { printUsage("-c requires an argument"); } } else if (thisArg.equals("-v")) { showProgressInterval=true; } } if (envHome == null) { printUsage("-h is a required argument"); } long totalLoadBytes=0; InputStream is; if (inputFileName == null) { is=System.in; if (showProgressInterval) { printUsage("-v requires -f"); } } else { is=new FileInputStream(inputFileName); if (showProgressInterval) { totalLoadBytes=((FileInputStream)is).getChannel().size(); progressInterval=totalLoadBytes / 20; } } BufferedReader reader=new BufferedReader(new InputStreamReader(is)); EnvironmentConfig envConfig=new EnvironmentConfig(); envConfig.setAllowCreate(true); Environment env=new Environment(envHome,envConfig); ret.setEnv(env); ret.setDbName(dbName); ret.setInputReader(reader); ret.setNoOverwrite(noOverwrite); ret.setTextFileMode(textFileMode); ret.setIgnoreUnknownConfig(ignoreUnknownConfig); ret.setProgressInterval(progressInterval); ret.setTotalLoadBytes(totalLoadBytes); return ret; } public DbLoad(){ } /** * If true, enables output of warning messages. Command line behavior is * not available via the public API. */ private void setCommandLine( boolean commandLine){ this.commandLine=commandLine; } public void setEnv( Environment env){ this.env=env; } public void setDbName( String dbName){ this.dbName=dbName; } public void setInputReader( BufferedReader reader){ this.reader=reader; } public void setNoOverwrite( boolean noOverwrite){ this.noOverwrite=noOverwrite; } public void setTextFileMode( boolean textFileMode){ this.textFileMode=textFileMode; } public void setIgnoreUnknownConfig( boolean ignoreUnknownConfigMode){ this.ignoreUnknownConfig=ignoreUnknownConfigMode; } public void setProgressInterval( long progressInterval){ this.progressInterval=progressInterval; } public void setTotalLoadBytes( long totalLoadBytes){ this.totalLoadBytes=totalLoadBytes; } public boolean load() throws IOException, DatabaseException { if (progressInterval > 0) { System.out.println("Load start: " + new Date()); } if (textFileMode) { formatUsingPrintable=true; } else { loadHeader(); } if (dbName == null) { throw new IllegalArgumentException("Must supply a database name if -l not supplied."); } DatabaseConfig dbConfig=new DatabaseConfig(); dbConfig.setSortedDuplicates(dupSort); dbConfig.setAllowCreate(true); Database db=env.openDatabase(null,dbName,dbConfig); loadData(db); db.close(); this.hook835(); if (progressInterval > 0) { System.out.println("Load end: " + new Date()); } return true; } private void loadConfigLine( String line) throws DatabaseException { int equalsIdx=line.indexOf('='); if (equalsIdx < 0) { throw new IllegalArgumentException("Invalid header parameter: " + line); } String keyword=line.substring(0,equalsIdx).trim().toLowerCase(); String value=line.substring(equalsIdx + 1).trim(); if (keyword.equals("version")) { if (DEBUG) { System.out.println("Found version: " + line); } if (!value.equals("3")) { throw new IllegalArgumentException("Version " + value + " is not supported."); } } else if (keyword.equals("format")) { value=value.toLowerCase(); if (value.equals("print")) { formatUsingPrintable=true; } else if (value.equals("bytevalue")) { formatUsingPrintable=false; } else { throw new IllegalArgumentException(value + " is an unknown value for the format keyword"); } if (DEBUG) { System.out.println("Found format: " + formatUsingPrintable); } } else if (keyword.equals("dupsort")) { value=value.toLowerCase(); if (value.equals("true") || value.equals("1")) { dupSort=true; } else if (value.equals("false") || value.equals("0")) { dupSort=false; } else { throw new IllegalArgumentException(value + " is an unknown value for the dupsort keyword"); } if (DEBUG) { System.out.println("Found dupsort: " + dupSort); } } else if (keyword.equals("type")) { value=value.toLowerCase(); if (!value.equals("btree")) { throw new IllegalArgumentException(value + " is not a supported database type."); } if (DEBUG) { System.out.println("Found type: " + line); } } else if (keyword.equals("database")) { if (dbName == null) { dbName=value; } if (DEBUG) { System.out.println("DatabaseImpl: " + dbName); } } else if (!ignoreUnknownConfig) { throw new IllegalArgumentException("'" + line + "' is not understood."); } } private void loadHeader() throws IOException, DatabaseException { if (DEBUG) { System.out.println("loading header"); } String line=reader.readLine(); while (line != null && !line.equals("HEADER=END")) { loadConfigLine(line); line=reader.readLine(); } } private void loadData( Database db) throws DatabaseException, IOException { String keyLine=reader.readLine(); String dataLine=null; int count=0; long totalBytesRead=0; long lastTime=System.currentTimeMillis(); long bytesReadThisInterval=0; while (keyLine != null && !keyLine.equals("DATA=END")) { dataLine=reader.readLine(); if (dataLine == null) { throw new DatabaseException("No data to match key " + keyLine); } bytesReadThisInterval+=dataLine.length() + 1; byte[] keyBytes=loadLine(keyLine.trim()); byte[] dataBytes=loadLine(dataLine.trim()); DatabaseEntry key=new DatabaseEntry(keyBytes); DatabaseEntry data=new DatabaseEntry(dataBytes); if (noOverwrite) { if (db.putNoOverwrite(null,key,data) == OperationStatus.KEYEXIST) { if (commandLine) { System.err.println("Key exists: " + key); } } } else { db.put(null,key,data); } count++; if ((progressInterval > 0) && (bytesReadThisInterval > progressInterval)) { totalBytesRead+=bytesReadThisInterval; bytesReadThisInterval-=progressInterval; long now=System.currentTimeMillis(); System.out.println("loaded " + count + " records "+ (now - lastTime)+ " ms - % completed: "+ ((100 * totalBytesRead) / totalLoadBytes)); lastTime=now; } keyLine=reader.readLine(); if (keyLine == null) { throw new DatabaseException("No \"DATA=END\""); } bytesReadThisInterval+=keyLine.length() + 1; } } private byte[] loadLine( String line) throws DatabaseException { if (formatUsingPrintable) { return readPrintableLine(line); } int nBytes=line.length() / 2; byte[] ret=new byte[nBytes]; int charIdx=0; for (int i=0; i < nBytes; i++, charIdx+=2) { int b2=Character.digit(line.charAt(charIdx),16); b2<<=4; b2+=Character.digit(line.charAt(charIdx + 1),16); ret[i]=(byte)b2; } return ret; } static private byte backSlashValue=(byte)(new Character('\\').charValue() & 0xff); private byte[] readPrintableLine( String line) throws DatabaseException { int maxNBytes=line.length(); byte[] ba=new byte[maxNBytes]; int actualNBytes=0; for (int charIdx=0; charIdx < maxNBytes; charIdx++) { char c=line.charAt(charIdx); if (c == '\\') { if (++charIdx < maxNBytes) { char c1=line.charAt(charIdx); if (c1 == '\\') { ba[actualNBytes++]=backSlashValue; } else { if (++charIdx < maxNBytes) { char c2=line.charAt(charIdx); int b=Character.digit(c1,16); b<<=4; b+=Character.digit(c2,16); ba[actualNBytes++]=(byte)b; } else { throw new DatabaseException("Corrupted file"); } } } else { throw new DatabaseException("Corrupted file"); } } else { ba[actualNBytes++]=(byte)(c & 0xff); } } if (maxNBytes == actualNBytes) { return ba; } else { byte[] ret=new byte[actualNBytes]; System.arraycopy(ba,0,ret,0,actualNBytes); return ret; } } protected void hook835() throws IOException, DatabaseException { } }