Пример #1
0
 public static void Deconstruct <T1, T2, T3>(this IVarTuple value, out T1 item1, out T2 item2, out T3 item3)
 {
     value.OfSize(3);
     item1 = value.Get <T1>(0);
     item2 = value.Get <T2>(1);
     item3 = value.Get <T3>(2);
 }
        public static async Task Shards(string[] path, IVarTuple extras, IFdbDatabase db, TextWriter log, CancellationToken ct)
        {
            var ranges = await Fdb.System.GetChunksAsync(db, FdbKey.MinValue, FdbKey.MaxValue, ct);

            Console.WriteLine($"Found {ranges.Count} shards in the whole cluster");

            // look if there is something under there
            if ((await TryOpenCurrentDirectoryAsync(path, db, ct)) is FdbDirectorySubspace folder)
            {
                var r = KeyRange.StartsWith(folder.Copy().GetPrefix());
                Console.WriteLine($"Searching for shards that intersect with /{String.Join("/", path)} ...");
                ranges = await Fdb.System.GetChunksAsync(db, r, ct);

                Console.WriteLine($"> Found {ranges.Count} ranges intersecting {r}:");
                var last = Slice.Empty;
                foreach (var range in ranges)
                {
                    Console.Write($"> {FdbKey.Dump(range.Begin)} ...");
                    long count = await Fdb.System.EstimateCountAsync(db, range, ct);

                    Console.WriteLine($" {count:N0}");
                    last = range.End;
                    //TODO: we can probably get more details on this shard looking in the system keyspace (where it is, how many replicas, ...)
                }
                Console.WriteLine($"> ... {FdbKey.Dump(last)}");
            }

            //Console.WriteLine("Found " + ranges.Count + " shards in the cluster");
            //TODO: shards that intersect the current directory
        }
        /// <summary>Counts the number of keys inside a directory</summary>
        public static async Task Count(string[] path, IVarTuple extras, IFdbDatabase db, TextWriter log, CancellationToken ct)
        {
            // look if there is something under there
            var folder = (await TryOpenCurrentDirectoryAsync(path, db, ct)) as FdbDirectorySubspace;

            if (folder == null)
            {
                Program.Error(log, $"# Directory {String.Join("/", path)} does not exist");
                return;
            }

            var copy = folder.Copy();

            log.WriteLine($"# Counting keys under {FdbKey.Dump(copy.GetPrefix())} ...");

            var progress = new Progress <(long Count, Slice Current)>((state) =>
            {
                log.Write($"\r# Found {state.Count:N0} keys...");
            });

            long count = await Fdb.System.EstimateCountAsync(db, copy.ToRange(), progress, ct);

            log.Write("\r");
            Program.Success(log, $"Found {count:N0} keys in {folder.FullName}");
        }
Пример #4
0
 public static void Deconstruct <T1, T2, T3>(this IVarTuple value, [MaybeNull] out T1 item1, [MaybeNull] out T2 item2, [MaybeNull] out T3 item3)
 {
     value.OfSize(3);
     item1 = value.Get <T1>(0) !;
     item2 = value.Get <T2>(1) !;
     item3 = value.Get <T3>(2) !;
 }
        /// <summary>Shows the first few keys of a directory</summary>
        public static async Task Show(string[] path, IVarTuple extras, bool reverse, IFdbDatabase db, TextWriter log, CancellationToken ct)
        {
            int count = 20;

            if (extras.Count > 0)
            {
                int x = extras.Get <int>(0);
                if (x > 0)
                {
                    count = x;
                }
            }

            if (path == null || path.Length == 0)
            {
                Program.Error(log, "Cannot directory list the content of Root Partition.");
                return;
            }

            // look if there is something under there
            var folder = await db.Directory.TryOpenAsync(db, path, ct : ct);

            if (folder != null)
            {
                if (folder.Layer == FdbDirectoryPartition.LayerId)
                {
                    Program.Error(log, "Cannot list the content of a Directory Partition!");
                    return;
                }
                Program.Comment(log, $"# Content of {FdbKey.Dump(folder.GetPrefix())} [{folder.GetPrefix().ToHexaString(' ')}]");

                var keys = await db.QueryAsync((tr) =>
                {
                    var query = tr.GetRange(folder.Keys.ToRange());
                    return(reverse
                                                ? query.Reverse().Take(count)
                                                : query.Take(count + 1));
                }, ct : ct);

                if (keys.Count > 0)
                {
                    if (reverse)
                    {
                        keys.Reverse();
                    }
                    foreach (var key in keys.Take(count))
                    {
                        log.WriteLine($"...{FdbKey.Dump(folder.ExtractKey(key.Key))} = {key.Value:V}");
                    }
                    if (!reverse && keys.Count == count + 1)
                    {
                        log.WriteLine("... more");
                    }
                }
                else
                {
                    log.WriteLine("Folder is empty");
                }
            }
        }
        /// <summary>Default (non-optimized) implementation for ITuple.StartsWith()</summary>
        /// <param name="a">Larger tuple</param>
        /// <param name="b">Smaller tuple</param>
        /// <returns>True if <paramref name="a"/> starts with (or is equal to) <paramref name="b"/></returns>
        public static bool StartsWith([NotNull] IVarTuple a, [NotNull] IVarTuple b)
        {
            Contract.Requires(a != null && b != null);
            if (object.ReferenceEquals(a, b))
            {
                return(true);
            }
            int an = a.Count;
            int bn = b.Count;

            if (bn > an)
            {
                return(false);
            }
            if (bn == 0)
            {
                return(true);                     // note: 'an' can only be 0 because of previous test
            }
            for (int i = 0; i < bn; i++)
            {
                if (!object.Equals(a[i], b[i]))
                {
                    return(false);
                }
            }
            return(true);
        }
        /// <summary>Remove a directory and all its data</summary>
        public static async Task RemoveDirectory(string[] path, IVarTuple extras, IFdbDatabase db, TextWriter log, CancellationToken ct)
        {
            if (log == null)
            {
                log = Console.Out;
            }

            string layer = extras.Count > 0 ? extras.Get <string>(0) : null;

            var folder = await db.Directory.TryOpenAsync(path, ct : ct);

            if (folder == null)
            {
                Program.Error(log, $"# Directory /{string.Join("/", path)} does not exist");
                return;
            }

            // are there any subdirectories ?
            var subDirs = await folder.TryListAsync(db, ct);

            if (subDirs != null && subDirs.Count > 0)
            {
                //TODO: "-r" flag ?
                Program.Error(log, $"# Cannot remove /{string.Join("/", path)} because it still contains {subDirs.Count:N0} sub-directorie(s)");
            }

            //TODO: ask for confirmation?

            await folder.RemoveAsync(db, ct);

            Program.Success(log, $"Deleted directory /{string.Join("/", path)}");
        }
Пример #8
0
        public static IVarTuple Splice(IVarTuple tuple, Range range)
        {
            Contract.Requires(tuple != null);
            int count = tuple.Count;

            (int start, int len) = range.GetOffsetAndLength(count);
            if (len == 0)
            {
                return(STuple.Empty);
            }
            if (start == 0 && len == count)
            {
                return(tuple);
            }
            switch (len)
            {
            case 1:
                return(new ListTuple <object?>(new[] { tuple[start] }));

            case 2:
                return(new ListTuple <object?>(new[] { tuple[start], tuple[start + 1] }));

            default:
            {
                var items = new object?[len];
                //note: can be slow for tuples using linked-lists, but hopefully they will have their own Slice implementation...
                int q = start;
                for (int p = 0; p < items.Length; p++)
                {
                    items[p] = tuple[q++];
                }
                return(new ListTuple <object?>(items.AsMemory()));
            }
            }
        }
        /// <summary>Default (non-optimized) implementation for ITuple.EndsWith()</summary>
        /// <param name="a">Larger tuple</param>
        /// <param name="b">Smaller tuple</param>
        /// <returns>True if <paramref name="a"/> starts with (or is equal to) <paramref name="b"/></returns>
        public static bool EndsWith(IVarTuple a, IVarTuple b)
        {
            Contract.Debug.Requires(a != null && b != null);
            if (object.ReferenceEquals(a, b))
            {
                return(true);
            }
            int an = a.Count;
            int bn = b.Count;

            if (bn > an)
            {
                return(false);
            }
            if (bn == 0)
            {
                return(true);                     // note: 'an' can only be 0 because of previous test
            }
            int offset = an - bn;

            for (int i = 0; i < bn; i++)
            {
                if (!object.Equals(a[offset + i], b[i]))
                {
                    return(false);
                }
            }
            return(true);
        }
Пример #10
0
        private static void LogCommand(string prm, IVarTuple extras, TextWriter log)
        {
            switch (prm.ToLowerInvariant())
            {
            case "on":
            {
                LogEnabled = true;
                log.WriteLine("# Logging enabled");
                break;
            }

            case "off":
            {
                LogEnabled = false;
                log.WriteLine("# Logging disabled");
                break;
            }

            default:
            {
                log.WriteLine("# Logging is {0}", LogEnabled ? "ON" : "OFF");
                break;
            }
            }
        }
        /// <summary>Creates a new directory</summary>
        public static async Task CreateDirectory(string[] path, IVarTuple extras, IFdbDatabase db, TextWriter log, CancellationToken ct)
        {
            if (log == null)
            {
                log = Console.Out;
            }

            string layer = extras.Count > 0 ? extras.Get <string>(0) : null;

            log.WriteLine($"# Creating directory {String.Join("/", path)} with layer '{layer}'");

            var folder = await db.Directory.TryOpenAsync(db, path, ct : ct);

            if (folder != null)
            {
                log.WriteLine($"- Directory {string.Join("/", path)} already exists!");
                return;
            }

            folder = await db.Directory.TryCreateAsync(db, path, Slice.FromString(layer), ct : ct);

            log.WriteLine($"- Created under {FdbKey.Dump(folder.GetPrefix())} [{folder.GetPrefix().ToHexaString(' ')}]");

            // look if there is already stuff under there
            var stuff = await db.ReadAsync((tr) => tr.GetRange(folder.Keys.ToRange()).FirstOrDefaultAsync(), ct : ct);

            if (stuff.Key.IsPresent)
            {
                Program.Error(log, $"CAUTION: There is already some data under {string.Join("/", path)} !");
                Program.Error(log, $"  {FdbKey.Dump(stuff.Key)} = {stuff.Value:V}");
            }
        }
        public PrefixedTuple(Slice prefix, IVarTuple items)
        {
            Contract.Debug.Requires(!prefix.IsNull && items != null);

            m_prefix = prefix;
            m_items  = items;
        }
Пример #13
0
        /// <summary>Remove a directory and all its data</summary>
        public static async Task RemoveDirectory(string[] path, IVarTuple extras, IFdbDatabase db, TextWriter log, CancellationToken ct)
        {
            if (log == null)
            {
                log = Console.Out;
            }

            string layer = extras.Count > 0 ? extras.Get <string>(0) : null;

            var folder = await db.Directory.TryOpenAsync(path, ct : ct);

            if (folder == null)
            {
                log.WriteLine("# Directory {0} does not exist", string.Join("/", path));
                return;
            }

            // are there any subdirectories ?
            var subDirs = await folder.TryListAsync(db, ct);

            if (subDirs != null && subDirs.Count > 0)
            {
                //TODO: "-r" flag ?
                log.WriteLine("# Cannot remove {0} because it still contains {1} sub-directorie(s)", string.Join("/", path), subDirs.Count);
            }

            //TODO: ask for confirmation?

            log.WriteLine("# Deleting directory {0} ...", String.Join("/", path));
            await folder.RemoveAsync(db, ct);

            log.WriteLine("# Gone!");
        }
Пример #14
0
        /// <summary>Create a new list tuple by merging the items of three tuples together</summary>
        public ListTuple(IVarTuple a, IVarTuple b, IVarTuple c)
        {
            Contract.NotNull(a, nameof(a));
            Contract.NotNull(b, nameof(b));
            Contract.NotNull(c, nameof(c));

            int nA = a.Count;
            int nB = b.Count;
            int nC = c.Count;

            m_offset = 0;
            m_count  = nA + nB + nC;
            m_items  = new object[m_count];

            if (nA > 0)
            {
                a.CopyTo(m_items, 0);
            }
            if (nB > 0)
            {
                b.CopyTo(m_items, nA);
            }
            if (nC > 0)
            {
                c.CopyTo(m_items, nA + nB);
            }
        }
Пример #15
0
        public static T Last <T>(this IVarTuple tuple)
        {
#if USE_RANGE_API
            return(tuple.Get <T>(^ 1));
#else
            return(tuple.Get <T>(-1));
#endif
        }
Пример #16
0
        /// <summary>Test if the end of current tuple is equal to another tuple</summary>
        /// <param name="left">Larger tuple</param>
        /// <param name="right">Smaller tuple</param>
        /// <returns>True if the end of <paramref name="left"/> is equal to <paramref name="right"/> or if both tuples are identical</returns>
        public static bool EndsWith(this IVarTuple left, IVarTuple right)
        {
            Contract.NotNull(left, nameof(left));
            Contract.NotNull(right, nameof(right));

            //REVIEW: move this on ITuple interface ?
            return(TupleHelpers.EndsWith(left, right));
        }
Пример #17
0
        /// <summary>Append a new value at the end of an existing tuple</summary>
        public LinkedTuple(IVarTuple head, T tail)
        {
            Contract.NotNull(head);

            this.Head  = head;
            this.Tail  = tail;
            this.Depth = head.Count;
        }
Пример #18
0
 /// <summary>Returns a typed version of a tuple of size 2</summary>
 /// <typeparam name="T1">Expected type of the first element</typeparam>
 /// <typeparam name="T2">Expected type of the second element</typeparam>
 /// <param name="tuple">Tuple that must be of size 2</param>
 /// <returns>Equivalent tuple, with its elements converted to the specified types</returns>
 public static ValueTuple <T1, T2> As <T1, T2>(this IVarTuple tuple)
 {
     tuple.OfSize(2);
     return(
         tuple.Get <T1>(0),
         tuple.Get <T2>(1)
         );
 }
Пример #19
0
 public static void Deconstruct <T1, T2, T3, T4, T5>(this IVarTuple value, [MaybeNull] out T1 item1, [MaybeNull] out T2 item2, [MaybeNull] out T3 item3, [MaybeNull] out T4 item4, [MaybeNull] out T5 item5)
 {
     value.OfSize(5);
     item1 = value.Get <T1>(0) !;
     item2 = value.Get <T2>(1) !;
     item3 = value.Get <T3>(2) !;
     item4 = value.Get <T4>(3) !;
     item5 = value.Get <T5>(4) !;
 }
Пример #20
0
 /// <summary>Returns a typed version of a tuple of size 3</summary>
 /// <typeparam name="T1">Expected type of the first element</typeparam>
 /// <typeparam name="T2">Expected type of the second element</typeparam>
 /// <typeparam name="T3">Expected type of the third element</typeparam>
 /// <param name="tuple">Tuple that must be of size 3</param>
 /// <returns>Equivalent tuple, with its elements converted to the specified types</returns>
 public static ValueTuple <T1, T2, T3> As <T1, T2, T3>([NotNull] this IVarTuple tuple)
 {
     tuple.OfSize(3);
     return(
         tuple.Get <T1>(0),
         tuple.Get <T2>(1),
         tuple.Get <T3>(2)
         );
 }
Пример #21
0
 public static void Deconstruct <T1, T2, T3, T4, T5>(this IVarTuple value, out T1 item1, out T2 item2, out T3 item3, out T4 item4, out T5 item5)
 {
     value.OfSize(5);
     item1 = value.Get <T1>(0);
     item2 = value.Get <T2>(1);
     item3 = value.Get <T3>(2);
     item4 = value.Get <T4>(3);
     item5 = value.Get <T5>(4);
 }
        public static async Task Dump(string[] path, string output, IVarTuple extras, IFdbDatabase db, TextWriter log, CancellationToken ct)
        {
            // look if there is something under there
            var folder = await db.Directory.TryOpenAsync(db, path, ct : ct);

            if (folder == null)
            {
                Program.Comment(log, $"# Directory {String.Join("/", path)} does not exist");
                return;
            }

            //TODO: if file already exists, ask confirmation before overriding?
            output = Path.GetFullPath(output);
            File.Delete(output);

            using (var fs = new FileStream(output, FileMode.Create, FileAccess.Write, FileShare.Read, 64 * 1024))
                using (var sw = new StreamWriter(fs, Encoding.UTF8, 32 * 1024))
                {
                    Program.Comment(log, $"# Dumping content of {FdbKey.Dump(folder.GetPrefix())} [{folder.GetPrefix().ToHexaString(' ')}] to {output}");
                    long bytes = 0;
                    var  kr    = new[] { '|', '/', '-', '\\' };
                    int  p     = 0;
                    var  count = await Fdb.Bulk.ExportAsync(
                        db,
                        folder.ToRange(),
                        (batch, offset, _ct) =>
                    {
                        if (log == Console.Out)
                        {
                            log.Write($"\r{kr[(p++) % kr.Length]} {bytes:N0} bytes");
                        }
                        foreach (var kv in batch)
                        {
                            bytes += kv.Key.Count + kv.Value.Count;
                            sw.WriteLine("{0} = {1:V}", FdbKey.Dump(folder.ExtractKey(kv.Key)), kv.Value);
                        }
                        ct.ThrowIfCancellationRequested();
                        return(sw.FlushAsync());
                    },
                        ct
                        );

                    if (log == Console.Out)
                    {
                        log.Write("\r");
                    }
                    if (count > 0)
                    {
                        Program.Success(log, $"Found {count:N0} keys ({bytes:N0} bytes)");
                    }
                    else
                    {
                        Program.StdOut(log, "Folder is empty.");
                    }
                }
        }
Пример #23
0
        public JoinedTuple(IVarTuple head, IVarTuple tail)
        {
            Contract.NotNull(head, nameof(head));
            Contract.NotNull(tail, nameof(tail));

            this.Head = head;
            this.Tail = tail;
            m_split   = head.Count;
            m_count   = m_split + tail.Count;
        }
        /// <summary>Helper to copy the content of a tuple at a specific position in an array</summary>
        /// <returns>Updated offset just after the last element of the copied tuple</returns>
        public static int CopyTo([NotNull] IVarTuple tuple, [NotNull] object[] array, int offset)
        {
            Contract.Requires(tuple != null && array != null && offset >= 0);

            foreach (var item in tuple)
            {
                array[offset++] = item;
            }
            return(offset);
        }
Пример #25
0
 /// <summary>Returns a typed version of a tuple of size 4</summary>
 /// <typeparam name="T1">Expected type of the first element</typeparam>
 /// <typeparam name="T2">Expected type of the second element</typeparam>
 /// <typeparam name="T3">Expected type of the third element</typeparam>
 /// <typeparam name="T4">Expected type of the fourth element</typeparam>
 /// <param name="tuple">Tuple that must be of size 4</param>
 /// <returns>Equivalent tuple, with its elements converted to the specified types</returns>
 public static ValueTuple <T1, T2, T3, T4> As <T1, T2, T3, T4>(this IVarTuple tuple)
 {
     tuple.OfSize(4);
     return(
         tuple.Get <T1>(0),
         tuple.Get <T2>(1),
         tuple.Get <T3>(2),
         tuple.Get <T4>(3)
         );
 }
        public PrefixedTuple Concat(IVarTuple tuple)
        {
            Contract.NotNull(tuple);
            if (tuple.Count == 0)
            {
                return(this);
            }

            return(new PrefixedTuple(m_prefix, m_items.Concat(tuple)));
        }
Пример #27
0
 /// <summary>Returns a typed version of a tuple of size 5</summary>
 /// <typeparam name="T1">Expected type of the first element</typeparam>
 /// <typeparam name="T2">Expected type of the second element</typeparam>
 /// <typeparam name="T3">Expected type of the third element</typeparam>
 /// <typeparam name="T4">Expected type of the fourth element</typeparam>
 /// <typeparam name="T5">Expected type of the fifth element</typeparam>
 /// <param name="tuple">Tuple that must be of size 5</param>
 /// <returns>Equivalent tuple, with its elements converted to the specified types</returns>
 public static ValueTuple <T1, T2, T3, T4, T5> As <T1, T2, T3, T4, T5>([NotNull] this IVarTuple tuple)
 {
     tuple.OfSize(5);
     return(
         tuple.Get <T1>(0),
         tuple.Get <T2>(1),
         tuple.Get <T3>(2),
         tuple.Get <T4>(3),
         tuple.Get <T5>(4)
         );
 }
Пример #28
0
 public static void Deconstruct <T1, T2, T3, T4, T5, T6, T7>(this IVarTuple value, out T1 item1, out T2 item2, out T3 item3, out T4 item4, out T5 item5, out T6 item6, out T7 item7)
 {
     value.OfSize(7);
     item1 = value.Get <T1>(0);
     item2 = value.Get <T2>(1);
     item3 = value.Get <T3>(2);
     item4 = value.Get <T4>(3);
     item5 = value.Get <T5>(4);
     item6 = value.Get <T6>(5);
     item7 = value.Get <T7>(6);
 }
 protected override FdbDirectoryLayer GetLayerForPath(IVarTuple relativeLocation)
 {
     if (relativeLocation.Count == 0)
     {             // Forward all actions on the Partition itself (empty path) to its parent's DL
         return(this.ParentDirectoryLayer);
     }
     else
     {             // For everything else, use the Partition's DL
         return(this.DirectoryLayer);
     }
 }
Пример #30
0
 public static void Deconstruct <T1, T2, T3, T4, T5, T6, T7>(this IVarTuple value, [MaybeNull] out T1 item1, [MaybeNull] out T2 item2, [MaybeNull] out T3 item3, [MaybeNull] out T4 item4, [MaybeNull] out T5 item5, [MaybeNull] out T6 item6, [MaybeNull] out T7 item7)
 {
     value.OfSize(7);
     item1 = value.Get <T1>(0) !;
     item2 = value.Get <T2>(1) !;
     item3 = value.Get <T3>(2) !;
     item4 = value.Get <T4>(3) !;
     item5 = value.Get <T5>(4) !;
     item6 = value.Get <T6>(5) !;
     item7 = value.Get <T7>(6) !;
 }