Beispiel #1
0
    public static AsyncReply TypedListParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
    {
        var rt = new AsyncBag <object>();

        // get the type
        var(hdrCs, rep) = RepresentationType.Parse(data, offset);

        offset += hdrCs;
        length -= hdrCs;

        var runtimeType = rep.GetRuntimeType();

        rt.ArrayType = runtimeType;

        while (length > 0)
        {
            var(cs, reply) = Codec.Parse(data, offset, connection, requestSequence);

            rt.Add(reply);

            if (cs > 0)
            {
                offset += (uint)cs;
                length -= (uint)cs;
            }
            else
            {
                throw new Exception("Error while parsing structured data");
            }
        }

        rt.Seal();
        return(rt);
    }
Beispiel #2
0
    public AsyncBag <T> Children <T>(IResource resource, string name) where T : IResource
    {
        if (resource == this)
        {
            IFindFluent <BsonDocument, BsonDocument> match;

            if (name == null)
            {
                match = resourcesCollection.Find(x => (x["parents"] as BsonArray).Contains(this.Instance.Name));
            }
            else
            {
                match = resourcesCollection.Find(x => (x["parents"] as BsonArray).Contains(this.Instance.Name) && x["name"] == name);
            }


            var st = match.ToList().Select(x => x["_id"].ToString()).ToArray();


            var bag = new AsyncBag <T>();

            foreach (var s in st)
            {
                var r = Fetch <T>(s);
                if (r.Ready && r.Result == null)
                {
                    continue;
                }

                bag.Add(r);
            }

            bag.Seal();
            return(bag);
        }
        else
        {
            var children = (string[])resource.Instance.Variables["children"];

            if (children == null)
            {
                return(new AsyncBag <T>(null));
            }

            var rt = new AsyncBag <T>();


            foreach (var child in children)
            {
                var r = Warehouse.Get <T>(child);
                if (r is AsyncReply <T> )
                {
                    rt.Add(r);// (AsyncReply<T>)r);
                }
            }

            rt.Seal();
            return(rt);
        }
    }
Beispiel #3
0
    public AsyncBag <T> Parents <T>(IResource resource, string name) where T : IResource
    {
        if (resource == this)
        {
            return(new AsyncBag <T>(null));
        }
        else
        {
            var parents = (string[])resource.Instance.Variables["parents"];

            if (parents == null)
            {
                return(new AsyncBag <T>(null));
            }

            var rt = new AsyncBag <T>();



            foreach (var parent in parents)
            {
                var r = Warehouse.Get <T>(parent);
                if (r is AsyncReply <T> )
                {
                    rt.Add(r);// (AsyncReply<T>)r);
                }
            }


            rt.Seal();


            return(rt);
        }
    }
Beispiel #4
0
        public AsyncReply <KeyList <PropertyTemplate, PropertyValue[]> > GetRecord(IResource resource, DateTime fromDate, DateTime toDate)
        {
            var properties = resource.Instance.Template.Properties.Where(x => x.Storage == StorageMode.Recordable).ToList();

            var reply = new AsyncReply <KeyList <PropertyTemplate, PropertyValue[]> >();

            AsyncBag <PropertyValue[]> bag = new AsyncBag <PropertyValue[]>();

            foreach (var p in properties)
            {
                bag.Add(GetPropertyRecordByDate(resource, p.Name, fromDate, toDate));
            }

            bag.Seal();

            bag.Then(x =>
            {
                var list = new KeyList <PropertyTemplate, PropertyValue[]>();

                for (var i = 0; i < x.Length; i++)
                {
                    list.Add(properties[i], x[i]);
                }

                reply.Trigger(list);
            });

            return(reply);
        }
Beispiel #5
0
    /// <summary>
    /// Close the warehouse.
    /// This function issues terminate trigger to all resources and stores.
    /// </summary>
    /// <returns>True, if no problem occurred.</returns>
    public static AsyncReply <bool> Close()
    {
        var bag = new AsyncBag <bool>();

        foreach (var resource in resources.Values)
        {
            IResource r;
            if (resource.TryGetTarget(out r))
            {
                if (!(r is IStore))
                {
                    bag.Add(r.Trigger(ResourceTrigger.Terminate));
                }
            }
        }

        foreach (var store in stores)
        {
            bag.Add(store.Key.Trigger(ResourceTrigger.Terminate));
        }


        foreach (var resource in resources.Values)
        {
            IResource r;
            if (resource.TryGetTarget(out r))
            {
                if (!(r is IStore))
                {
                    bag.Add(r.Trigger(ResourceTrigger.SystemTerminated));
                }
            }
        }


        foreach (var store in stores)
        {
            bag.Add(store.Key.Trigger(ResourceTrigger.SystemTerminated));
        }

        bag.Seal();

        var rt = new AsyncReply <bool>();

        bag.Then((x) =>
        {
            foreach (var b in x)
            {
                if (!b)
                {
                    rt.Trigger(false);
                    return;
                }
            }

            rt.Trigger(true);
        });

        return(rt);
    }
Beispiel #6
0
    public static AsyncReply TupleParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
    {
        var results = new AsyncBag <object>();
        var rt      = new AsyncReply();

        var tupleSize = data[offset++];

        length--;

        var types = new List <Type>();

        for (var i = 0; i < tupleSize; i++)
        {
            var(cs, rep) = RepresentationType.Parse(data, offset);
            types.Add(rep.GetRuntimeType());
            offset += cs;
            length -= cs;
        }

        while (length > 0)
        {
            var(cs, reply) = Codec.Parse(data, offset, connection, requestSequence);

            results.Add(reply);

            if (cs > 0)
            {
                offset += (uint)cs;
                length -= (uint)cs;
            }
            else
            {
                throw new Exception("Error while parsing structured data");
            }
        }

        results.Seal();


        results.Then(ar =>
        {
            if (ar.Length == 2)
            {
                var type = typeof(ValueTuple <,>).MakeGenericType(types.ToArray());
                rt.Trigger(Activator.CreateInstance(type, ar[0], ar[1]));
            }
            else if (ar.Length == 3)
            {
                var type = typeof(ValueTuple <, ,>).MakeGenericType(types.ToArray());
                rt.Trigger(Activator.CreateInstance(type, ar[0], ar[1], ar[2]));
            }
            else if (ar.Length == 4)
            {
                var type = typeof(ValueTuple <, , ,>).MakeGenericType(types.ToArray());
                rt.Trigger(Activator.CreateInstance(type, ar[0], ar[1], ar[2], ar[3]));
            }
        });

        return(rt);
    }
Beispiel #7
0
        /// <summary>
        /// Open the warehouse.
        /// This function issues the initialize trigger to all stores and resources.
        /// </summary>
        /// <returns>True, if no problem occurred.</returns>
        public static AsyncReply <bool> Open()
        {
            var bag = new AsyncBag <bool>();

            foreach (var store in stores)
            {
                bag.Add(store.Trigger(ResourceTrigger.Initialize));
            }


            bag.Seal();

            var rt = new AsyncReply <bool>();

            bag.Then((x) =>
            {
                foreach (var b in x)
                {
                    if (!b)
                    {
                        rt.Trigger(false);
                        return;
                    }
                }

                var rBag = new AsyncBag <bool>();
                foreach (var rk in resources)
                {
                    rBag.Add(rk.Value.Trigger(ResourceTrigger.SystemInitialized));
                }

                rBag.Seal();

                rBag.Then(y =>
                {
                    foreach (var b in y)
                    {
                        if (!b)
                        {
                            rt.Trigger(false);
                            return;
                        }
                    }

                    rt.Trigger(true);
                    storeIsOpen = true;
                });
            });

            return(rt);
        }
Beispiel #8
0
    public static AsyncReply TypedMapParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
    {
        // get key type
        var(keyCs, keyRepType) = RepresentationType.Parse(data, offset);
        offset += keyCs;
        length -= keyCs;

        var(valueCs, valueRepType) = RepresentationType.Parse(data, offset);
        offset += valueCs;
        length -= valueCs;

        var map = (IMap)Activator.CreateInstance(typeof(Map <,>).MakeGenericType(keyRepType.GetRuntimeType(), valueRepType.GetRuntimeType()));

        var rt = new AsyncReply();

        var results = new AsyncBag <object>();

        while (length > 0)
        {
            var(cs, reply) = Codec.Parse(data, offset, connection, requestSequence);


            results.Add(reply);

            if (cs > 0)
            {
                offset += (uint)cs;
                length -= (uint)cs;
            }
            else
            {
                throw new Exception("Error while parsing structured data");
            }
        }

        results.Seal();

        results.Then(ar =>
        {
            for (var i = 0; i < ar.Length; i += 2)
            {
                map.Add(ar[i], ar[i + 1]);
            }

            rt.Trigger(map);
        });


        return(rt);
    }
Beispiel #9
0
        public AsyncReply <bool> Trigger(ResourceTrigger trigger)
        {
            if (trigger == ResourceTrigger.Initialize)
            {
                var filter = new BsonDocument();

                var list = resourcesCollection.Find(filter).ToList();

                Console.WriteLine(list.Count);

                // if (list.Count == 0)
                //   return new AsyncBag<IResource>(new IResource[0]);

                var bag = new AsyncBag <IResource>();

                for (var i = 0; i < list.Count; i++)
                {
                    Console.WriteLine("Loading {0}/{1}", i, list.Count);
                    bag.Add(Get("id/" + list[i]["_id"].AsObjectId.ToString()));
                }

                bag.Seal();

                var rt = new AsyncReply <bool>();

                bag.Then((x) => { rt.Trigger(true); });

                return(rt);
            }
            else if (trigger == ResourceTrigger.Terminate)
            {
                // save all resources
                foreach (var resource in resources.Values)
                {
                    SaveResource(resource);
                }

                return(new AsyncReply <bool>(true));
            }
            else
            {
                return(new AsyncReply <bool>(true));
            }
        }
Beispiel #10
0
    public static AsyncReply <KeyList <PropertyTemplate, PropertyValue[]> > HistoryParser(byte[] data, uint offset, uint length, IResource resource, DistributedConnection connection, uint[] requestSequence)
    {
        //var count = (int)toAge - (int)fromAge;

        var list = new KeyList <PropertyTemplate, PropertyValue[]>();

        var reply = new AsyncReply <KeyList <PropertyTemplate, PropertyValue[]> >();

        var bagOfBags = new AsyncBag <PropertyValue[]>();

        var ends = offset + length;

        while (offset < ends)
        {
            var index = data[offset++];
            var pt    = resource.Instance.Template.GetPropertyTemplateByIndex(index);
            list.Add(pt, null);
            var cs = data.GetUInt32(offset, Endian.Little);
            offset += 4;

            var(len, pv) = PropertyValueParser(data, offset, connection, requestSequence);

            bagOfBags.Add(pv);// ParsePropertyValueArray(data, offset, cs, connection));
            offset += len;
        }

        bagOfBags.Seal();

        bagOfBags.Then(x =>
        {
            for (var i = 0; i < list.Count; i++)
            {
                list[list.Keys.ElementAt(i)] = x[i];
            }

            reply.Trigger(list);
        });

        return(reply);
    }
Beispiel #11
0
        public AsyncReply <PropertyValue[]> GetPropertyRecordByDate(IResource resource, string propertyName, DateTime fromDate, DateTime toDate)
        {
            var objectId = resource.Instance.Attributes["objectId"].ToString();

            var record  = this.database.GetCollection <BsonDocument>("record_" + objectId);
            var builder = Builders <BsonDocument> .Filter;

            var filter = builder.Gte("date", fromDate) & builder.Lte("date", toDate) & builder.Eq("property", propertyName);

            var reply = new AsyncReply <PropertyValue[]>();

            record.FindAsync(filter).ContinueWith((x) =>
            {
                var values = ((Task <IAsyncCursor <BsonDocument> >)x).Result.ToList();

                var bag = new AsyncBag <object>();

                foreach (var v in values)
                {
                    bag.Add(Parse(v["value"]));
                }

                bag.Seal();

                bag.Then((results) =>
                {
                    var list = new List <PropertyValue>();
                    for (var i = 0; i < results.Length; i++)
                    {
                        list.Add(new PropertyValue(results[i], (ulong)values[i]["age"].AsInt64, values[i]["date"].ToUniversalTime()));
                    }

                    reply.Trigger(list.ToArray());
                });
            });

            return(reply);
        }
Beispiel #12
0
        /// <summary>
        /// Parse an array of bytes into an array of varialbes.
        /// </summary>
        /// <param name="data">Array of bytes.</param>
        /// <param name="offset">Zero-indexed offset.</param>
        /// <param name="length">Number of bytes to parse.</param>
        /// <param name="connection">DistributedConnection is required to fetch resources.</param>
        /// <returns>Array of variables.</returns>
        public static AsyncBag <object> ParseVarArray(byte[] data, uint offset, uint length, DistributedConnection connection)
        {
            var rt = new AsyncBag <object>();

            while (length > 0)
            {
                uint cs;

                rt.Add(Parse(data, offset, out cs, connection));

                if (cs > 0)
                {
                    offset += (uint)cs;
                    length -= (uint)cs;
                }
                else
                {
                    throw new Exception("Error while parsing structured data");
                }
            }

            rt.Seal();
            return(rt);
        }
Beispiel #13
0
        /// <summary>
        /// Parse an array of PropertyValue.
        /// </summary>
        /// <param name="data">Array of bytes.</param>
        /// <param name="offset">Zero-indexed offset.</param>
        /// <param name="length">Number of bytes to parse.</param>
        /// <param name="connection">DistributedConnection is required to fetch resources.</param>
        /// <param name="ageIncluded">Whether property age is represented in the data.</param>
        /// <returns></returns>
        public static AsyncBag <PropertyValue> ParsePropertyValueArray(byte[] data, uint offset, uint length, DistributedConnection connection)//, bool ageIncluded = true)
        {
            var rt = new AsyncBag <PropertyValue>();

            while (length > 0)
            {
                uint cs;

                rt.Add(ParsePropertyValue(data, offset, out cs, connection));//, ageIncluded));

                if (cs > 0)
                {
                    offset += (uint)cs;
                    length -= (uint)cs;
                }
                else
                {
                    throw new Exception("Error while parsing ValueInfo structured data");
                }
            }

            rt.Seal();
            return(rt);
        }
Beispiel #14
0
    public static AsyncBag <object> ListParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
    {
        var rt = new AsyncBag <object>();

        while (length > 0)
        {
            var(cs, reply) = Codec.Parse(data, offset, connection, requestSequence);

            rt.Add(reply);

            if (cs > 0)
            {
                offset += (uint)cs;
                length -= (uint)cs;
            }
            else
            {
                throw new Exception("Error while parsing structured data");
            }
        }

        rt.Seal();
        return(rt);
    }
Beispiel #15
0
        AsyncReply <IResource> Fetch(string id)
        {
            var filter = Builders <BsonDocument> .Filter.Eq("_id", new BsonObjectId(new ObjectId(id)));

            var list = resourcesCollection.Find(filter).ToList();

            if (list.Count == 0)
            {
                return(new AsyncReply <IResource>(null));
            }
            var document = list[0];


            IResource resource = (IResource)Activator.CreateInstance(Type.GetType(document["classname"].AsString));

            resources.Add(document["_id"].AsObjectId.ToString(), resource);

            Warehouse.Put(resource, document["name"].AsString, this);


            var parents  = document["parents"].AsBsonArray;
            var children = document["children"].AsBsonArray;
            //var managers = document["managers"].AsBsonArray;

            var attributes = Parse(document["attributes"]).Then(x => {
                resource.Instance.SetAttributes(x as Structure);
            });

            var bag = new AsyncBag <object>();

            foreach (var p in parents)
            {
                var ap = Warehouse.Get(p.AsString);
                bag.Add(ap);
                ap.Then((x) =>
                {
                    if (!resource.Instance.Parents.Contains(x))
                    {
                        resource.Instance.Parents.Add(x);
                    }
                });
            }

            foreach (var c in children)
            {
                var ac = Warehouse.Get(c.AsString);
                bag.Add(ac);
                ac.Then((x) =>
                {
                    if (!resource.Instance.Children.Contains(x))
                    {
                        resource.Instance.Children.Add(x);
                    }
                });
            }

            /*
             * // load managers
             * foreach(var m in managers)
             * {
             *  IPermissionsManager pm = (IPermissionsManager)Activator.CreateInstance(Type.GetType(m["classname"].AsString));
             *  var sr = Parse(m["settings"]);
             *  bag.Add(sr);
             *  sr.Then((x) =>
             *  {
             *      pm.Initialize((Structure)x, resource);
             *      resource.Instance.Managers.Add(pm);
             *  });
             * }
             */

            // Load values
            var values = document["values"].AsBsonDocument;


            foreach (var v in values)
            {
                var valueInfo = v.Value as BsonDocument;

                var av = Parse(valueInfo["value"]);
                bag.Add(av);
                av.Then((x) =>
                {
                    resource.Instance.LoadProperty(v.Name, (ulong)valueInfo["age"].AsInt64, valueInfo["modification"].ToUniversalTime(), x);
                });
            }

            bag.Seal();

            var rt = new AsyncReply <IResource>();

            bag.Then((x) =>
            {
                rt.Trigger(resource);
            });

            return(rt);
        }
Beispiel #16
0
        /// <summary>
        /// Parse an array of structures
        /// </summary>
        /// <param name="data">Bytes array</param>
        /// <param name="offset">Zero-indexed offset</param>
        /// <param name="length">Number of bytes to parse</param>
        /// <param name="connection">DistributedConnection is required in case a structure in the array holds items at the other end</param>
        /// <returns>Array of structures</returns>
        public static AsyncBag <Structure> ParseStructureArray(byte[] data, uint offset, uint length, DistributedConnection connection)
        {
            var reply = new AsyncBag <Structure>();

            if (length == 0)
            {
                reply.Seal();
                return(reply);
            }

            var end = offset + length;

            var result = (StructureComparisonResult)data[offset++];

            AsyncReply previous = null;

            // string[] previousKeys = null;
            // DataType[] previousTypes = null;

            Structure.StructureMetadata metadata = new Structure.StructureMetadata();


            if (result == StructureComparisonResult.Null)
            {
                previous = new AsyncReply <Structure>(null);
            }
            else if (result == StructureComparisonResult.Structure)
            {
                uint cs = data.GetUInt32(offset);
                offset  += 4;
                previous = ParseStructure(data, offset, cs, connection, out metadata);
                offset  += cs;
            }

            reply.Add(previous);


            while (offset < end)
            {
                result = (StructureComparisonResult)data[offset++];

                if (result == StructureComparisonResult.Null)
                {
                    previous = new AsyncReply <Structure>(null);
                }
                else if (result == StructureComparisonResult.Structure)
                {
                    uint cs = data.GetUInt32(offset);
                    offset  += 4;
                    previous = ParseStructure(data, offset, cs, connection, out metadata);// out previousKeys, out previousTypes);
                    offset  += cs;
                }
                else if (result == StructureComparisonResult.StructureSameKeys)
                {
                    uint cs = data.GetUInt32(offset);
                    offset  += 4;
                    previous = ParseStructure(data, offset, cs, connection, out metadata, metadata.Keys);
                    offset  += cs;
                }
                else if (result == StructureComparisonResult.StructureSameTypes)
                {
                    uint cs = data.GetUInt32(offset);
                    offset  += 4;
                    previous = ParseStructure(data, offset, cs, connection, out metadata, metadata.Keys, metadata.Types);
                    offset  += cs;
                }

                reply.Add(previous);
            }

            reply.Seal();
            return(reply);
        }
Beispiel #17
0
        AsyncReply Parse(BsonValue value)
        {
            if (value.BsonType == BsonType.Document)
            {
                var doc = value.AsBsonDocument;
                if (doc["type"] == 0)
                {
                    return(Warehouse.Get(doc["link"].AsString));
                } // structure
                else if (doc["type"] == 1)
                {
                    var bag = new AsyncBag <object>();
                    var rt  = new AsyncReply <Structure>();

                    var bs = (BsonDocument)doc["values"].AsBsonDocument;
                    var s  = new Structure();

                    foreach (var v in bs)
                    {
                        bag.Add(Parse(v.Value));
                    }

                    bag.Seal();
                    bag.Then((x) =>
                    {
                        for (var i = 0; i < x.Length; i++)
                        {
                            s[bs.GetElement(i).Name] = x[i];
                        }

                        rt.Trigger(s);
                    });

                    return(rt);
                }
                else
                {
                    return(new AsyncReply(null));
                }
            }
            else if (value.BsonType == BsonType.Array)
            {
                var array = value.AsBsonArray;
                var bag   = new AsyncBag <object>();

                foreach (var v in array)
                {
                    bag.Add(Parse(v));
                }

                bag.Seal();

                return(bag);
            }
            else if (value.BsonType == BsonType.DateTime)
            {
                return(new AsyncReply(value.ToUniversalTime()));
            }
            else
            {
                return(new AsyncReply(value.RawValue));
            }
        }
Beispiel #18
0
        /// <summary>
        /// Parse a structure
        /// </summary>
        /// <param name="data">Bytes array</param>
        /// <param name="offset">Zero-indexed offset.</param>
        /// <param name="length">Number of bytes to parse.</param>
        /// <param name="connection">DistributedConnection is required in case a structure in the array holds items at the other end.</param>
        /// <param name="parsedKeys">Array to store keys in.</param>
        /// <param name="parsedTypes">Array to store DataTypes in.</param>
        /// <param name="keys">Array of keys, in case the data doesn't include keys</param>
        /// <param name="types">Array of DataTypes, in case the data doesn't include DataTypes</param>
        /// <returns>Structure</returns>
        public static AsyncReply <Structure> ParseStructure(byte[] data, uint offset, uint length, DistributedConnection connection, out Structure.StructureMetadata metadata, string[] keys = null, DataType[] types = null)// out string[] parsedKeys, out DataType[] parsedTypes, string[] keys = null, DataType[] types = null)
        {
            var reply    = new AsyncReply <Structure>();
            var bag      = new AsyncBag <object>();
            var keylist  = new List <string>();
            var typelist = new List <DataType>();

            if (keys == null)
            {
                while (length > 0)
                {
                    var len = data[offset++];
                    keylist.Add(data.GetString(offset, len));
                    offset += len;

                    typelist.Add((DataType)data[offset]);

                    uint rt;
                    bag.Add(Codec.Parse(data, offset, out rt, connection));
                    length -= rt + len + 1;
                    offset += rt;
                }
            }
            else if (types == null)
            {
                keylist.AddRange(keys);

                while (length > 0)
                {
                    typelist.Add((DataType)data[offset]);

                    uint rt;
                    bag.Add(Codec.Parse(data, offset, out rt, connection));
                    length -= rt;
                    offset += rt;
                }
            }
            else
            {
                keylist.AddRange(keys);
                typelist.AddRange(types);

                var i = 0;
                while (length > 0)
                {
                    uint rt;
                    bag.Add(Codec.Parse(data, offset, out rt, connection, types[i]));
                    length -= rt;
                    offset += rt;
                    i++;
                }
            }

            bag.Seal();

            bag.Then((res) =>
            {
                // compose the list
                var s = new Structure();
                for (var i = 0; i < keylist.Count; i++)
                {
                    s[keylist[i]] = res[i];
                }
                reply.Trigger(s);
            });

            metadata = new Structure.StructureMetadata()
            {
                Keys = keylist.ToArray(), Types = typelist.ToArray()
            };

            return(reply);
        }
Beispiel #19
0
        /// <summary>
        /// Parse an array of bytes into array of resources
        /// </summary>
        /// <param name="data">Array of bytes.</param>
        /// <param name="length">Number of bytes to parse.</param>
        /// <param name="offset">Zero-indexed offset.</param>
        /// <param name="connection">DistributedConnection is required to fetch resources.</param>
        /// <returns>Array of resources.</returns>
        public static AsyncBag <IResource> ParseResourceArray(byte[] data, uint offset, uint length, DistributedConnection connection)
        {
            var reply = new AsyncBag <IResource>();

            if (length == 0)
            {
                reply.Seal();
                return(reply);
            }

            var end = offset + length;

            //
            var result = (ResourceComparisonResult)data[offset++];

            AsyncReply previous = null;

            if (result == ResourceComparisonResult.Null)
            {
                previous = new AsyncReply <IResource>(null);
            }
            else if (result == ResourceComparisonResult.Local)
            {
                previous = Warehouse.Get(data.GetUInt32(offset));
                offset  += 4;
            }
            else if (result == ResourceComparisonResult.Distributed)
            {
                previous = connection.Fetch(data.GetUInt32(offset));
                offset  += 4;
            }

            reply.Add(previous);


            while (offset < end)
            {
                result = (ResourceComparisonResult)data[offset++];

                AsyncReply current = null;

                if (result == ResourceComparisonResult.Null)
                {
                    current = new AsyncReply <IResource>(null);
                }
                else if (result == ResourceComparisonResult.Same)
                {
                    current = previous;
                }
                else if (result == ResourceComparisonResult.Local)
                {
                    current = Warehouse.Get(data.GetUInt32(offset));
                    offset += 4;
                }
                else if (result == ResourceComparisonResult.Distributed)
                {
                    current = connection.Fetch(data.GetUInt32(offset));
                    offset += 4;
                }

                reply.Add(current);

                previous = current;
            }

            reply.Seal();
            return(reply);
        }