diff --git a/Esiur.Stores.EntityCore/EntityStore.cs b/Esiur.Stores.EntityCore/EntityStore.cs index 2d119d2..b8de6cd 100644 --- a/Esiur.Stores.EntityCore/EntityStore.cs +++ b/Esiur.Stores.EntityCore/EntityStore.cs @@ -103,7 +103,7 @@ public class EntityStore : IStore } } - public AsyncReply Put(IResource resource) + public AsyncReply Put(IResource resource, string path) { if (resource == this) return new AsyncReply(true); diff --git a/Esiur.Stores.EntityCore/EsiurExtensions.cs b/Esiur.Stores.EntityCore/EsiurExtensions.cs index 87720ed..c663739 100644 --- a/Esiur.Stores.EntityCore/EsiurExtensions.cs +++ b/Esiur.Stores.EntityCore/EsiurExtensions.cs @@ -131,7 +131,7 @@ public static class EsiurExtensions var id = store.TypesByType[typeof(T)].PrimaryKey.GetValue(resource); - await options.Warehouse.Put(id.ToString(), res, store, null, 0, manager); + await options.Warehouse.Put($"{store.Instance.Name}/{typeof(T).Name}/{id}", res, null, 0, manager); return (T)res; } diff --git a/Esiur.Stores.EntityCore/EsiurProxyRewrite.cs b/Esiur.Stores.EntityCore/EsiurProxyRewrite.cs index ca72c26..5e9877d 100644 --- a/Esiur.Stores.EntityCore/EsiurProxyRewrite.cs +++ b/Esiur.Stores.EntityCore/EsiurProxyRewrite.cs @@ -71,7 +71,7 @@ public class EsiurProxyRewrite : IModelFinalizingConvention // check if the object exists var obj = options.Warehouse.Create(entityType.ClrType) as IResource; options.Store.TypesByType[entityType.ClrType].PrimaryKey.SetValue(obj, id); - options.Warehouse.Put(id.ToString(), obj, options.Store, null, 0, manager).Wait(); + options.Warehouse.Put($"{options.Store.Instance.Name}/{entityType.ClrType.Name}/{id}", obj, null, 0, manager).Wait(); return obj; } else diff --git a/Esiur.Stores.MongoDB/MongoDBStore.cs b/Esiur.Stores.MongoDB/MongoDBStore.cs index 9fed634..04d2696 100644 --- a/Esiur.Stores.MongoDB/MongoDBStore.cs +++ b/Esiur.Stores.MongoDB/MongoDBStore.cs @@ -303,7 +303,7 @@ public class MongoDBStore : IStore return this.Instance.Name + "/id/" + (string)resource.Instance.Variables["objectId"]; } - public async AsyncReply Put(IResource resource) + public async AsyncReply Put(IResource resource, string path) { try { diff --git a/Esiur.Stores.MongoDB/MongoDBStoreGeneric.cs b/Esiur.Stores.MongoDB/MongoDBStoreGeneric.cs index ec5e96b..18d4c79 100644 --- a/Esiur.Stores.MongoDB/MongoDBStoreGeneric.cs +++ b/Esiur.Stores.MongoDB/MongoDBStoreGeneric.cs @@ -38,8 +38,8 @@ namespace Esiur.Stores.MongoDB [Export] public async AsyncReply New(string name = null, object properties = null) { - var resource = Instance.Warehouse.CreateInstance(properties); - await Instance.Warehouse.Put(name, resource, this, null, 0); + var resource = Instance.Warehouse.Create(properties); + await Instance.Warehouse.Put(this.Instance.Name + "/" + name, resource); resource.Instance.Managers.AddRange(this.Instance.Managers.ToArray()); return resource; } diff --git a/Esiur/Net/IIP/DistributedConnection.cs b/Esiur/Net/IIP/DistributedConnection.cs index aa94dad..aebfe02 100644 --- a/Esiur/Net/IIP/DistributedConnection.cs +++ b/Esiur/Net/IIP/DistributedConnection.cs @@ -1570,14 +1570,13 @@ public partial class DistributedConnection : NetworkConnection, IStore return true; } - // AsyncReply connect({ISocket socket, String hostname, int port, String username, DC password, String domain}) - + /// /// Store interface. /// /// Resource. /// - public AsyncReply Put(IResource resource) + public AsyncReply Put(IResource resource, string path) { if (Codec.IsLocalResource(resource, this)) neededResources.Add((resource as DistributedResource).DistributedResourceInstanceId, (DistributedResource)resource); diff --git a/Esiur/Net/IIP/DistributedConnectionProtocol.cs b/Esiur/Net/IIP/DistributedConnectionProtocol.cs index e3cfaf1..f9e6667 100644 --- a/Esiur/Net/IIP/DistributedConnectionProtocol.cs +++ b/Esiur/Net/IIP/DistributedConnectionProtocol.cs @@ -272,7 +272,7 @@ partial class DistributedConnection return; } - var (_, parsed) = Codec.ParseAsync(data, 0, this, null); + var (_, parsed) = Codec.ParseAsync(data, 0, this, null, dataType); if (parsed is AsyncReply reply) { reply.Then(result => @@ -2054,7 +2054,7 @@ partial class DistributedConnection dataType.ContentLength, Instance.Warehouse); var peerTime = (DateTime)args[0]; - var interval = (uint)args[0]; + var interval = (uint)args[1]; uint jitter = 0; diff --git a/Esiur/Resource/IStore.cs b/Esiur/Resource/IStore.cs index 6d6344a..4fd70e0 100644 --- a/Esiur/Resource/IStore.cs +++ b/Esiur/Resource/IStore.cs @@ -37,7 +37,7 @@ namespace Esiur.Resource; public interface IStore : IResource { AsyncReply Get(string path); - AsyncReply Put(IResource resource); + AsyncReply Put(IResource resource, string path); string Link(IResource resource); bool Record(IResource resource, string propertyName, object value, ulong? age, DateTime? dateTime); bool Modify(IResource resource, string propertyName, object value, ulong? age, DateTime? dateTime); diff --git a/Esiur/Resource/Instance.cs b/Esiur/Resource/Instance.cs index 95df488..1cc4386 100644 --- a/Esiur/Resource/Instance.cs +++ b/Esiur/Resource/Instance.cs @@ -764,7 +764,7 @@ public class Instance if (res == res.Instance.store) return name; // root store else - return store.Link(res); + return store.Instance.name + "/" + store.Link(res); } else return null; diff --git a/Esiur/Resource/StoreGeneric.cs b/Esiur/Resource/StoreGeneric.cs index 811277a..8dad38c 100644 --- a/Esiur/Resource/StoreGeneric.cs +++ b/Esiur/Resource/StoreGeneric.cs @@ -31,7 +31,7 @@ public abstract class Store : IStore where T : IResource public abstract bool Modify(IResource resource, string propertyName, object value, ulong? age, DateTime? dateTime); - public abstract AsyncReply Put(IResource resource); + public abstract AsyncReply Put(IResource resource, string path); public abstract bool Record(IResource resource, string propertyName, object value, ulong? age, DateTime? dateTime); diff --git a/Esiur/Resource/Warehouse.cs b/Esiur/Resource/Warehouse.cs index 834d7ab..b3b008a 100644 --- a/Esiur/Resource/Warehouse.cs +++ b/Esiur/Resource/Warehouse.cs @@ -346,78 +346,78 @@ public class Warehouse /// Resource instance. /// IStore that manages the resource. Can be null if the resource is a store. /// Parent resource. if not presented the store becomes the parent for the resource. - public async AsyncReply Put(string instanceName, T resource, IStore store, TypeTemplate customTemplate = null, ulong age = 0, IPermissionsManager manager = null, object attributes = null) where T : IResource - { - if (resource.Instance != null) - throw new Exception("Resource has a store."); + //public async AsyncReply Put(string instanceName, T resource, IStore store, TypeTemplate customTemplate = null, ulong age = 0, IPermissionsManager manager = null, object attributes = null) where T : IResource + //{ + // if (resource.Instance != null) + // throw new Exception("Resource has a store."); - var resourceReference = new WeakReference(resource); + // var resourceReference = new WeakReference(resource); - if (resource is IStore && store == null) - store = (IStore)resource; + // if (resource is IStore && store == null) + // store = (IStore)resource; - if (store == null) - throw new Exception("Resource store is not set."); + // if (store == null) + // throw new Exception("Resource store is not set."); - resource.Instance = new Instance(this, resourceCounter++, instanceName, resource, store, customTemplate, age); + // resource.Instance = new Instance(this, resourceCounter++, instanceName, resource, store, customTemplate, age); - if (attributes != null) - if (attributes is Map attrs) - resource.Instance.SetAttributes(attrs); - else - resource.Instance.SetAttributes(Map.FromObject(attributes)); + // if (attributes != null) + // if (attributes is Map attrs) + // resource.Instance.SetAttributes(attrs); + // else + // resource.Instance.SetAttributes(Map.FromObject(attributes)); - if (manager != null) - resource.Instance.Managers.Add(manager); + // if (manager != null) + // resource.Instance.Managers.Add(manager); - //if (store == parent) - // parent = null; + // //if (store == parent) + // // parent = null; - try - { - if (resource is IStore) - stores.TryAdd(resource as IStore, new List>()); + // try + // { + // if (resource is IStore) + // stores.TryAdd(resource as IStore, new List>()); - if (!await store.Put(resource)) - throw new Exception("Store failed to put the resource"); - //return default(T); + // if (!await store.Put(resource)) + // throw new Exception("Store failed to put the resource"); + // //return default(T); - //if (parent != null) - //{ - // await parent.Instance.Store.AddChild(parent, resource); - // await store.AddParent(resource, parent); - //} + // //if (parent != null) + // //{ + // // await parent.Instance.Store.AddChild(parent, resource); + // // await store.AddParent(resource, parent); + // //} - var t = resource.GetType(); - Global.Counters["T-" + t.Namespace + "." + t.Name]++; + // var t = resource.GetType(); + // Global.Counters["T-" + t.Namespace + "." + t.Name]++; - resources.TryAdd(resource.Instance.Id, resourceReference); + // resources.TryAdd(resource.Instance.Id, resourceReference); - if (warehouseIsOpen) - { - await resource.Trigger(ResourceTrigger.Initialize); - if (resource is IStore) - await resource.Trigger(ResourceTrigger.Open); - } + // if (warehouseIsOpen) + // { + // await resource.Trigger(ResourceTrigger.Initialize); + // if (resource is IStore) + // await resource.Trigger(ResourceTrigger.Open); + // } - if (resource is IStore) - StoreConnected?.Invoke(resource as IStore); - } - catch (Exception ex) - { - Remove(resource); - throw ex; - } + // if (resource is IStore) + // StoreConnected?.Invoke(resource as IStore); + // } + // catch (Exception ex) + // { + // Remove(resource); + // throw ex; + // } - return resource; + // return resource; - } + //} /// /// Put a resource in the warehouse. @@ -429,7 +429,7 @@ public class Warehouse public async AsyncReply Put(string path, T resource, TypeTemplate customTemplate = null, ulong age = 0, IPermissionsManager manager = null, object attributes = null) where T : IResource { if (resource.Instance != null) - throw new Exception("Resource has a store."); + throw new Exception("Resource already initialized."); if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("Invalid path."); @@ -437,6 +437,7 @@ public class Warehouse var location = path.TrimStart('/').Split('/'); IStore store = null; + //IResource parent = null; var instanceName = location.Last(); @@ -447,73 +448,46 @@ public class Warehouse store = (IStore)resource; } + else + { - if (location.Length == 1 && + // get parent + var parent = await Get(string.Join("/", location.Take(location.Length - 1))); + if (parent == null) + throw new Exception("Can't find parent"); - if (location.Length == 1) - return await Put(path, resource, null, customTemplate, age, manager, attributes); - else - { - // get parent - parent = await Get(string.Join("/", location.Take(location.Length - 1))); - - if (parent == null) - throw new Exception("Can't find parent"); - - return await Put(instanceName, resource, parent.Instance.Store, customTemplate, age, manager, attributes); - } - + store = parent.Instance.Store;// GetStore(location[0]); + //if (store == null) + // throw new Exception("Store not found."); + } var resourceReference = new WeakReference(resource); - - if (resource is IStore && store == null) - store = (IStore)resource; - - if (store == null) - throw new Exception("Resource store is not set."); - - resource.Instance = new Instance(this, resourceCounter++, instanceName, resource, store, customTemplate, age); - + if (attributes != null) if (attributes is Map attrs) resource.Instance.SetAttributes(attrs); else resource.Instance.SetAttributes(Map.FromObject(attributes)); - - //if (manager != null) - // resource.Instance.Managers.Add(manager); - - //if (store == parent) - // parent = null; - - try { if (resource is IStore) stores.TryAdd(resource as IStore, new List>()); - - - if (!await store.Put(resource)) - throw new Exception("Store failed to put the resource"); - //return default(T); - - - //if (parent != null) - //{ - // await parent.Instance.Store.AddChild(parent, resource); - // await store.AddParent(resource, parent); - //} + else if ((IResource)resource != store) + { + if (!await store.Put(resource, string.Join("/", location.Skip(1).ToArray()))) + throw new Exception("Store failed to put the resource."); + } var t = resource.GetType(); Global.Counters["T-" + t.Namespace + "." + t.Name]++; resources.TryAdd(resource.Instance.Id, resourceReference); - + if (warehouseIsOpen) { await resource.Trigger(ResourceTrigger.Initialize); @@ -523,6 +497,7 @@ public class Warehouse if (resource is IStore) StoreConnected?.Invoke(resource as IStore); + } catch (Exception ex) { @@ -599,7 +574,7 @@ public class Warehouse public async AsyncReply New(Type type, string path, IPermissionsManager manager = null, object attributes = null, object properties = null) { - var res = CreateInstance(type, properties); + var res = Create(type, properties); return await Put(path, res, null, 0, manager, attributes); } diff --git a/Esiur/Stores/MemoryStore.cs b/Esiur/Stores/MemoryStore.cs index 9c1c772..e192360 100644 --- a/Esiur/Stores/MemoryStore.cs +++ b/Esiur/Stores/MemoryStore.cs @@ -15,7 +15,7 @@ public class MemoryStore : IStore public Instance Instance { get; set; } public event DestroyedEvent OnDestroy; - + KeyList resources = new KeyList(); @@ -27,8 +27,9 @@ public class MemoryStore : IStore public string Link(IResource resource) { if (resource.Instance.Store == this) - return this.Instance.Name + "/$" + resource.Instance.Id; + return (string)resource.Instance.Variables["link"]; + // return this.Instance.Name + "/$" + resource.Instance.Id; return null; } @@ -48,24 +49,25 @@ public class MemoryStore : IStore else { foreach (var r in resources) - if (r.Value.Instance.Name == path) + if (Link(r.Value) == path)//.Value.Instance.Name == path) return new AsyncReply(r.Value); } return new AsyncReply(null); } - public AsyncReply Put(IResource resource) + public AsyncReply Put(IResource resource, string path) { - resources.Add(resource.Instance.Id, resource);// new WeakReference(resource)); + resources.Add(resource.Instance.Id, resource); resource.Instance.Variables["children"] = new AutoList(resource.Instance); resource.Instance.Variables["parents"] = new AutoList(resource.Instance); + resource.Instance.Variables["link"] = path; return new AsyncReply(true); } - + public AsyncReply Trigger(ResourceTrigger trigger) { return new AsyncReply(true); @@ -102,7 +104,7 @@ public class MemoryStore : IStore // else // return new AsyncReply(false); //} - + //public AsyncReply AddParent(IResource resource, IResource parent) //{ @@ -123,12 +125,19 @@ public class MemoryStore : IStore public AsyncBag Children(IResource resource, string name) where T : IResource { - var children = (resource.Instance.Variables["children"] as AutoList); - if (name == null) - return new AsyncBag(children.Where(x => x is T).Select(x => (T)x).ToArray()); - else - return new AsyncBag(children.Where(x => x is T && x.Instance.Name == name).Select(x => (T)x).ToArray()); + var rt = new AsyncBag(); + + var location = Link(resource) + "/"; + + return new AsyncBag(resources.Where(r => r.Value is T && Link(r.Value).StartsWith(location)).Select(r => (T)r.Value).ToArray()); + + //var children = (resource.Instance.Variables["children"] as AutoList); + + //if (name == null) + // return new AsyncBag(children.Where(x => x is T).Select(x => (T)x).ToArray()); + //else + // return new AsyncBag(children.Where(x => x is T && x.Instance.Name == name).Select(x => (T)x).ToArray()); } diff --git a/Esiur/Stores/TemporaryStore.cs b/Esiur/Stores/TemporaryStore.cs index 2c4f5a1..2c433f9 100644 --- a/Esiur/Stores/TemporaryStore.cs +++ b/Esiur/Stores/TemporaryStore.cs @@ -40,7 +40,7 @@ public class TemporaryStore : IStore return new AsyncReply(null); } - public AsyncReply Put(IResource resource) + public AsyncReply Put(IResource resource, string path) { resources.Add(resource.Instance.Id, new WeakReference(resource)); return new AsyncReply(true);