package org.neo4j.shell.tools.imp;
import com.esotericsoftware.kryo.io.Input;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.shell.*;
import org.neo4j.shell.kernel.GraphDatabaseShellServer;
import org.neo4j.shell.tools.imp.format.kryo.KryoReader;
import org.neo4j.shell.tools.imp.util.*;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.zip.InflaterInputStream;
/**
* Created by efulton on 5/5/16.
*/
public class ImportBinaryApp extends BinaryApp {
private static final int DEFAULT_BATCH_SIZE = 10000;
private static final String DEFAULT_REL_TYPE = "RELATED_TO";
{
addOptionDefinition("i", new OptionDefinition(OptionValueType.MUST, "Input Binary file"));
addOptionDefinition("b", new OptionDefinition(OptionValueType.MAY, "Batch Size. Default is: " + DEFAULT_BATCH_SIZE));
addOptionDefinition("r", new OptionDefinition(OptionValueType.MAY, "Default Relationship-Type otherwise edge attribute 'label' " + DEFAULT_REL_TYPE));
addOptionDefinition("c", new OptionDefinition(OptionValueType.NONE, "Use a node-cache that overflows to disk, necessary for very large imports"));
}
@Override
public String getName() {
return "import-binary";
}
@Override
public GraphDatabaseShellServer getServer() {
return (GraphDatabaseShellServer) super.getServer();
}
@Override
public Continuation execute(AppCommandParser parser, Session session, Output out) throws Exception {
String fileName = parser.option("i", null);
String relType = parser.option("r", DEFAULT_REL_TYPE);
int batchSize = Integer.parseInt( parser.option("b", String.valueOf(DEFAULT_BATCH_SIZE)));
boolean diskSpillCache = parser.options().containsKey("c");
try (FileInputStream fileInputStream = new FileInputStream(fileName)) {
String type = loadType(fileInputStream);
switch (type) {
case KRYO:
readKryo(fileName, fileInputStream, out, diskSpillCache, batchSize, relType);
break;
case CBOR:
throw new RuntimeException(String.format("%s is not supported yet", CBOR));
case PACKSTREAM:
throw new RuntimeException(String.format("%s is not supported yet", PACKSTREAM));
}
}
return Continuation.INPUT_COMPLETE;
}
private String loadType(FileInputStream fileInputStream) throws IOException {
StringBuilder type = new StringBuilder();
String result = null;
for (int i = 0; i < MAX_FORMAT_STRING_SIZE && fileInputStream.available() > 0; i++) {
char character = (char) fileInputStream.read();
type.append(character);
if (BINARY_FORMATS.contains(type.toString())) {
result = type.toString();
break;
}
}
return result;
}
private void readKryo(String fileName, FileInputStream fileInputStream, Output out, boolean diskSpillCache, int batchSize, String relType) throws IOException {
Input input = new Input(new InflaterInputStream(new BufferedInputStream(fileInputStream,FileUtils.MEGABYTE)),FileUtils.MEGABYTE);
FileInputWrapper fileInputWrapper = new FileInputWrapper(fileInputStream);
out.println(String.format("Binary import file %s rel-type %s batch-size %d use disk-cache %s", fileName, relType, batchSize, diskSpillCache));
ProgressReporter reporter = new ProgressReporter(fileInputWrapper, out);
GraphDatabaseService db = getServer().getDb();
NodeCache cache = diskSpillCache ? MapNodeCache.<Long, Long>usingMapDb() : MapNodeCache.<Long, Long>usingHashMap();
try(BatchTransaction tx = new BatchTransaction(db, batchSize, reporter)) {
KryoReader importReader = new KryoReader(db, relType, reporter, out);
long count = importReader.readBinaryDump(input, tx, cache);
out.println("Binary import created " + count + " entities.");
} finally {
input.close();
}
}
}