Пример #1
0
        public void Load(LogReader reader)
        {
            if (CurrentVersion != null)
            {
                return;
            }

            CurrentVersion = ReadVersionEdit(reader);
            Print(CurrentVersion);

            foreach (var level in CurrentVersion.NewFiles)             // Search all levels for file with matching index
            {
                foreach (FileMetadata tbl in level.Value)
                {
                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug($"Found table file for key in level {level.Key} in file={tbl.FileNumber}");
                    }

                    Table tableReader = tbl.Table;
                    if (tableReader == null)
                    {
                        FileInfo f = new FileInfo(Path.Combine(_baseDirectory.FullName, $"{tbl.FileNumber:000000}.ldb"));
                        if (!f.Exists)
                        {
                            throw new Exception($"Could not find table {f.FullName}");
                        }
                        tableReader = new Table(f);
                        tbl.Table   = tableReader;
                    }
                }
            }
        }
Пример #2
0
        public void Close()
        {
            var tableFiles = CurrentVersion.NewFiles;

            CurrentVersion = null;
            foreach (var level in tableFiles)             // Search all levels for file with matching index
            {
                foreach (FileMetadata tbl in level.Value)
                {
                    tbl.Table?.Dispose();
                    tbl.Table = null;
                }
            }
        }
Пример #3
0
        public VersionEdit ReadVersionEdit(LogReader logReader)
        {
            string comparator         = null;
            ulong? logNumber          = null;
            ulong? previousLogNumber  = null;
            ulong? nextFileNumber     = null;
            ulong? lastSequenceNumber = null;

            VersionEdit finalVersion = new VersionEdit();

            while (true)
            {
                Record record = logReader.ReadRecord();

                if (record.LogRecordType != LogRecordType.Full)
                {
                    break;
                }

                var reader = new SpanReader(record.Data);

                VersionEdit versionEdit = new VersionEdit();

                while (!reader.Eof)
                {
                    LogTagType logTag = (LogTagType)reader.ReadVarLong();
                    switch (logTag)
                    {
                    case LogTagType.Comparator:
                    {
                        versionEdit.Comparator = reader.ReadLengthPrefixedString();
                        break;
                    }

                    case LogTagType.LogNumber:
                    {
                        versionEdit.LogNumber = reader.ReadVarLong();
                        break;
                    }

                    case LogTagType.NextFileNumber:
                    {
                        versionEdit.NextFileNumber = reader.ReadVarLong();
                        break;
                    }

                    case LogTagType.LastSequence:
                    {
                        versionEdit.LastSequenceNumber = reader.ReadVarLong();
                        break;
                    }

                    case LogTagType.CompactPointer:
                    {
                        int level       = (int)reader.ReadVarLong();
                        var internalKey = reader.ReadLengthPrefixedBytes();
                        versionEdit.CompactPointers[level] = internalKey.ToArray();
                        break;
                    }

                    case LogTagType.DeletedFile:
                    {
                        int   level      = (int)reader.ReadVarLong();
                        ulong fileNumber = reader.ReadVarLong();
                        if (!versionEdit.DeletedFiles.ContainsKey(level))
                        {
                            versionEdit.DeletedFiles[level] = new List <ulong>();
                        }
                        versionEdit.DeletedFiles[level].Add(fileNumber);
                        if (!finalVersion.DeletedFiles.ContainsKey(level))
                        {
                            finalVersion.DeletedFiles[level] = new List <ulong>();
                        }
                        finalVersion.DeletedFiles[level].Add(fileNumber);
                        break;
                    }

                    case LogTagType.NewFile:
                    {
                        int   level      = (int)reader.ReadVarLong();
                        ulong fileNumber = reader.ReadVarLong();
                        ulong fileSize   = reader.ReadVarLong();
                        var   smallest   = reader.ReadLengthPrefixedBytes();
                        var   largest    = reader.ReadLengthPrefixedBytes();

                        FileMetadata fileMetadata = new FileMetadata();
                        fileMetadata.FileNumber  = fileNumber;
                        fileMetadata.FileSize    = fileSize;
                        fileMetadata.SmallestKey = smallest.ToArray();
                        fileMetadata.LargestKey  = largest.ToArray();
                        if (!versionEdit.NewFiles.ContainsKey(level))
                        {
                            versionEdit.NewFiles[level] = new List <FileMetadata>();
                        }
                        versionEdit.NewFiles[level].Add(fileMetadata);
                        if (!finalVersion.NewFiles.ContainsKey(level))
                        {
                            finalVersion.NewFiles[level] = new List <FileMetadata>();
                        }
                        finalVersion.NewFiles[level].Add(fileMetadata);
                        break;
                    }

                    case LogTagType.PrevLogNumber:
                    {
                        versionEdit.PreviousLogNumber = reader.ReadVarLong();
                        break;
                    }

                    default:
                    {
                        throw new ArgumentOutOfRangeException($"Unknown tag={logTag}");
                    }
                    }
                }

                versionEdit.CompactPointers = versionEdit.CompactPointers.Count == 0 ? null : versionEdit.CompactPointers;
                versionEdit.DeletedFiles    = versionEdit.DeletedFiles.Count == 0 ? null : versionEdit.DeletedFiles;
                versionEdit.NewFiles        = versionEdit.NewFiles.Count == 0 ? null : versionEdit.NewFiles;

                comparator         = versionEdit.Comparator ?? comparator;
                logNumber          = versionEdit.LogNumber ?? logNumber;
                previousLogNumber  = versionEdit.PreviousLogNumber ?? previousLogNumber;
                nextFileNumber     = versionEdit.NextFileNumber ?? nextFileNumber;
                lastSequenceNumber = versionEdit.LastSequenceNumber ?? lastSequenceNumber;
            }

            // Clean files
            List <ulong> deletedFiles = new List <ulong>();

            foreach (var versionDeletedFile in finalVersion.DeletedFiles.Values)
            {
                deletedFiles.AddRange(versionDeletedFile);
            }

            foreach (var levelKvp in finalVersion.NewFiles)
            {
                foreach (var newFile in levelKvp.Value.ToArray())
                {
                    if (deletedFiles.Contains(newFile.FileNumber))
                    {
                        levelKvp.Value.Remove(newFile);
                    }
                }
            }
            finalVersion.NewFiles = finalVersion.NewFiles.OrderBy(kvp => kvp.Key).ToDictionary(pair => pair.Key, pair => pair.Value);

            finalVersion.Comparator         = comparator;
            finalVersion.LogNumber          = logNumber;
            finalVersion.PreviousLogNumber  = previousLogNumber;
            finalVersion.NextFileNumber     = nextFileNumber;
            finalVersion.LastSequenceNumber = lastSequenceNumber;

            return(finalVersion);
        }
Пример #4
0
        public void Open()
        {
            if (_manifest != null)
            {
                throw new InvalidOperationException("Already had manifest for database. Did you already open it?");
            }
            if (_newMemCache != null)
            {
                throw new InvalidOperationException("Already had memory cache for database. Did you already open it?");
            }

            if (Directory.Name.EndsWith(".mcworld"))
            {
                // Exported from MCPE. Unpack to temp

                Log.Debug($"Opening directory: {Directory.Name}");

                var originalFile = Directory;

                string newDirPath = Path.Combine(Path.GetTempPath(), Directory.Name);
                Directory = new DirectoryInfo(Path.Combine(newDirPath, "db"));
                if (!Directory.Exists || originalFile.LastWriteTimeUtc > Directory.LastWriteTimeUtc)
                {
                    ZipFile.ExtractToDirectory(originalFile.FullName, newDirPath, true);
                    Log.Warn($"Created new temp directory: {Directory.FullName}");
                }

                Log.Warn($"Extracted bedrock world and set new DB directory to: {Directory.FullName}");
            }

            // Verify that directory exists
            if (!Directory.Exists)
            {
                if (!CreateIfMissing)
                {
                    throw new DirectoryNotFoundException(Directory.Name);
                }

                Directory.Create();

                // Create new MANIFEST

                VersionEdit newVersion = new VersionEdit();
                newVersion.NextFileNumber = 1;
                newVersion.Comparator     = "leveldb.BytewiseComparator";

                // Create new CURRENT text file and store manifest filename in it
                using (var manifestStream = File.CreateText($@"{Path.Combine(Directory.FullName, "CURRENT")}"))
                {
                    manifestStream.WriteLine($"MANIFEST-{newVersion.NextFileNumber++:000000}");
                    manifestStream.Close();
                }


                // Done
            }

            // Read Manifest into memory

            string manifestFilename;

            using (var currentStream = File.OpenText($@"{Path.Combine(Directory.FullName, "CURRENT")}"))
            {
                manifestFilename = currentStream.ReadLine();
                currentStream.Close();
            }

            Log.Debug($"Reading manifest from {Path.Combine(Directory.FullName, manifestFilename)}");
            using (var reader = new LogReader(new FileInfo($@"{Path.Combine(Directory.FullName, manifestFilename)}")))
            {
                _manifest = new Manifest(Directory);
                _manifest.Load(reader);
            }

            // Read current log
            //TODO: remove unit-test-stuff
            var      logFileName = Path.Combine(Directory.FullName, $"{_manifest.CurrentVersion.LogNumber + 1:000000}.log");
            FileInfo f           = new FileInfo(logFileName);

            if (!f.Exists)
            {
                f = new FileInfo(Path.Combine(Directory.FullName, $"{_manifest.CurrentVersion.LogNumber:000000}.log"));
            }

            using (var reader = new LogReader(f))
            {
                _newMemCache = new MemCache();
                _newMemCache.Load(reader);
            }
        }