Determine Neo4j database version

帅比萌擦擦* 提交于 2019-12-08 02:49:46

问题


The Neo4j Java API automatically updates outdated databases to the current version when I call

new GraphDatabaseFactory().newEmbeddedDatabase(File storeDir)

I would like to check what version the database is before doing that. Is there a way to do that with the Java API? Or alternatively: Where is the database version stored so I can read it out manually?


回答1:


Release version

I dug into the Neo4j API source and found an answer. Neo4j reads out the previous version from the debug.log file in the logs directory. Whenever the database is started the version is printed into the log file as Kernel version: (this is where you'll find the version). For instance it could look like this:

2017-11-21 06:21:43.460+0000 INFO [o.n.k.i.DiagnosticsManager] Kernel version: 3.3.0,5b700972242a5ec3e0140261120f2845fb3520ad

You could read out the debug.log the Neo4j way:

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<ReadableClosablePositionAwareChannel> logEntryReader = new VersionAwareLogEntryReader<>();
        LogTailScanner tailScanner = new LogTailScanner( logFiles, fileSystem, logEntryReader );

        LogEntryVersion version = tailScanner.getTailInformation().latestLogEntryVersion;

        if(version!=null) {
                return version.toString();
        } else {
                return null;
        }
    }

}

The above method returns V3_0_10 for a debug.log whose latest Kernel version entry is the one above.

Unfortunately the Neo4j way is not very precise. As you can see the Kernel version from the debug.log starts with 3.3.0 but the Neo method says it is V3_0_10. I'm assuming this has something to do with the way Neo handles versions internally.

But since we now know how Neo4j gets the version, we can do the same thing in a more exact way:

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;
    }

}

The method above will return 3.3.0.

Store version

Of course both of these methods only work if there is a debug.log file. Not all previous Neo4j versions have them. As long as the store directory contains the neostore file you can read out the store version which is not as nice as reading out the release version but at least it is something. So here's how that works:

There is a Neo4j class called StoreVersionCheck which contains a very handy method called getVersion(File neostoreFile). Unfortunately we need an instance of something called a PageCache to initialize an instance of StoreVersionCheck. We can make a PageCache, so that is what we'll do.

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<String> 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<Log> consumer) {}

    }

}


来源:https://stackoverflow.com/questions/47378638/determine-neo4j-database-version

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!