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