Beispiel #1
0
        /// <summary>
        /// Dumps a label scan write log as plain text. Arguments:
        /// <ul>
        ///     <li>{@value #ARG_TOFILE}: dumps to a .txt file next to the writelog</li>
        ///     <li>{@value #ARG_TXFILTER}: filter for which tx ids to include in the dump.
        ///     <para>
        ///     Consists of one or more groups separated by comma.
        /// </para>
        ///     <para>
        ///     Each group is either a txId, or a txId range, e.g. 123-456
        ///     </li>
        /// </ul>
        /// </para>
        /// <para>
        /// How to interpret the dump, e.g:
        /// <pre>
        /// === ..../neostore.labelscanstore.db.writelog ===
        /// [1,1]+tx:6,node:0,label:0
        /// [1,1]+tx:3,node:20,label:0
        /// [1,1]+tx:4,node:40,label:0
        /// [1,1]+tx:5,node:60,label:0
        /// [2,1]+tx:8,node:80,label:1
        /// [3,1]+tx:10,node:41,label:1
        /// [4,1]+tx:9,node:21,label:1
        /// [4,1]+tx:11,node:61,label:1
        /// [4,1]+range:0,labelId:1
        ///  [00000000 00000000 00000010 00000000 00000000 00000000 00000000 00000000]
        ///  [00100000 00000000 00000000 00000000 00000000 00100000 00000000 00000000]
        /// [5,1]+tx:12,node:81,label:1
        /// [5,1]+range:1,labelId:1
        ///  [00000000 00000000 00000000 00000000 00000000 00000001 00000000 00000000]
        ///  [00000000 00000000 00000000 00000000 00000000 00000010 00000000 00000000]
        /// [6,1]+tx:13,node:1,label:1
        /// [6,1]+range:0,labelId:1
        ///  [00100000 00000000 00000010 00000000 00000000 00100000 00000000 00000000]
        ///  [00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000010]
        /// [7,1]+tx:14,node:62,label:1
        /// [7,1]+range:0,labelId:1
        /// </pre>
        /// How to interpret a message like:
        /// <pre>
        /// [1,1]+tx:6,node:0,label:0
        ///  ▲ ▲ ▲   ▲      ▲       ▲
        ///  │ │ │   │      │       └──── label id of the change
        ///  │ │ │   │      └──────────── node id of the change
        ///  │ │ │   └─────────────────── id of transaction making this particular change
        ///  │ │ └─────────────────────── addition, a minus means removal
        ///  │ └───────────────────────── flush, local to each write session, incremented when a batch of changes is flushed internally in a writer session
        ///  └─────────────────────────── write session, incremented for each <seealso cref="LabelScanStore.newWriter()"/>
        /// </pre>
        /// How to interpret a message like:
        /// <pre>
        /// [4,1]+range:0,labelId:1
        ///  [00000000 00000000 00000010 00000000 00000000 00000000 00000000 00000000]
        ///  [00100000 00000000 00000000 00000000 00000000 00100000 00000000 00000000]
        /// </pre>
        /// First the first line (parts within bracket same as above):
        /// <pre>
        /// [4,1]+range:0,labelId:1
        ///             ▲         ▲
        ///             │         └── label id of the changed bitset to apply
        ///             └──────────── range, i.e. which bitset to apply this change for
        /// </pre>
        /// Then the bitsets are printed
        /// <pre>
        ///  [00000000 00000000 00000010 00000000 00000000 00000000 00000000 00000000] : state of the bitset for this label id before the change
        ///  [00100000 00000000 00000000 00000000 00000000 00100000 00000000 00000000] : bits that applied to this bitset
        ///                                                                              for addition the 1-bits denotes bits to be added
        ///                                                                              for removal the 1-bits denotes bits to be removed
        /// </pre>
        /// </para>
        /// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: public static void main(String[] args) throws java.io.IOException
        public static void Main(string[] args)
        {
            Args arguments = Args.withFlags(ARG_TOFILE).parse(args);

            if (arguments.Orphans().Count == 0)
            {
                Console.Error.WriteLine("Please supply database directory");
                return;
            }

            DatabaseLayout        databaseLayout = DatabaseLayout.of(new File(arguments.Orphans()[0]));
            FileSystemAbstraction fs             = new DefaultFileSystemAbstraction();
            TxFilter    txFilter        = ParseTxFilter(arguments.Get(ARG_TXFILTER, null));
            PrintStream @out            = System.out;
            bool        redirectsToFile = arguments.GetBoolean(ARG_TOFILE);

            if (redirectsToFile)
            {
                File outFile = new File(WriteLogBaseFile(databaseLayout).AbsolutePath + ".txt");
                Console.WriteLine("Redirecting output to " + outFile);
                @out = new PrintStream(new BufferedOutputStream(new FileStream(outFile, FileMode.Create, FileAccess.Write)));
            }
            Dumper dumper = new PrintStreamDumper(@out);

            Dump(fs, databaseLayout, dumper, txFilter);
            if (redirectsToFile)
            {
                @out.close();
            }
        }
Beispiel #2
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private static void dumpPrepare(Dumper dumper, byte type, org.neo4j.storageengine.api.ReadableChannel channel, long range, int labelId, TxFilter txFilter, long session, long flush) throws java.io.IOException
        private static void DumpPrepare(Dumper dumper, sbyte type, ReadableChannel channel, long range, int labelId, TxFilter txFilter, long session, long flush)
        {
            long txId   = channel.Long;
            int  offset = channel.Get();
            long nodeId = range * 64 + offset;

            if (txFilter == null || txFilter.Contains(txId))
            {
                // I.e. if the txId this update comes from is within the txFilter
                dumper.Prepare(type == TYPE_PREPARE_ADD, session, flush, txId, nodeId, labelId);
            }
        }
Beispiel #3
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private static void dumpMerge(Dumper dumper, byte type, org.neo4j.storageengine.api.ReadableChannel channel, long range, int labelId, TxFilter txFilter, long session, long flush) throws java.io.IOException
        private static void DumpMerge(Dumper dumper, sbyte type, ReadableChannel channel, long range, int labelId, TxFilter txFilter, long session, long flush)
        {
            long existingBits = channel.Long;
            long newBits      = channel.Long;

            if (txFilter == null || txFilter.Contains())
            {
                dumper.Merge(type == TYPE_MERGE_ADD, session, flush, range, labelId, existingBits, newBits);
            }
        }
Beispiel #4
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private static long dumpFile(org.neo4j.io.fs.FileSystemAbstraction fs, java.io.File file, Dumper dumper, TxFilter txFilter, long session) throws java.io.IOException
        private static long DumpFile(FileSystemAbstraction fs, File file, Dumper dumper, TxFilter txFilter, long session)
        {
            try
            {
                using (ReadableChannel channel = new ReadAheadChannel <>(fs.Open(file, OpenMode.READ)))
                {
                    long range   = -1;
                    int  labelId = -1;
                    long flush   = 0;
                    while (true)
                    {
                        sbyte type = channel.Get();
                        switch (type)
                        {
                        case TYPE_RANGE:
                            range   = channel.Long;
                            labelId = channel.Int;
                            if (txFilter != null)
                            {
                                txFilter.Clear();
                            }
                            break;

                        case TYPE_PREPARE_ADD:
                        case TYPE_PREPARE_REMOVE:
                            DumpPrepare(dumper, type, channel, range, labelId, txFilter, session, flush);
                            break;

                        case TYPE_MERGE_ADD:
                        case TYPE_MERGE_REMOVE:
                            DumpMerge(dumper, type, channel, range, labelId, txFilter, session, flush);
                            break;

                        case TYPE_FLUSH:
                            flush++;
                            break;

                        case TYPE_SESSION_END:
                            session++;
                            flush = 0;
                            break;

                        default:
                            Console.WriteLine("Unknown type " + type + " at " + (( ReadAheadChannel )channel).position());
                            break;
                        }
                    }
                }
            }
            catch (ReadPastEndException)
            {
                // This is OK. we're done with this file
            }
            return(session);
        }
Beispiel #5
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: public static void dump(org.neo4j.io.fs.FileSystemAbstraction fs, org.neo4j.io.layout.DatabaseLayout databaseLayout, Dumper dumper, TxFilter txFilter) throws java.io.IOException
        public static void Dump(FileSystemAbstraction fs, DatabaseLayout databaseLayout, Dumper dumper, TxFilter txFilter)
        {
            File   writeLogFile         = WriteLogBaseFile(databaseLayout);
            string writeLogFileBaseName = writeLogFile.Name;

            File[] files = fs.ListFiles(databaseLayout.DatabaseDirectory(), (dir, name) => name.StartsWith(writeLogFileBaseName));
            Arrays.sort(files, comparing(_file => _file.Name.Equals(writeLogFileBaseName) ? 0 : MillisOf(_file)));
            long session = 0;

            foreach (File file in files)
            {
                dumper.File(file);
                session = DumpFile(fs, file, dumper, txFilter, session);
            }
        }