private static async Task SyncOneEntryObject(
            Tuple <JObject, List <int>, int, string> tuple,
            BlobDirectory dir, String entry, List <int> statuses)
        {
            if (!Object.ReferenceEquals(tuple.Item2, null) && tuple.Item2.Count > 0)
            {
                var dirProviders = dir.GetAllProviders();
                if (Object.ReferenceEquals(statuses, null))
                {
                    statuses = dirProviders.ConvertAll(x => 0);
                }

                var content = tuple.Item1.ToString();
                foreach (var i in tuple.Item2)
                {
                    try
                    {
                        if (statuses[i] >= 0)
                        {
                            var item = dirProviders[i].GetBlockBlobReference(entry);
                            await item.UploadTextAsync(content);

                            Console.WriteLine($"Sync {dir.Name}/{entry} for {dirProviders[i].Provider.Name}");
                            statuses[i] = 1;
                        }
                    }
                    catch
                    {
                        var provider = dirProviders[i].Provider.Name;
                        Console.WriteLine($"Sync {entry} failed, the provider {provider} is not operational");
                        statuses[i] = -1;
                    }
                }
            }
        }
        /// <summary>
        /// Gets the consistent JObject, this is used for JObject that are stored at multiple cloud provider without the hash (for consistency).
        /// A certain  key, usually time, is used to identity the freshness of the JObject, the object with the latest time is considered the latest.
        /// </summary>
        /// <returns>The consistent JObject, a list of blob that needs to be updated, current blob, and eTag (if exists) </returns>
        /// <param name="dir">directory.</param>
        /// <param name="tag">path .</param>
        public static async Task <Tuple <JObject, List <int>, int, string> > GetConsistentJObject(BlobDirectory dir, String entry, String timeTag = Constant.JSonKeyTime)
        {
            var allDirs  = dir.GetAllProviders();
            var allBlobs = allDirs.ConvertAll(x => x.GetBlockBlobReference(entry));
            var allTasks = allBlobs.ConvertAll(x => x.DownloadTextAsync());

            try
            {
                await Task.WhenAll(allTasks);
            } catch {};

            List <Tuple <String, int> > curStrs = new List <Tuple <string, int> >();

            for (int i = 0; i < allBlobs.Count; i++)
            {
                var    task    = allTasks[i];
                var    curBlob = allBlobs[i];
                String str     = null;
                if (task.Status == TaskStatus.RanToCompletion)
                {
                    str = task.Result;
                }
                curStrs.Add(new Tuple <String, int>(str, i));
            }
            ;
            // Nothing
            if (curStrs.Count <= 0)
            {
                return(new Tuple <JObject, List <int>, int, string>(new JObject(), null, -1, null));
            }
            var curObjs  = curStrs.ConvertAll(x => JsonUtils.TryParse(x.Item1));
            var modTicks = curObjs.ConvertAll(x => JsonUtils.GetType <Int64>(timeTag, x, 0L));
            // Console.WriteLine($"Consistency object {entry} ticks: {String.Join( ',', modTicks.ConvertAll(x => x.ToString()) )}");
            var bestObj = LatestModified(modTicks);

            if (bestObj < 0)
            {
                bestObj = 0;
            }
            var retObj = curObjs[bestObj];
            var retIdx = curStrs[bestObj].Item2;
            var eTag   = allBlobs[retIdx].ETag;
            var lst    = new List <int>();

            for (int i = 0; i < modTicks.Count; i++)
            {
                if (modTicks[i] < modTicks[bestObj])
                {
                    lst.Add(curStrs[i].Item2);
                }
            }

            if (lst.Count <= 0)
            {
                lst = null;
            }

            return(new Tuple <JObject, List <int>, int, string>(retObj, lst, retIdx, eTag));
        }