예제 #1
0
        public static SelectByIndexInfo Create(ITableInfo tableInfo, IIndexInfo indexInfo)
        {
            var sqlParameters = tableInfo.Columns.Where(x => indexInfo.ColumnNames.Contains(x.ColumnName)).ToList();

            return(new SelectByIndexInfo
            {
                Sql = GetSql(tableInfo, sqlParameters),
                SqlParameters = sqlParameters
            });
        }
예제 #2
0
        public static void WriteEntities <I, T>(
            IIndexInfo <I> indexInfo,
            Dictionary <I, T> entities,
            List <Type> types,
            string savePath,
            out Dictionary <string, int> counts
            ) where T : class, ISerializable
        {
            counts = new Dictionary <string, int>();

            var typeName = indexInfo.TypeName;

            var path = Path.Combine(savePath, typeName);

            PathUtility.EnsureDirectory(path);

            string idxPath = Path.Combine(path, $"{typeName}.idx");
            string tdbPath = Path.Combine(path, $"{typeName}.tdb");
            string binPath = Path.Combine(path, $"{typeName}.bin");

            using var idx = new BinaryFileWriter(idxPath, false);
            using var tdb = new BinaryFileWriter(tdbPath, false);
            using var bin = new BinaryFileWriter(binPath, true);

            idx.Write(1); // Version
            idx.Write(entities.Count);
            foreach (var e in entities.Values)
            {
                long start = bin.Position;

                idx.Write(e.TypeRef);
                idx.Write(e.Serial);
                idx.Write(e.Created.Ticks);
                idx.Write(e.LastSerialized.Ticks);
                idx.Write(start);

                e.SerializeTo(bin);

                idx.Write((int)(bin.Position - start));

                var type = e.GetType().FullName;
                if (type != null)
                {
                    counts[type] = (counts.TryGetValue(type, out var count) ? count : 0) + 1;
                }
            }

            tdb.Write(types.Count);
            for (int i = 0; i < types.Count; ++i)
            {
                tdb.Write(types[i].FullName);
            }
        }
예제 #3
0
        public static Dictionary <I, T> LoadIndex <I, T>(
            string path,
            IIndexInfo <I> indexInfo,
            out List <EntityIndex <T> > entities
            ) where T : class, ISerializable
        {
            var map = new Dictionary <I, T>();

            object[] ctorArgs = new object[1];

            var indexType = indexInfo.TypeName;

            string indexPath = Path.Combine(path, indexType, $"{indexType}.idx");
            string typesPath = Path.Combine(path, indexType, $"{indexType}.tdb");

            entities = new List <EntityIndex <T> >();

            if (!File.Exists(indexPath) || !File.Exists(typesPath))
            {
                return(map);
            }

            using FileStream idx = new FileStream(indexPath, FileMode.Open, FileAccess.Read, FileShare.Read);
            BinaryReader idxReader = new BinaryReader(idx);

            using FileStream tdb = new FileStream(typesPath, FileMode.Open, FileAccess.Read, FileShare.Read);
            BinaryReader tdbReader = new BinaryReader(tdb);

            List <Tuple <ConstructorInfo, string> > types = ReadTypes <I>(tdbReader);

            var count = idxReader.ReadInt32();

            for (int i = 0; i < count; ++i)
            {
                var typeID = idxReader.ReadInt32();
                var number = idxReader.ReadUInt32();
                var pos    = idxReader.ReadInt64();
                var length = idxReader.ReadInt32();

                Tuple <ConstructorInfo, string> objs = types[typeID];

                if (objs == null)
                {
                    continue;
                }

                T t;
                ConstructorInfo ctor = objs.Item1;
                I indexer            = indexInfo.CreateIndex(number);

                ctorArgs[0] = indexer;
                t           = ctor.Invoke(ctorArgs) as T;

                if (t != null)
                {
                    entities.Add(new EntityIndex <T>(t, typeID, pos, length));
                    map[indexer] = t;
                }
            }

            tdbReader.Close();
            idxReader.Close();

            return(map);
        }
예제 #4
0
        public static void LoadData <I, T>(
            string path,
            IIndexInfo <I> indexInfo,
            List <EntityIndex <T> > entities
            ) where T : class, ISerializable
        {
            var indexType = indexInfo.TypeName;

            string dataPath = Path.Combine(path, indexType, $"{indexType}.bin");

            if (!File.Exists(dataPath))
            {
                return;
            }

            using FileStream bin = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read);

            BufferReader br = null;

            foreach (var entry in entities)
            {
                T t = entry.Entity;

                // Skip this entry
                if (t == null)
                {
                    bin.Seek(entry.Length, SeekOrigin.Current);
                    continue;
                }

                var buffer = GC.AllocateUninitializedArray <byte>(entry.Length);
                if (br == null)
                {
                    br = new BufferReader(buffer);
                }
                else
                {
                    br.SwapBuffers(buffer, out _);
                }

                bin.Read(buffer.AsSpan());
                string error;

                try
                {
                    t.Deserialize(br);

                    error = br.Position != entry.Length
                        ? $"Serialized object was {entry.Length} bytes, but {br.Position} bytes deserialized"
                        : null;
                }
                catch (Exception e)
                {
                    error = e.ToString();
                }

                if (error == null)
                {
                    t.InitializeSaveBuffer(buffer);
                }
                else
                {
                    Utility.PushColor(ConsoleColor.Red);
                    Persistence.WriteConsoleLine($"***** Bad deserialize of {t.GetType()} *****");
                    Persistence.WriteConsoleLine(error);
                    Utility.PopColor();

                    Persistence.WriteConsoleLine("Delete the object and continue? (y/n)");

                    if (Console.ReadKey(true).Key != ConsoleKey.Y)
                    {
                        throw new Exception("Deserialization failed.");
                    }
                    t.Delete();
                }
            }
        }
예제 #5
0
        public static Dictionary <I, T> LoadIndex <I, T>(
            string path,
            IIndexInfo <I> indexInfo,
            out List <EntityIndex <T> > entities
            ) where T : class, ISerializable
        {
            var map = new Dictionary <I, T>();

            object[] ctorArgs = new object[1];

            var indexType = indexInfo.TypeName;

            string indexPath = Path.Combine(path, indexType, $"{indexType}.idx");
            string typesPath = Path.Combine(path, indexType, $"{indexType}.tdb");

            entities = new List <EntityIndex <T> >();

            if (!File.Exists(indexPath) || !File.Exists(typesPath))
            {
                return(map);
            }

            using FileStream idx = new FileStream(indexPath, FileMode.Open, FileAccess.Read, FileShare.Read);
            BinaryReader idxReader = new BinaryReader(idx);

            using FileStream tdb = new FileStream(typesPath, FileMode.Open, FileAccess.Read, FileShare.Read);
            BinaryReader tdbReader = new BinaryReader(tdb);

            List <Tuple <ConstructorInfo, string> > types = ReadTypes <I>(tdbReader);

            int count;
            var version = idxReader.ReadInt32();

            // Handle non-versioned (version 0).
            if (version > _idxVersion || idx.Length - 4 - version * 20 == 0)
            {
                count   = version;
                version = 0;
            }
            else
            {
                count = idxReader.ReadInt32();
            }

            var now = DateTime.UtcNow;

            for (int i = 0; i < count; ++i)
            {
                var typeID         = idxReader.ReadInt32();
                var serial         = idxReader.ReadUInt32();
                var created        = version == 0 ? now : new DateTime(idxReader.ReadInt64(), DateTimeKind.Utc);
                var lastSerialized = version == 0 ? DateTime.MinValue : new DateTime(idxReader.ReadInt64(), DateTimeKind.Utc);
                var pos            = idxReader.ReadInt64();
                var length         = idxReader.ReadInt32();

                Tuple <ConstructorInfo, string> objs = types[typeID];

                if (objs == null)
                {
                    continue;
                }

                ConstructorInfo ctor = objs.Item1;
                I indexer            = indexInfo.CreateIndex(serial);

                ctorArgs[0] = indexer;

                if (ctor.Invoke(ctorArgs) is T t)
                {
                    t.Created        = created;
                    t.LastSerialized = lastSerialized;
                    entities.Add(new EntityIndex <T>(t, typeID, pos, length));
                    map[indexer] = t;
                }
            }

            tdbReader.Close();
            idxReader.Close();

            return(map);
        }
예제 #6
0
        public static void LoadData <I, T>(
            string path,
            IIndexInfo <I> indexInfo,
            List <EntityIndex <T> > entities
            ) where T : class, ISerializable
        {
            var indexType = indexInfo.TypeName;

            string dataPath = Path.Combine(path, indexType, $"{indexType}.bin");

            if (!File.Exists(dataPath) || new FileInfo(dataPath).Length == 0)
            {
                return;
            }

            using var mmf    = MemoryMappedFile.CreateFromFile(dataPath, FileMode.Open);
            using var stream = mmf.CreateViewStream();
            BufferReader br = null;

            var deleteAllFailures = false;

            foreach (var entry in entities)
            {
                T t = entry.Entity;

                var position = entry.Position;
                stream.Seek(position, SeekOrigin.Begin);

                // Skip this entry
                if (t == null)
                {
                    continue;
                }

                if (entry.Length == 0)
                {
                    t.Delete();
                    continue;
                }

                var buffer = GC.AllocateUninitializedArray <byte>(entry.Length);
                if (br == null)
                {
                    br = new BufferReader(buffer, t.LastSerialized);
                }
                else
                {
                    br.Reset(buffer, out _);
                }

                stream.Read(buffer.AsSpan());
                string error;

                try
                {
                    t.Deserialize(br);

                    error = br.Position != entry.Length
                        ? $"Serialized object was {entry.Length} bytes, but {br.Position} bytes deserialized"
                        : null;
                }
                catch (Exception e)
                {
                    error = e.ToString();
                }

                if (error == null)
                {
                    t.InitializeSaveBuffer(buffer);
                }
                else
                {
                    Console.WriteLine($"***** Bad deserialize of {t.GetType()} *****");
                    Console.WriteLine(error);

                    ConsoleKey pressedKey;

                    if (!deleteAllFailures)
                    {
                        Console.WriteLine("Delete the object and continue? (y/n/a)");
                        pressedKey = Console.ReadKey(true).Key;

                        if (pressedKey == ConsoleKey.A)
                        {
                            deleteAllFailures = true;
                        }
                        else if (pressedKey != ConsoleKey.Y)
                        {
                            throw new Exception("Deserialization failed.");
                        }
                    }

                    t.Delete();
                }
            }
        }
예제 #7
0
 public IndexNode(DatabaseInfo databaseInfo, IIndexInfo indexInfo) :
     base(IndexList.Path(databaseInfo, indexInfo), $"{indexInfo.IndexName} ({databaseInfo.BaseName})")
 {
 }
예제 #8
0
 public static string Path(IAdlibDatabaseInfo databaseInfo, IIndexInfo indexInfo) => $"{DatabaseNode.DatabasePath(databaseInfo)}\\index\\{indexInfo.TableName}";