Ejemplo n.º 1
0
 internal void CopyTo(IWriteOnlyTable table)
 {
     foreach (var kv in records)
     {
         var value = kv.Value;
         if (value == null)
         {
             table.Remove(kv.Key);
         }
         else
         {
             table.Put(kv.Key, value);
         }
     }
 }
Ejemplo n.º 2
0
 internal static bool Update(this IWriteOnlyTable table, string key, string val)
 {
     return(table.Update(Encoding.UTF8.GetBytes(key), Encoding.UTF8.GetBytes(val)));
 }
Ejemplo n.º 3
0
 internal static bool Remove(this IWriteOnlyTable table, string key)
 {
     return(table.Remove(Encoding.UTF8.GetBytes(key)));
 }
Ejemplo n.º 4
0
 internal static void Put(this IWriteOnlyTable table, string key, string val)
 {
     table.Put(Encoding.UTF8.GetBytes(key), Encoding.UTF8.GetBytes(val));
 }
Ejemplo n.º 5
0
        internal static void ReplayOnto(Stream journal, PlaneDBOptions options, IWriteOnlyTable table)
        {
            var transformer = options.BlockTransformer;
            var actions     = 0;

            journal.Seek(0, SeekOrigin.Begin);
            if (journal.ReadInt32() != Constants.MAGIC)
            {
                throw new IOException("Bad journal file (wrong blocktransformer?)");
            }

            Span <byte> small = stackalloc byte[4096];

            for (;;)
            {
                try {
                    var unlength = journal.ReadInt32();
                    var length   = journal.ReadInt32();
                    if (length <= 0 || unlength <= 0)
                    {
                        throw new IOException("Bad record");
                    }

                    Span <byte> input  = length <= 4096 ? small.Slice(0, length) : new byte[length];
                    Span <byte> buffer = unlength <= 4096 ? small.Slice(0, unlength) : new byte[unlength];
                    journal.ReadFullBlock(input);
                    var tlen = transformer.UntransformBlock(input, buffer);
                    if (tlen <= 0)
                    {
                        throw new IOException($"Bad record ({length}/{tlen})");
                    }

                    buffer = buffer.Slice(0, tlen);

                    var type = buffer[0];
                    buffer = buffer.Slice(1);

                    switch ((RecordType)type)
                    {
                    case RecordType.Put: {
                        var klen = BinaryPrimitives.ReadInt32LittleEndian(buffer);
                        var vlen = BinaryPrimitives.ReadInt32LittleEndian(buffer.Slice(sizeof(int)));
                        var key  = buffer.Slice(sizeof(int) * 2, klen);
                        var val  = buffer.Slice(sizeof(int) * 2 + klen, vlen);
                        table.Put(key, val);
                        ++actions;
                        break;
                    }

                    case RecordType.Remove: {
                        var klen = BinaryPrimitives.ReadInt32LittleEndian(buffer);
                        var key  = buffer.Slice(sizeof(int), klen);
                        table.Remove(key);
                        ++actions;
                        break;
                    }

                    case RecordType.Update: {
                        var klen = BinaryPrimitives.ReadInt32LittleEndian(buffer);
                        var vlen = BinaryPrimitives.ReadInt32LittleEndian(buffer.Slice(sizeof(int)));
                        var key  = buffer.Slice(sizeof(int) * 2, klen);
                        var val  = buffer.Slice(sizeof(int) * 2 + klen, vlen);
                        table.Update(key, val);
                        ++actions;
                        break;
                    }

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }
                catch (IOException) {
                    break;
                }
            }

            if (actions > 0)
            {
                return;
            }

            throw journal switch {
                      FileStream fs => new BrokenJournalException(fs),
                      _ => new BrokenJournalException()
            };
        }