diff --git a/Esiur/Net/HTTP/HTTPConnection.cs b/Esiur/Net/HTTP/HTTPConnection.cs index 3fa345d..796f984 100644 --- a/Esiur/Net/HTTP/HTTPConnection.cs +++ b/Esiur/Net/HTTP/HTTPConnection.cs @@ -445,7 +445,7 @@ public class HTTPConnection : NetworkConnection // do nothing } - protected override void Disconencted() + protected override void Disconnected() { // do nothing } diff --git a/Esiur/Net/IIP/DistributedConnection.cs b/Esiur/Net/IIP/DistributedConnection.cs index 93802e4..5c73723 100644 --- a/Esiur/Net/IIP/DistributedConnection.cs +++ b/Esiur/Net/IIP/DistributedConnection.cs @@ -55,34 +55,6 @@ public partial class DistributedConnection : NetworkConnection, IStore public delegate void ProtocolRequestReplyHandler(DistributedConnection connection, uint callbackId, TransmissionType dataType, byte[] data); - //ProtocolGeneralHandler[] NotificationHandlers = new ProtocolGeneralHandler[] - //{ - // IIPNotificationResourceDestroyed, - // IIPNotificationResourceReassigned, - // IIPNotificationResourceMoved, - // IIPNotificationSystemFailure, - // IIPNotificationPropertyModified - //}; - - //ProtocolRequestReplyHandler[] RequestHandlers = new ProtocolRequestReplyHandler[] - //{ - // IIPRequestAttachResource, - // IIPRequest - - //}; - - //ProtocolRequestReplyHandler[] ReplyHandlers = new ProtocolRequestReplyHandler[] - //{ - - //}; - - //ProtocolGeneralHandler[] ExtensionHandler = new ProtocolGeneralHandler[] - //{ - - //}; - - - // Delegates public delegate void ReadyEvent(DistributedConnection sender); public delegate void ErrorEvent(DistributedConnection sender, byte errorCode, string errorMessage); @@ -163,7 +135,7 @@ public partial class DistributedConnection : NetworkConnection, IStore [Attribute] public Func> Authenticator { get; set; } - //public Func, AsyncReply> Authenticator { get; set; } + [Attribute] public bool AutoReconnect { get; set; } = false; @@ -294,7 +266,7 @@ public partial class DistributedConnection : NetworkConnection, IStore // change to Map for compatibility var headers = Codec.Compose(session.LocalHeaders.Select(x => new KeyValuePair((byte)x.Key, x.Value)), this); - // @REVIEW: MITM Attack can still occure + // @REVIEW: MITM Attack can still occur SendParams() .AddUInt8((byte)IIPAuthPacketInitialize.NoAuthNoAuth) .AddUInt8Array(headers) @@ -792,7 +764,8 @@ public partial class DistributedConnection : NetworkConnection, IStore if (this.Instance == null) { - Warehouse.Put(session.AuthorizedAccount.Replace("/", "_"), this, null, Server).Then(x => + Instance.Warehouse.Put(Server + "/" + session.AuthorizedAccount.Replace("/", "_"), this) + .Then(x => { openReply?.Trigger(true); OnReady?.Invoke(this); @@ -1259,7 +1232,9 @@ public partial class DistributedConnection : NetworkConnection, IStore if (this.Instance == null) { - Warehouse.Put(this.GetHashCode().ToString().Replace("/", "_"), this, null, Server).Then(x => + Instance.Warehouse.Put( + Server.Instance.Link + "/" + this.GetHashCode().ToString().Replace("/", "_"), this) + .Then(x => { ready = true; Status = ConnectionStatus.Connected; @@ -1622,46 +1597,11 @@ public partial class DistributedConnection : NetworkConnection, IStore return true; } - AsyncReply IStore.AddChild(IResource parent, IResource child) - { - // not implemented - throw new NotImplementedException(); - } - - AsyncReply IStore.RemoveChild(IResource parent, IResource child) - { - // not implemeneted - throw new NotImplementedException(); - } - - public AsyncReply AddParent(IResource child, IResource parent) - { - throw new NotImplementedException(); - } - - public AsyncReply RemoveParent(IResource child, IResource parent) - { - throw new NotImplementedException(); - } - - public AsyncBag Children(IResource resource, string name) where T : IResource { throw new Exception("Not implemented"); - - //if (Codec.IsLocalResource(resource, this)) - // return new AsyncBag((resource as DistributedResource).children.Where(x => x.GetType() == typeof(T)).Select(x => (T)x)); - - //return null; } - public AsyncBag Parents(IResource resource, string name) where T : IResource - { - throw new Exception("Not implemented"); - //if (Codec.IsLocalResource(resource, this)) - // return (resource as DistributedResource).parents.Where(x => x.GetType() == typeof(T)).Select(x => (T)x); - - } protected override void Connected() @@ -1670,7 +1610,7 @@ public partial class DistributedConnection : NetworkConnection, IStore Declare(); } - protected override void Disconencted() + protected override void Disconnected() { // clean up ready = false; @@ -1737,7 +1677,7 @@ public partial class DistributedConnection : NetworkConnection, IStore suspendedResources.Clear(); UnsubscribeAll(); - Warehouse.Remove(this); + Instance.Warehouse.Remove(this); if (ready) Server.Membership?.Logout(session); @@ -1758,4 +1698,33 @@ public partial class DistributedConnection : NetworkConnection, IStore } + public AsyncBag Parent(IResource resource, string name) where T : IResource + { + throw new NotImplementedException(); + } + + public AsyncReply> GetRecord(IResource resource, DateTime fromDate, DateTime toDate) + { + throw new NotImplementedException(); + } + + AsyncReply IStore.Remove(IResource resource) + { + throw new NotImplementedException(); + } + + public AsyncReply Remove(string path) + { + throw new NotImplementedException(); + } + + public AsyncReply Move(IResource resource, string newPath) + { + throw new NotImplementedException(); + } + + AsyncReply IStore.Parent(IResource resource, string name) + { + throw new NotImplementedException(); + } } diff --git a/Esiur/Net/IIP/DistributedConnectionProtocol.cs b/Esiur/Net/IIP/DistributedConnectionProtocol.cs index 0cc2712..b5d4f67 100644 --- a/Esiur/Net/IIP/DistributedConnectionProtocol.cs +++ b/Esiur/Net/IIP/DistributedConnectionProtocol.cs @@ -512,20 +512,6 @@ partial class DistributedConnection }); } - - void IIPEventAttributesUpdated(uint resourceId, byte[] attributes) - { - Fetch(resourceId, null).Then(resource => - { - var attrs = attributes.GetStringArray(0, (uint)attributes.Length); - - GetAttributes(resource, attrs).Then(s => - { - resource.Instance.SetAttributes(s); - }); - }); - } - void IIPRequestAttachResource(uint callback, TransmissionType dataType, byte[] data) { @@ -533,7 +519,7 @@ partial class DistributedConnection var resourceId = (uint)value; - Warehouse.GetById(resourceId).Then((res) => + Instance.Warehouse.GetById(resourceId).Then((res) => { if (res != null) { @@ -592,7 +578,7 @@ partial class DistributedConnection var resourceId = (uint)args[0]; var age = (ulong)args[1]; - Warehouse.GetById(resourceId).Then((res) => + Instance.Warehouse.GetById(resourceId).Then((res) => { if (res != null) { @@ -647,7 +633,7 @@ partial class DistributedConnection var resourceId = (uint)value; - Warehouse.GetById(resourceId).Then((res) => + Instance.Warehouse.GetById(resourceId).Then((res) => { if (res != null) { @@ -673,15 +659,18 @@ partial class DistributedConnection void IIPRequestCreateResource(uint callback, TransmissionType dataType, byte[] data) { + var (_, parsed) = Codec.ParseAsync(data, 0, this, null, dataType); - var (offset, length, args) = DataDeserializer.LimitedCountListParser(data, dataType.Offset, - dataType.ContentLength, 4); - var storeId = (uint)args[0]; - var parentId = (uint)args[1]; - var className = (string)args[2]; - var instanceName = (string)args[3]; + var args = (object[])parsed; - var type = Type.GetType(className); + var path = (string)args[0]; + + TypeTemplate type = null; + + if (args[1] is UUID) + type = Instance.Warehouse.GetTemplateByClassId((UUID)args[1]); + else if (args[1] is string) + type = Instance.Warehouse.GetTemplateByClassName((string)args[1]); if (type == null) { @@ -689,72 +678,43 @@ partial class DistributedConnection return; } - Warehouse.GetById(storeId).Then(store => - { - if (store == null) - { - SendError(ErrorType.Management, callback, (ushort)ExceptionCode.StoreNotFound); - return; - } + var props = (Map)((object[])args)[2]; + var attrs = (Map)((object[])args)[3]; - if (!(store is IStore)) - { - SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceIsNotStore); - return; - } + // Get store + var sc = path.Split('/'); - // check security - if (store.Instance.Applicable(session, ActionType.CreateResource, null) != Ruling.Allowed) - { - SendError(ErrorType.Management, callback, (ushort)ExceptionCode.CreateDenied); - return; - } + Instance.Warehouse.Get(string.Join("/", sc.Take(sc.Length - 1))) + .Then(r => + { + if (r == null) + { + SendError(ErrorType.Management, callback, (ushort)ExceptionCode.StoreNotFound); + return; + } + var store = r.Instance.Store; - Warehouse.GetById(parentId).Then(parent => - { - // check security - if (parent != null) - if (parent.Instance.Applicable(session, ActionType.AddChild, null) != Ruling.Allowed) - { - SendError(ErrorType.Management, callback, (ushort)ExceptionCode.AddChildDenied); - return; - } + // check security + if (store.Instance.Applicable(session, ActionType.CreateResource, null) != Ruling.Allowed) + { + SendError(ErrorType.Management, callback, (ushort)ExceptionCode.CreateDenied); + return; + } + Instance.Warehouse.New(type.DefinedType, path, null, attrs, props).Then(resource => + { + SendReply(IIPPacketReply.Completed, callback, resource.Instance.Id); - var (_, parsed) = Codec.ParseAsync(data, 0, this, null, dataType); + }).Error(e => + { + SendError(e.Type, callback, (ushort)e.Code, e.Message); + }); - if (parsed is AsyncReply reply) - { - reply.Then((result) => - { - var props = (Map)((object[])result)[4]; - var attrs = (Map)((object[])result)[5]; - Warehouse.New(type, instanceName, store as IStore, parent, null, attrs, props) - .Then(resource => - { - SendReply(IIPPacketReply.Completed, callback, resource.Instance.Id); - }) - .Error(ex => - { - SendError(ErrorType.Exception, callback, (ushort)ExceptionCode.AddToStoreFailed); - }); - }); - } - else - { - var map = (Map)parsed; - Warehouse.New(type, instanceName, store as IStore, parent, null, null, map) - .Then(resource => - { - SendReply(IIPPacketReply.Completed, callback, resource.Instance.Id); - }).Error(x => - { - SendError(ErrorType.Exception, callback, (ushort)ExceptionCode.AddToStoreFailed); - }); - } - }); - }); + }).Error(e => + { + SendError(e.Type, callback, (ushort)e.Code, e.Message); + }); } @@ -765,7 +725,7 @@ partial class DistributedConnection var resourceId = (uint)value; - Warehouse.GetById(resourceId).Then(r => + Instance.Warehouse.GetById(resourceId).Then(r => { if (r == null) { @@ -779,9 +739,9 @@ partial class DistributedConnection return; } - if (Warehouse.Remove(r)) + if (Instance.Warehouse.Remove(r)) SendReply(IIPPacketReply.Completed, callback); - + else SendError(ErrorType.Management, callback, (ushort)ExceptionCode.DeleteFailed); }); @@ -802,7 +762,7 @@ partial class DistributedConnection return; } - Warehouse.GetById(resourceId).Then(resource => + Instance.Warehouse.GetById(resourceId).Then(resource => { if (resource == null) { @@ -837,39 +797,31 @@ partial class DistributedConnection var resourceLink = (string)value; - Action queryCallback = (r) => + Action queryCallback = (r) => { if (r == null) - SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound); - else { - var list = r.Where(x => x.Instance.Applicable(session, ActionType.ViewTemplate, null) != Ruling.Denied).ToArray(); - - if (list.Length == 0) - SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound); - else - { - // get all templates related to this resource - var templates = new List(); - foreach (var resource in list) - templates.AddRange(TypeTemplate.GetDependencies(resource.Instance.Template).Where(x => !templates.Contains(x))); - - var binList = new List(); - - foreach (var t in templates) - binList.Add(t.Content); - - // Send - SendReply(IIPPacketReply.Completed, callback, binList.ToArray()); - - } + SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound); + return; } + + if (r.Instance.Applicable(session, ActionType.ViewTemplate, null) == Ruling.Denied) + { + SendError(ErrorType.Management, callback, (ushort)ExceptionCode.NotAllowed); + return; + } + + var templates = TypeTemplate.GetDependencies(r.Instance.Template, Instance.Warehouse); + + // Send + SendReply(IIPPacketReply.Completed, callback, templates.Select(x=>x.Content).ToArray()); + }; if (Server?.EntryPoint != null) Server.EntryPoint.Query(resourceLink, this).Then(queryCallback); else - Warehouse.Query(resourceLink).Then(queryCallback); + Instance.Warehouse.Query(resourceLink).Then(queryCallback); } void IIPRequestTemplateFromClassName(uint callback, TransmissionType dataType, byte[] data) @@ -878,7 +830,7 @@ partial class DistributedConnection var className = (string)value; - var t = Warehouse.GetTemplateByClassName(className); + var t = Instance.Warehouse.GetTemplateByClassName(className); if (t != null) { @@ -898,7 +850,7 @@ partial class DistributedConnection var classId = new UUID((byte[])value); - var t = Warehouse.GetTemplateByClassId(classId); + var t = Instance.Warehouse.GetTemplateByClassId(classId); if (t != null) { @@ -920,7 +872,7 @@ partial class DistributedConnection var resourceId = (uint)value; - Warehouse.GetById(resourceId).Then((r) => + Instance.Warehouse.GetById(resourceId).Then((r) => { if (r != null) { @@ -941,25 +893,26 @@ partial class DistributedConnection var (_, parsed) = Codec.ParseSync(data, 0, dataType); var resourceLink = (string)parsed; - Action queryCallback = (r) => + Action queryCallback = (r) => { if (r == null) SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound); else { - var list = r.Where(x => x.Instance.Applicable(session, ActionType.Attach, null) != Ruling.Denied).ToArray(); - - if (list.Length == 0) + if (r.Instance.Applicable(session, ActionType.Attach, null) == Ruling.Denied) + { SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound); - else - SendReply(IIPPacketReply.Completed, callback, list.FirstOrDefault()); + return; + } + + SendReply(IIPPacketReply.Completed, callback, r); } }; if (Server?.EntryPoint != null) Server.EntryPoint.Query(resourceLink, this).Then(queryCallback); else - Warehouse.Query(resourceLink).Then(queryCallback); + Instance.Warehouse.Query(resourceLink).Then(queryCallback); } @@ -969,25 +922,37 @@ partial class DistributedConnection var resourceLink = (string)parsed; - Action queryCallback = (r) => + Action queryCallback = (r) => { if (r == null) SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound); else { - var list = r.Where(x => x.Instance.Applicable(session, ActionType.Attach, null) != Ruling.Denied).ToArray(); + if (r.Instance.Applicable(session, ActionType.Attach, null) == Ruling.Denied) + { + SendError(ErrorType.Management, callback, (ushort)ExceptionCode.NotAllowed); + return; + } - if (list.Length == 0) - SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound); - else + r.Instance.Children().Then(children => + { + var list = children.Where(x => x.Instance.Applicable(session, ActionType.Attach, null) != Ruling.Denied).ToArray(); SendReply(IIPPacketReply.Completed, callback, list); + }).Error(e => + { + SendError(e.Type, callback, (ushort)e.Code, e.Message); + }); } }; if (Server?.EntryPoint != null) - Server.EntryPoint.Query(resourceLink, this).Then(queryCallback); + Server.EntryPoint.Query(resourceLink, this) + .Then(queryCallback) + .Error(e => SendError(e.Type, callback, (ushort)e.Code, e.Message)); else - Warehouse.Query(resourceLink).Then(queryCallback); + Instance.Warehouse.Query(resourceLink) + .Then(queryCallback) + .Error(e => SendError(e.Type, callback, (ushort)e.Code, e.Message)); } void IIPRequestResourceAttribute(uint callback, uint resourceId) @@ -1078,7 +1043,7 @@ partial class DistributedConnection var index = (byte)args[1]; - var template = Warehouse.GetTemplateByClassId(classId); + var template = Instance.Warehouse.GetTemplateByClassId(classId); if (template == null) @@ -1154,7 +1119,7 @@ partial class DistributedConnection var resourceId = (uint)args[0]; var index = (byte)args[1]; - Warehouse.GetById(resourceId).Then((r) => + Instance.Warehouse.GetById(resourceId).Then((r) => { if (r == null) { @@ -1411,7 +1376,7 @@ partial class DistributedConnection var resourceId = (uint)args[0]; var index = (byte)args[1]; - Warehouse.GetById(resourceId).Then((r) => + Instance.Warehouse.GetById(resourceId).Then((r) => { if (r == null) { @@ -1470,7 +1435,7 @@ partial class DistributedConnection var resourceId = (uint)args[0]; var index = (byte)args[1]; - Warehouse.GetById(resourceId).Then((r) => + Instance.Warehouse.GetById(resourceId).Then((r) => { if (r == null) { @@ -1534,7 +1499,7 @@ partial class DistributedConnection // un hold the socket to send data immediately this.Socket.Unhold(); - Warehouse.GetById(rid).Then((r) => + Instance.Warehouse.GetById(rid).Then((r) => { if (r == null) { @@ -1671,7 +1636,7 @@ partial class DistributedConnection var args = (object[])result; templateRequests.Remove(classId); templates.Add(((TypeTemplate)args[0]).ClassId, (TypeTemplate)args[0]); - Warehouse.PutTemplate(args[0] as TypeTemplate); + Instance.Warehouse.PutTemplate(args[0] as TypeTemplate); reply.Trigger(args[0]); }).Error((ex) => { @@ -1702,7 +1667,7 @@ partial class DistributedConnection templateByNameRequests.Remove(className); templates.Add(tt.ClassId, tt); - Warehouse.PutTemplate(tt); + Instance.Warehouse.PutTemplate(tt); reply.Trigger(tt); }).Error((ex) => { @@ -1748,10 +1713,10 @@ partial class DistributedConnection SendRequest(IIPPacketRequest.LinkTemplates, link) .Then((result) => { - + var templates = new List(); - foreach(var template in (byte[][])result) + foreach (var template in (byte[][])result) { templates.Add(TypeTemplate.Parse(template)); } @@ -1838,7 +1803,7 @@ partial class DistributedConnection if (resource == null) { - template = Warehouse.GetTemplateByClassId(classId, TemplateType.Resource); + template = Instance.Warehouse.GetTemplateByClassId(classId, TemplateType.Resource); if (template?.DefinedType != null && template.IsWrapper) dr = Activator.CreateInstance(template.DefinedType, this, id, (ulong)args[1], (string)args[2]) as DistributedResource; else @@ -1895,12 +1860,14 @@ partial class DistributedConnection if (template == null) { - GetTemplate((UUID)rt[0]).Then((tmp) => + GetTemplate(classId).Then((tmp) => { // ClassId, ResourceAge, ResourceLink, Content if (resource == null) { - Warehouse.Put(id.ToString(), dr, this, null, tmp).Then(initResource).Error(ex => reply.TriggerError(ex)); + Instance.Warehouse.Put(this.Instance.Link + "/" + id.ToString(), dr, tmp) + .Then(initResource) + .Error(ex => reply.TriggerError(ex)); } else { @@ -1916,7 +1883,7 @@ partial class DistributedConnection { if (resource == null) { - Warehouse.Put(id.ToString(), dr, this, null, template) + Instance.Warehouse.Put(this.Instance.Link + "/" + id.ToString(), dr, template) .Then(initResource).Error((ex) => reply.TriggerError(ex)); } else @@ -1936,60 +1903,6 @@ partial class DistributedConnection } - public AsyncReply GetChildren(IResource resource) - { - var rt = new AsyncReply(); - - SendRequest(IIPPacketRequest.ResourceChildren) - .AddUInt32(resource.Instance.Id) - .Done() - .Then(ar => - { - var dataType = (TransmissionType)ar[0]; - var data = (byte[])ar[1]; - - var (_, parsed) = Codec.ParseAsync(data, dataType.Offset, this, null, dataType); - - parsed.Then(resources => rt.Trigger(resources)) - .Error(ex => rt.TriggerError(ex)); - - //Codec.ParseResourceArray(d, 0, (uint)d.Length, this).Then(resources => - //{ - // rt.Trigger(resources); - //}).Error(ex => rt.TriggerError(ex)); - }); - - return rt; - } - - public AsyncReply GetParents(IResource resource) - { - var rt = new AsyncReply(); - - SendRequest(IIPPacketRequest.ResourceParents) - .AddUInt32(resource.Instance.Id) - .Done() - .Then(ar => - { - var dataType = (TransmissionType)ar[0]; - var data = (byte[])ar[1]; - var (_, parsed) = Codec.Parse(data, dataType.Offset, this, null, dataType); - - parsed.Then(resources => rt.Trigger(resources)) - .Error(ex => rt.TriggerError(ex)); - - //Codec.ParseResourceArray(d, 0, (uint)d.Length, this).Then(resources => - //{ - // rt.Trigger(resources); - //}).Error(ex => rt.TriggerError(ex)); - }); - - return rt; - } - - - - /// /// Query resources at specific link. /// @@ -2013,39 +1926,19 @@ partial class DistributedConnection /// /// Create a new resource. /// - /// The store in which the resource is saved. - /// Class full name. - /// Constructor parameters. - /// Resource attributeds. - /// Values for the resource properties. + /// Resource path. + /// Type template. + /// Values for the resource properties. + /// Resource attributes. /// New resource instance - public AsyncReply Create(IStore store, IResource parent, string className, Map values, Map attributes) + public AsyncReply Create(string path, TypeTemplate type, Map properties, Map attributes) { var reply = new AsyncReply(); - var pkt = new BinaryList() - .AddUInt32(store.Instance.Id) - .AddUInt32(parent.Instance.Id) - .AddUInt8((byte)className.Length) - .AddString(className) - .AddUInt8Array(Codec.Compose(parameters, this)) - .AddUInt8Array(Codec.Compose(attributes, this)) - .AddUInt8Array(Codec.Compose(values, this)); - pkt.InsertInt32(8, pkt.Length); - - SendRequest(IIPPacketRequest.CreateResource, store, parent, cl) - .AddUInt8Array(pkt.ToArray()) - .Done() - .Then(args => - { - var rid = (uint)args[0]; - - Fetch(rid, null).Then((r) => - { - reply.Trigger(r); - }); - - }); + SendRequest(IIPPacketRequest.CreateResource, path, type.ClassId, type.CastProperties(properties), attributes) + .Then(r => reply.Trigger((DistributedResource)r)) + .Error(e => reply.TriggerError(e)) + .Warning((l, m) => reply.TriggerWarning(l, m)); return reply; } @@ -2098,33 +1991,22 @@ partial class DistributedConnection { Unsubscribe(resource); + // compose the packet - SendEvent(IIPPacketEvent.ResourceDestroyed) - .AddUInt32(resource.Instance.Id) - .Done(); - - + SendNotification(IIPPacketNotification.ResourceDestroyed, resource.Instance.Id); } private void Instance_PropertyModified(PropertyModificationInfo info) { - //var pt = resource.Instance.Template.GetPropertyTemplateByName(name); - // if (pt == null) - // return; - - SendEvent(IIPPacketEvent.PropertyUpdated) - .AddUInt32(info.Resource.Instance.Id) - .AddUInt8(info.PropertyTemplate.Index) - .AddUInt8Array(Codec.Compose(info.Value, this)) - .Done(); - + SendNotification(IIPPacketNotification.PropertyModified, + info.Resource.Instance.Id, + info.PropertyTemplate.Index, + info.Value); } - // private void Instance_EventOccurred(IResource resource, string name, string[] users, DistributedConnection[] connections, object[] args) - private void Instance_CustomEventOccurred(CustomEventOccurredInfo info) { - if (info.EventTemplate.Listenable) + if (info.EventTemplate.Subscribable) { lock (subscriptionsLock) { @@ -2145,11 +2027,10 @@ partial class DistributedConnection // compose the packet - SendEvent(IIPPacketEvent.EventOccurred) - .AddUInt32(info.Resource.Instance.Id) - .AddUInt8((byte)info.EventTemplate.Index) - .AddUInt8Array(Codec.Compose(info.Value, this)) - .Done(); + SendNotification(IIPPacketNotification.EventOccurred, + info.Resource.Instance.Id, + info.EventTemplate.Index, + info.Value); } private void Instance_EventOccurred(EventOccurredInfo info) @@ -2171,11 +2052,10 @@ partial class DistributedConnection return; // compose the packet - SendEvent(IIPPacketNotification.EventOccurred) - .AddUInt32(info.Resource.Instance.Id) - .AddUInt8((byte)info.EventTemplate.Index) - .AddUInt8Array(Codec.Compose(info.Value, this)) - .Done(); + SendNotification(IIPPacketNotification.EventOccurred, + info.Resource.Instance.Id, + info.EventTemplate.Index, + info.Value); } @@ -2196,17 +2076,10 @@ partial class DistributedConnection if (lastKeepAliveReceived != null) { var diff = (uint)(now - (DateTime)lastKeepAliveReceived).TotalMilliseconds; - //Console.WriteLine("Diff " + diff + " " + interval); - jitter = (uint)Math.Abs((int)diff - (int)interval); } - SendParams() - .AddUInt8((byte)(0x80 | (byte)IIPPacketRequest.KeepAlive)) - .AddUInt32(callbackId) - .AddDateTime(now) - .AddUInt32(jitter) - .Done(); + SendRequest(IIPPacketRequest.KeepAlive, now, jitter); lastKeepAliveReceived = now; } diff --git a/Esiur/Net/IIP/DistributedResource.cs b/Esiur/Net/IIP/DistributedResource.cs index 6f0deb7..77a7048 100644 --- a/Esiur/Net/IIP/DistributedResource.cs +++ b/Esiur/Net/IIP/DistributedResource.cs @@ -238,7 +238,7 @@ public class DistributedResource : DynamicObject, IResource, INotifyPropertyChan Instance.EmitResourceEvent(et, args); } - public AsyncReply _Invoke(byte index, Map args) + public AsyncReply _Invoke(byte index, Map args) { if (destroyed) throw new Exception("Trying to access a destroyed object."); @@ -268,7 +268,7 @@ public class DistributedResource : DynamicObject, IResource, INotifyPropertyChan if (!et.Subscribable) return new AsyncReply().TriggerError(new AsyncException(ErrorType.Management, (ushort)ExceptionCode.NotSubscribable, "")); - return connection.SendListenRequest(instanceId, et.Index); + return connection.SendSubscribeRequest(instanceId, et.Index); } public AsyncReply Subscribe(string eventName) @@ -285,9 +285,9 @@ public class DistributedResource : DynamicObject, IResource, INotifyPropertyChan return new AsyncReply().TriggerError(new AsyncException(ErrorType.Management, (ushort)ExceptionCode.MethodNotFound, "")); if (!et.Subscribable) - return new AsyncReply().TriggerError(new AsyncException(ErrorType.Management, (ushort)ExceptionCode.NotListenable, "")); + return new AsyncReply().TriggerError(new AsyncException(ErrorType.Management, (ushort)ExceptionCode.NotSubscribable, "")); - return connection.SendUnlistenRequest(instanceId, et.Index); + return connection.SendUnsubscribeRequest(instanceId, et.Index); } public AsyncReply Unsubscribe(string eventName) diff --git a/Esiur/Net/IIP/EntryPoint.cs b/Esiur/Net/IIP/EntryPoint.cs index 5561a10..148534e 100644 --- a/Esiur/Net/IIP/EntryPoint.cs +++ b/Esiur/Net/IIP/EntryPoint.cs @@ -34,6 +34,6 @@ namespace Esiur.Net.IIP; public abstract class EntryPoint : Esiur.Resource.Resource { - public abstract AsyncReply Query(string path, DistributedConnection sender); + public abstract AsyncReply Query(string path, DistributedConnection sender); protected abstract override bool Create(); } diff --git a/Esiur/Net/NetworkConnection.cs b/Esiur/Net/NetworkConnection.cs index c876b56..d1f6cdd 100644 --- a/Esiur/Net/NetworkConnection.cs +++ b/Esiur/Net/NetworkConnection.cs @@ -283,7 +283,7 @@ public abstract class NetworkConnection : IDestructible, INetworkReceiver Remove(IResource resource); + + AsyncReply Remove(string path); + + AsyncReply Move(IResource resource, string newPath); //bool RemoveAttributes(IResource resource, string[] attributes = null); @@ -51,15 +55,15 @@ public interface IStore : IResource - AsyncReply AddChild(IResource parent, IResource child); - AsyncReply RemoveChild(IResource parent, IResource child); + //AsyncReply AddChild(IResource parent, IResource child); + //AsyncReply RemoveChild(IResource parent, IResource child); - AsyncReply AddParent(IResource child, IResource parent); - AsyncReply RemoveParent(IResource child, IResource parent); + //AsyncReply AddParent(IResource child, IResource parent); + //AsyncReply RemoveParent(IResource child, IResource parent); AsyncBag Children(IResource resource, string name) where T : IResource; - AsyncBag Parents(IResource resource, string name) where T : IResource; + AsyncReply Parent(IResource resource, string name) where T : IResource; diff --git a/Esiur/Resource/Instance.cs b/Esiur/Resource/Instance.cs index dd00dd1..bb59dd6 100644 --- a/Esiur/Resource/Instance.cs +++ b/Esiur/Resource/Instance.cs @@ -393,7 +393,7 @@ public class Instance /// /// Number of nodes to reach the original resource. /// - public ulong Hops + public byte Hops { get { return hops; } internal set { hops = value; } @@ -776,24 +776,21 @@ public class Instance IResource res; if (this.resource.TryGetTarget(out res)) { - //if (!(store is null)) return store.Children(res, name); - //else - // return (res as IStore).Children(res, name); } else return new AsyncBag(null); } - public AsyncBag Parents(string name = null) where T : IResource + public AsyncReply Parent(string name = null) where T : IResource { IResource res; if (this.resource.TryGetTarget(out res)) { - return store.Parents(res, name); + return store.Parent(res, name); } else - return new AsyncBag(null); + return new AsyncReply(default(T)); } /* @@ -908,6 +905,7 @@ public class Instance /// public AutoList Managers => managers; + public readonly Warehouse Warehouse; /// /// Create new instance. /// @@ -915,8 +913,9 @@ public class Instance /// Name of the instance. /// Resource to manage. /// Store responsible for the resource. - public Instance(uint id, string name, IResource resource, IStore store, TypeTemplate customTemplate = null, ulong age = 0) + public Instance(Warehouse warehouse, uint id, string name, IResource resource, IStore store, TypeTemplate customTemplate = null, ulong age = 0) { + this.Warehouse = warehouse; this.store = store; this.resource = new WeakReference(resource); this.id = id; diff --git a/Esiur/Resource/Template/TypeTemplate.cs b/Esiur/Resource/Template/TypeTemplate.cs index c1fd00f..cc2213e 100644 --- a/Esiur/Resource/Template/TypeTemplate.cs +++ b/Esiur/Resource/Template/TypeTemplate.cs @@ -216,7 +216,7 @@ public class TypeTemplate } - public static TypeTemplate[] GetDependencies(TypeTemplate template) + public static TypeTemplate[] GetDependencies(TypeTemplate template, Warehouse warehouse) { var list = new List(); @@ -238,7 +238,7 @@ public class TypeTemplate // Get parents while (parentType != null) { - var parentTemplate = Warehouse.GetTemplateByType(parentType); + var parentTemplate = warehouse.GetTemplateByType(parentType); if (parentTemplate != null) { list.Add(parentTemplate); @@ -255,7 +255,7 @@ public class TypeTemplate foreach (var functionReturnType in functionReturnTypes) { - var functionReturnTemplate = Warehouse.GetTemplateByType(functionReturnType); + var functionReturnTemplate = warehouse.GetTemplateByType(functionReturnType); if (functionReturnTemplate != null) { if (!bag.Contains(functionReturnTemplate)) @@ -274,7 +274,7 @@ public class TypeTemplate foreach (var fpType in fpTypes) { - var fpt = Warehouse.GetTemplateByType(fpType); + var fpt = warehouse.GetTemplateByType(fpType); if (fpt != null) { if (!bag.Contains(fpt)) @@ -297,7 +297,7 @@ public class TypeTemplate foreach (var fpType in fpTypes) { - var fpt = Warehouse.GetTemplateByType(fpType); + var fpt = warehouse.GetTemplateByType(fpType); if (fpt != null) { if (!bag.Contains(fpt)) @@ -319,7 +319,7 @@ public class TypeTemplate foreach (var propertyType in propertyTypes) { - var propertyTemplate = Warehouse.GetTemplateByType(propertyType); + var propertyTemplate = warehouse.GetTemplateByType(propertyType); if (propertyTemplate != null) { if (!bag.Contains(propertyTemplate)) @@ -338,7 +338,7 @@ public class TypeTemplate foreach (var eventType in eventTypes) { - var eventTemplate = Warehouse.GetTemplateByType(eventType); + var eventTemplate = warehouse.GetTemplateByType(eventType); if (eventTemplate != null) { @@ -398,7 +398,7 @@ public class TypeTemplate public bool IsWrapper { get; private set; } - public TypeTemplate(Type type, bool addToWarehouse = false) + public TypeTemplate(Type type, Warehouse warehouse = null) { //if (!type.IsPublic) @@ -430,8 +430,8 @@ public class TypeTemplate // set guid classId = GetTypeUUID(type); - if (addToWarehouse) - Warehouse.PutTemplate(this); + if (warehouse != null) + warehouse.PutTemplate(this); @@ -887,7 +887,7 @@ public class TypeTemplate offset += dts; - (dts, var value) = Codec.Parse(data, offset, null, null); + (dts, var value) = Codec.ParseSync(data, offset); offset += dts; @@ -899,7 +899,7 @@ public class TypeTemplate offset += cs; } - var ct = new ConstantTemplate(od, eventIndex++, name, inherited, valueType, value.Result, annotation); + var ct = new ConstantTemplate(od, eventIndex++, name, inherited, valueType, value, annotation); od.constants.Add(ct); } @@ -920,5 +920,18 @@ public class TypeTemplate return od; } + + public Map CastProperties(Map properties) + { + var rt = new Map(); + foreach(var kv in properties) + { + var pt = GetPropertyTemplateByName(kv.Key); + if (pt == null) continue; + rt.Add(pt.Index, kv.Value); + } + + return rt; + } } diff --git a/Esiur/Resource/Warehouse.cs b/Esiur/Resource/Warehouse.cs index 56d9e9c..9a62672 100644 --- a/Esiur/Resource/Warehouse.cs +++ b/Esiur/Resource/Warehouse.cs @@ -41,20 +41,23 @@ using System.Data; namespace Esiur.Resource; -// Centeral Resource Issuer -public static class Warehouse +// Central Resources Manager +public class Warehouse { + + public static Warehouse Default = new Warehouse(); + //static byte prefixCounter; //static AutoList stores = new AutoList(null); - static ConcurrentDictionary> resources = new ConcurrentDictionary>(); - static ConcurrentDictionary>> stores = new ConcurrentDictionary>>(); + ConcurrentDictionary> resources = new ConcurrentDictionary>(); + ConcurrentDictionary>> stores = new ConcurrentDictionary>>(); - static uint resourceCounter = 0; + uint resourceCounter = 0; - static KeyList> templates + KeyList> templates = new KeyList>() { //[TemplateType.Unspecified] = new KeyList(), @@ -64,36 +67,33 @@ public static class Warehouse [TemplateType.Enum] = new KeyList(), }; - static bool warehouseIsOpen = false; + bool warehouseIsOpen = false; - public delegate void StoreEvent(IStore store);//, string name); - // public delegate void StoreDisconnectedEvent(IStore store); - - public static event StoreEvent StoreConnected; - //public static event StoreEvent StoreOpen; - public static event StoreEvent StoreDisconnected; + public delegate void StoreEvent(IStore store); + public event StoreEvent StoreConnected; + public event StoreEvent StoreDisconnected; public delegate AsyncReply ProtocolInstance(string name, object properties); - public static KeyList Protocols { get; } = GetSupportedProtocols(); + public KeyList Protocols { get; } = new KeyList(); - private static Regex urlRegex = new Regex(@"^(?:([\S]*)://([^/]*)/?)"); + private Regex urlRegex = new Regex(@"^(?:([\S]*)://([^/]*)/?)"); - //private static object resourcesLock = new object(); - static KeyList GetSupportedProtocols() + public Warehouse() { - var rt = new KeyList(); - rt.Add("iip", async (name, attributes) => await Warehouse.New(name, null, null, null, attributes)); - return rt; + Protocols.Add("iip", + async (name, attributes) + => await New(name, null, attributes)); } + /// /// Get a store by its name. /// /// Store instance name /// - public static IStore GetStore(string name) + public IStore GetStore(string name) { foreach (var s in stores) if (s.Key.Instance.Name == name) @@ -101,14 +101,14 @@ public static class Warehouse return null; } - public static WeakReference[] Resources => resources.Values.ToArray(); + public WeakReference[] Resources => resources.Values.ToArray(); /// /// Get a resource by instance Id. /// /// Instance Id /// - public static AsyncReply GetById(uint id) + public AsyncReply GetById(uint id) { if (resources.ContainsKey(id)) { @@ -122,7 +122,7 @@ public static class Warehouse return new AsyncReply(null); } - static void LoadGenerated() + void LoadGenerated() { foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { @@ -155,7 +155,7 @@ public static class Warehouse /// This function issues the initialize trigger to all stores and resources. /// /// True, if no problem occurred. - public static async AsyncReply Open() + public async AsyncReply Open() { if (warehouseIsOpen) return false; @@ -193,68 +193,16 @@ public static class Warehouse foreach (var r in resSnap) { - //IResource r; - //if (rk.Value.TryGetTarget(out r)) - //{ var rt = await r.Trigger(ResourceTrigger.SystemInitialized); if (!rt) { Global.Log("Warehouse", LogType.Warning, $"Resource failed at SystemInitialized {r.Instance.Name} [{r.Instance.Template.ClassName}]"); } - //return false; - //} } return true; - /* - var bag = new AsyncBag(); - - //foreach (var store in stores) - // bag.Add(store.Trigger(ResourceTrigger.Initialize)); - - - bag.Seal(); - - var rt = new AsyncReply(); - bag.Then((x) => - { - foreach (var b in x) - if (!b) - { - rt.Trigger(false); - return; - } - - var rBag = new AsyncBag(); - foreach (var rk in resources) - { - IResource r; - if (rk.Value.TryGetTarget(out r)) - rBag.Add(r.Trigger(ResourceTrigger.Initialize)); - } - - rBag.Seal(); - - rBag.Then(y => - { - foreach (var b in y) - if (!b) - { - rt.Trigger(false); - return; - } - - rt.Trigger(true); - warehouseIsOpen = true; - }); - - }); - - - return rt; - */ } /// @@ -262,7 +210,7 @@ public static class Warehouse /// This function issues terminate trigger to all resources and stores. /// /// True, if no problem occurred. - public static AsyncReply Close() + public AsyncReply Close() { var bag = new AsyncBag(); @@ -315,96 +263,20 @@ public static class Warehouse } - /* - private static IResource[] QureyIn(string[] path, int index, IEnumerable resources)// AutoList resources) - { - var rt = new List(); - - if (index == path.Length - 1) - { - if (path[index] == "") - foreach (IResource child in resources) - rt.Add(child); - else - foreach (IResource child in resources) - if (child.Instance.Name == path[index]) - rt.Add(child); - } - else - foreach (IResource child in resources) - if (child.Instance.Name == path[index]) - rt.AddRange(QureyIn(path, index+1, child.Instance.Children())); - - return rt.ToArray(); - } - - public static AsyncReply Query(string path) - { - if (path == null || path == "") - { - var roots = stores.Where(s => s.Instance.Parents().Count() == 0).ToArray(); - return new AsyncReply(roots); - } - else - { - var rt = new AsyncReply(); - Get(path).Then(x => - { - var p = path.Split('/'); - - if (x == null) - { - rt.Trigger(QureyIn(p, 0, stores)); - } - else - { - var ar = QureyIn(p, 0, stores).Where(r => r != x).ToList(); - ar.Insert(0, x); - rt.Trigger(ar.ToArray()); - } - }); - - return rt; - - } - - } - */ - - - - public static async AsyncReply Query(string path) + public async AsyncReply Query(string path) { var p = path.Trim().TrimStart('/').Split('/'); - IResource resource; foreach (var store in stores.Keys) { if (p[0] == store.Instance.Name) { - if (p.Length == 1) - return new IResource[] { store }; + return store; var res = await store.Get(String.Join("/", p.Skip(1).ToArray())); if (res != null) - return new IResource[] { res }; - - - resource = store; - for (var i = 1; i < p.Length; i++) - { - var children = await resource.Instance.Children(p[i]); - if (children != null && children.Length > 0) - { - if (i == p.Length - 1) - return children; - else - resource = children[0]; - } - else - break; - } + return res; return null; } @@ -419,12 +291,9 @@ public static class Warehouse /// /// /// Resource instance. - public static async AsyncReply Get(string path, object attributes = null, IResource parent = null, IPermissionsManager manager = null) + public async AsyncReply Get(string path, object attributes = null, IResource parent = null, IPermissionsManager manager = null) where T : IResource { - //var rt = new AsyncReply(); - - // Should we create a new store ? if (urlRegex.IsMatch(path)) { @@ -441,8 +310,6 @@ public static class Warehouse try { - //await Put(store, url[2], null, parent, null, 0, manager, attributes); - if (url[3].Length > 0 && url[3] != "") return (T)await store.Get(url[3]); else @@ -451,79 +318,21 @@ public static class Warehouse } catch (Exception ex) { - Warehouse.Remove(store); + Remove(store); throw ex; } - } - - - // store.Get(url[3]).Then(r => - // { - // rt.Trigger(r); - // }).Error(e => - // { - // Warehouse.Remove(store); - // rt.TriggerError(e); - // }); - // else - // rt.Trigger(store); - - // store.Trigger(ResourceTrigger.Open).Then(x => - // { - - // warehouseIsOpen = true; - // await Put(store, url[2], null, parent, null, 0, manager, attributes); - - // if (url[3].Length > 0 && url[3] != "") - // store.Get(url[3]).Then(r => - // { - // rt.Trigger(r); - // }).Error(e => - // { - // Warehouse.Remove(store); - // rt.TriggerError(e); - // }); - // else - // rt.Trigger(store); - // }).Error(e => - // { - // rt.TriggerError(e); - // //Warehouse.Remove(store); - // }); - - // return rt; - //} } - - //await Query(path).Then(rs => - //{ - // // rt.TriggerError(new Exception()); - // if (rs != null && rs.Length > 0) - // rt.Trigger(rs.First()); - // else - // rt.Trigger(null); - //}); - - //return rt; - var res = await Query(path); - if (res == null || res.Length == 0) + if (res == null) return default(T); else - return (T)res.First(); + return (T)res; } - - //public static async AsyncReply Push(string path, T resource) where T : IResource - //{ - // await Put(path, resource); - // return resource; - //} - /// /// Put a resource in the warehouse. /// @@ -531,29 +340,27 @@ public static 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 static async AsyncReply Put(string name, T resource, IStore store = null, IResource parent = null, TypeTemplate customTemplate = null, ulong age = 0, IPermissionsManager manager = null, object attributes = null) where T : IResource + 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."); - var path = name.TrimStart('/').Split('/'); + var location = path.TrimStart('/').Split('/'); - if (path.Length > 1) + IResource parent = null; + IStore store = null; + var instanceName = location.Last(); + + if (location.Length > 1) { - if (parent != null) - throw new Exception("Parent can't be set when using path in instance name"); - - parent = await Warehouse.Get(string.Join("/", path.Take(path.Length - 1))); + parent = await Get(string.Join("/", path.Take(path.Length - 1))); if (parent == null) throw new Exception("Can't find parent"); - store = store ?? parent.Instance.Store; + store = parent.Instance.Store; } - var instanceName = path.Last(); - - var resourceReference = new WeakReference(resource); if (store == null) @@ -590,10 +397,13 @@ public static class Warehouse throw new Exception("Can't find a store for the resource."); } - resource.Instance = new Instance(resourceCounter++, instanceName, resource, store, customTemplate, age); + resource.Instance = new Instance(this, resourceCounter++, instanceName, resource, store, customTemplate, age); if (attributes != null) - resource.Instance.SetAttributes(Map.FromObject(attributes)); + if (attributes is Map attrs) + resource.Instance.SetAttributes(attrs); + else + resource.Instance.SetAttributes(Map.FromObject(attributes)); if (manager != null) resource.Instance.Managers.Add(manager); @@ -602,8 +412,6 @@ public static class Warehouse parent = null; - - try { if (resource is IStore) @@ -615,16 +423,15 @@ public static class Warehouse //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]++; - resources.TryAdd(resource.Instance.Id, resourceReference); if (warehouseIsOpen) @@ -639,15 +446,14 @@ public static class Warehouse } catch (Exception ex) { - Warehouse.Remove(resource); + Remove(resource); throw ex; } return resource; - } - public static async AsyncReply New(Type type, string name = null, IStore store = null, IResource parent = null, IPermissionsManager manager = null, object attributes = null, object properties = null) + public async AsyncReply New(Type type, string path, IPermissionsManager manager = null, object attributes = null, object properties = null) { type = ResourceProxy.GetProxy(type); @@ -703,26 +509,20 @@ public static class Warehouse } } - if (store != null || parent != null || res is IStore) - { - await Put(name, res, store, parent, null, 0, manager, attributes); - } - - return res; - + return await Put(path, res, null, 0, manager, attributes); } - public static async AsyncReply New(string name, IStore store = null, IResource parent = null, IPermissionsManager manager = null, object attributes = null, object properties = null) + public async AsyncReply New(string path, IPermissionsManager manager = null, object attributes = null, object properties = null) where T : IResource { - return (T)(await New(typeof(T), name, store, parent, manager, attributes, properties)); + return (T)(await New(typeof(T), path, manager, attributes, properties)); } /// /// Put a resource template in the templates warehouse. /// /// Resource template. - public static void PutTemplate(TypeTemplate template) + public void PutTemplate(TypeTemplate template) { if (templates[template.Type].ContainsKey(template.ClassId)) throw new Exception($"Template with same class Id already exists. {templates[template.Type][template.ClassId].ClassName} -> {template.ClassName}"); @@ -736,7 +536,7 @@ public static class Warehouse /// /// .Net type. /// Resource template. - public static TypeTemplate GetTemplateByType(Type type) + public TypeTemplate GetTemplateByType(Type type) { if (!(type.IsClass || type.IsEnum)) return null; @@ -762,8 +562,8 @@ public static class Warehouse return template; // create new template for type - template = new TypeTemplate(baseType, true); - TypeTemplate.GetDependencies(template); + template = new TypeTemplate(baseType, this); + TypeTemplate.GetDependencies(template, this); return template; } @@ -773,7 +573,7 @@ public static class Warehouse /// /// Class Id. /// Resource template. - public static TypeTemplate GetTemplateByClassId(UUID classId, TemplateType? templateType = null) + public TypeTemplate GetTemplateByClassId(UUID classId, TemplateType? templateType = null) { if (templateType == null) { @@ -807,7 +607,7 @@ public static class Warehouse /// /// Class name. /// Resource template. - public static TypeTemplate GetTemplateByClassName(string className, TemplateType? templateType = null) + public TypeTemplate GetTemplateByClassName(string className, TemplateType? templateType = null) { if (templateType == null) { @@ -836,14 +636,12 @@ public static class Warehouse } } - public static bool Remove(IResource resource) + public bool Remove(IResource resource) { if (resource.Instance == null) return false; - //lock (resourcesLock) - //{ WeakReference resourceReference;