确定Neo4j数据库版本

当我打电话时,Neo4j Java API会自动将过时的数据库更新为当前版本

new GraphDatabaseFactory().newEmbeddedDatabase(File storeDir)

我想在执行此操作之前检查数据库的版本。 有没有办法用Java API做到这一点? 或者:存储数据库版本在哪里,以便我可以手动读出它?

发布版本

我挖掘了Neo4j API源并找到了答案。 Neo4j从logs目录中的debug.log文件中读出以前的版本。 每当启动数据库时,版本都会作为Kernel version: (this is where you'll find the version)打印到日志文件中Kernel version: (this is where you'll find the version) 。 例如,它可能看起来像这样:

 2017-11-21 06:21:43.460+0000 INFO [onkiDiagnosticsManager] Kernel version: 3.3.0,5b700972242a5ec3e0140261120f2845fb3520ad 

你可以用Neo4j方式读出debug.log:

 import java.io.File; import org.neo4j.io.fs.DefaultFileSystemAbstraction; import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.kernel.impl.transaction.log.LogTailScanner; import org.neo4j.kernel.impl.transaction.log.PhysicalLogFile; import org.neo4j.kernel.impl.transaction.log.PhysicalLogFiles; import org.neo4j.kernel.impl.transaction.log.ReadableClosablePositionAwareChannel; import org.neo4j.kernel.impl.transaction.log.entry.LogEntryReader; import org.neo4j.kernel.impl.transaction.log.entry.LogEntryVersion; import org.neo4j.kernel.impl.transaction.log.entry.VersionAwareLogEntryReader; public class Neo4jVersionChecker { //Note that this method needs the store directory NOT the debug.log file public static String getNeo4jVersion(File storeDir) { FileSystemAbstraction fileSystem = new DefaultFileSystemAbstraction(); final PhysicalLogFiles logFiles = new PhysicalLogFiles( storeDir, PhysicalLogFile.DEFAULT_NAME, fileSystem ); final LogEntryReader logEntryReader = new VersionAwareLogEntryReader<>(); LogTailScanner tailScanner = new LogTailScanner( logFiles, fileSystem, logEntryReader ); LogEntryVersion version = tailScanner.getTailInformation().latestLogEntryVersion; if(version!=null) { return version.toString(); } else { return null; } } } 

上面的方法为debug.log返回V3_0_10 ,其最新的Kernel version条目是上面的那个。

不幸的是,Neo4j方式不是很精确。 正如您所看到的, debug.logKernel version3.3.0开头,但Neo方法表示它是V3_0_10 。 我假设这与Neo内部处理版本的方式有关。

但是既然我们现在知道Neo4j如何获得版本,我们可以更精确地做同样的事情:

 import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import org.apache.commons.io.input.ReversedLinesFileReader; public class VersionChecker { public static String getVersion(File storeDir) { File debugLog = new File(storeDir, "logs" + File.separator + "debug.log"); if(debugLog.exists()) { try { //The ReversedLinesFileReader reads the last line of a file first and so on ReversedLinesFileReader reader = new ReversedLinesFileReader(debugLog, StandardCharsets.UTF_8); //Read last line String line = reader.readLine(); while(line!=null) { //Line can't be null at this point if(line.contains("Kernel version: ")) { //This line contains the version line = line.substring(line.indexOf("Kernel version: ")).substring(16); //get rid of everything except the version line = line.split(",")[0]; //get rid of the second part of the Kernel version that we don't want return line; } //Next line line = reader.readLine(); } reader.close(); } catch (IOException e) { e.printStackTrace(); } } return null; } } 

上面的方法将返回3.3.0

商店版本

当然,只有存在debug.log文件时,这两种方法才有效。 并非所有以前的Neo4j版本都有它们。 只要商店目录包含neostore文件,您就可以读出store version ,这不如读取发行版本那么好,但至少它是一些东西。 所以这是如何工作的:

有一个名为StoreVersionCheck的Neo4j类,它包含一个非常方便的方法getVersion(File neostoreFile) 。 不幸的是,我们需要一个名为PageCache的实例来初始化PageCache的实例。 我们可以创建一个PageCache ,这就是我们要做的。

 import java.io.File; import java.io.IOException; import java.util.Optional; import java.util.function.Consumer; import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.io.fs.DefaultFileSystemAbstraction; import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.pagecache.PageCache; import org.neo4j.kernel.configuration.Config; import org.neo4j.kernel.impl.factory.GraphDatabaseFacadeFactory; import org.neo4j.kernel.impl.pagecache.ConfiguringPageCacheFactory; import org.neo4j.kernel.impl.storemigration.StoreVersionCheck; import org.neo4j.kernel.impl.util.Neo4jJobScheduler; import org.neo4j.kernel.monitoring.Monitors; import org.neo4j.kernel.monitoring.tracing.Tracers; import org.neo4j.logging.Log; import org.neo4j.logging.Logger; import org.neo4j.scheduler.JobScheduler; public class StoreVersionChecker { public static String getStoreVersion(File storeDir) { File storeFile = new File(storeDir, "neostore"); if(!storeFile.exists()) { return null; } StoreVersionCheck check = new StoreVersionCheck(buildPageCache()); try { Optional version = check.getVersion(storeFile); if(version.isPresent()) { return version.get(); } } catch (IOException e) { e.printStackTrace(); } return null; } private static PageCache buildPageCache() { FileSystemAbstraction fileSystem = new DefaultFileSystemAbstraction(); Config config = Config.defaults(); Log pageCacheLog = new DummyLog(); String desiredImplementationName = config.get( GraphDatabaseFacadeFactory.Configuration.tracer ); Monitors monitors = new Monitors(); JobScheduler jobScheduler = new Neo4jJobScheduler(); Tracers tracers = new Tracers( desiredImplementationName, new DummyLog(), monitors, jobScheduler ); ConfiguringPageCacheFactory pageCacheFactory = new ConfiguringPageCacheFactory(fileSystem, config, tracers.pageCacheTracer, tracers.pageCursorTracerSupplier, pageCacheLog ); PageCache pageCache = pageCacheFactory.getOrCreatePageCache(); if ( config.get( GraphDatabaseSettings.dump_configuration ) ) { pageCacheFactory.dumpConfiguration(); } return pageCache; } //We need this so we can give the Tracers a Log private static class DummyLog implements Log { @Override public boolean isDebugEnabled() {return false;} @Override public Logger debugLogger() {return null;} @Override public void debug(String message) {} @Override public void debug(String message, Throwable throwable) {} @Override public void debug(String format, Object... arguments) {} @Override public Logger infoLogger() {return null;} @Override public void info(String message) {} @Override public void info(String message, Throwable throwable) {} @Override public void info(String format, Object... arguments) {} @Override public Logger warnLogger() {return null;} @Override public void warn(String message) {} @Override public void warn(String message, Throwable throwable) {} @Override public void warn(String format, Object... arguments) {} @Override public Logger errorLogger() {return null;} @Override public void error(String message) {} @Override public void error(String message, Throwable throwable) {} @Override public void error(String format, Object... arguments) {} @Override public void bulk(Consumer consumer) {} } }