2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2026-04-29 06:48:41 +00:00
This commit is contained in:
2026-04-05 12:35:27 +03:00
parent 44983d7784
commit c7d095ea96
17 changed files with 546 additions and 732 deletions
+177 -160
View File
@@ -57,9 +57,11 @@ partial class EpConnection
Dictionary<Uuid, TypeDef> typeDefs = new Dictionary<Uuid, TypeDef>();
object typeDefsLock = new object();
KeyList<uint, AsyncReply> requests = new KeyList<uint, AsyncReply>();
volatile uint callbackCounter = 0;
volatile int callbackCounter = 0;
Dictionary<IResource, List<byte>> subscriptions = new Dictionary<IResource, List<byte>>();
@@ -73,15 +75,18 @@ partial class EpConnection
/// <summary>
/// Send IIP request.
/// Send EP request.
/// </summary>
/// <param name="action">Packet action.</param>
/// <param name="args">Arguments to send.</param>
/// <returns></returns>
///
AsyncReply SendRequest(EpPacketRequest action, params object[] args)
{
var reply = new AsyncReply();
var c = callbackCounter++; // avoid thread racing
var c = (uint)Interlocked.Increment(ref callbackCounter);
//callbackCounter++; // avoid thread racing
requests.Add(c, reply);
if (args.Length == 0)
@@ -112,7 +117,7 @@ partial class EpConnection
}
/// <summary>
/// Send IIP notification.
/// Send EP notification.
/// </summary>
/// <param name="action">Packet action.</param>
/// <param name="args">Arguments to send.</param>
@@ -343,7 +348,7 @@ partial class EpConnection
var args = DataDeserializer.ListParser(dataType, Instance.Warehouse)
as object[];
var errorCode = (ushort)args[0];
var errorCode =Convert.ToUInt16( args[0]);
var errorMsg = (string)args[1];
req.TriggerError(new AsyncException(type, errorCode, errorMsg));
@@ -1721,60 +1726,66 @@ partial class EpConnection
/// <returns>TypeSchema.</returns>
public AsyncReply<TypeDef> GetTypeDefById(Uuid typeId)
{
if (typeDefs.ContainsKey(typeId))
return new AsyncReply<TypeDef>(typeDefs[typeId]);
else if (typeDefsByIdRequests.ContainsKey(typeId))
return typeDefsByIdRequests[typeId];
lock (typeDefsLock)
{
if (typeDefs.ContainsKey(typeId))
return new AsyncReply<TypeDef>(typeDefs[typeId]);
else if (typeDefsByIdRequests.ContainsKey(typeId))
return typeDefsByIdRequests[typeId];
var reply = new AsyncReply<TypeDef>();
typeDefsByIdRequests.Add(typeId, reply);
var reply = new AsyncReply<TypeDef>();
typeDefsByIdRequests.Add(typeId, reply);
SendRequest(EpPacketRequest.TypeDefById, typeId)
.Then((result) =>
{
var tt = TypeDef.Parse((byte[])result);
typeDefsByIdRequests.Remove(typeId);
typeDefs.Add(tt.Id, tt);
Instance.Warehouse.RegisterTypeDef(tt);
reply.Trigger(tt);
SendRequest(EpPacketRequest.TypeDefById, typeId)
.Then((result) =>
{
var tt = TypeDef.Parse((byte[])result);
typeDefsByIdRequests.Remove(typeId);
typeDefs.Add(tt.Id, tt);
Instance.Warehouse.RegisterTypeDef(tt);
reply.Trigger(tt);
}).Error((ex) =>
{
reply.TriggerError(ex);
});
}).Error((ex) =>
{
reply.TriggerError(ex);
});
return reply;
return reply;
}
}
public AsyncReply<TypeDef> GetTypeDefByName(string typeName)
{
var typeDef = typeDefs.Values.FirstOrDefault(x => x.Name == typeName);
if (typeDef != null)
return new AsyncReply<TypeDef>(typeDef);
lock (typeDefsLock)
{
var typeDef = typeDefs.Values.FirstOrDefault(x => x.Name == typeName);
if (typeDef != null)
return new AsyncReply<TypeDef>(typeDef);
if (typeDefsByNameRequests.ContainsKey(typeName))
return typeDefsByNameRequests[typeName];
if (typeDefsByNameRequests.ContainsKey(typeName))
return typeDefsByNameRequests[typeName];
var reply = new AsyncReply<TypeDef>();
typeDefsByNameRequests.Add(typeName, reply);
var reply = new AsyncReply<TypeDef>();
typeDefsByNameRequests.Add(typeName, reply);
SendRequest(EpPacketRequest.TypeDefByName, typeName)
.Then((result) =>
{
var tt = TypeDef.Parse((byte[])result);
SendRequest(EpPacketRequest.TypeDefByName, typeName)
.Then((result) =>
{
var tt = TypeDef.Parse((byte[])result);
typeDefsByNameRequests.Remove(typeName);
typeDefs.Add(tt.Id, tt);
Instance.Warehouse.RegisterTypeDef(tt);
reply.Trigger(tt);
}).Error((ex) =>
{
reply.TriggerError(ex);
});
typeDefsByNameRequests.Remove(typeName);
typeDefs.Add(tt.Id, tt);
Instance.Warehouse.RegisterTypeDef(tt);
reply.Trigger(tt);
}).Error((ex) =>
{
reply.TriggerError(ex);
});
return reply;
return reply;
}
}
// IStore interface
@@ -1846,156 +1857,162 @@ partial class EpConnection
/// </summary>
/// <param name="id">Resource Id</param>
/// <returns>DistributedResource</returns>
///
object fetchLock = new object();
public AsyncReply<EpResource> Fetch(uint id, uint[] requestSequence)
{
//lock (fetchLock)
//{
EpResource resource = null;
EpResource resource = null;
attachedResources[id]?.TryGetTarget(out resource);
attachedResources[id]?.TryGetTarget(out resource);
if (resource != null)
return new AsyncReply<EpResource>(resource);
resource = neededResources[id];
var requestInfo = resourceRequests[id];
if (requestInfo != null)
{
if (resource != null && (requestSequence?.Contains(id) ?? false))
{
// dead lock avoidance for loop reference.
if (resource != null)
return new AsyncReply<EpResource>(resource);
}
else if (resource != null && requestInfo.RequestSequence.Contains(id))
resource = neededResources[id];
var requestInfo = resourceRequests[id];
if (requestInfo != null)
{
// dead lock avoidance for dependent reference.
if (resource != null && (requestSequence?.Contains(id) ?? false))
{
// dead lock avoidance for loop reference.
return new AsyncReply<EpResource>(resource);
}
else if (resource != null && requestInfo.RequestSequence.Contains(id))
{
// dead lock avoidance for dependent reference.
return new AsyncReply<EpResource>(resource);
}
else
{
return requestInfo.Reply;
}
}
else if (resource != null && !resource.DistributedResourceSuspended)
{
// @REVIEW: this should never happen
Global.Log("DCON", LogType.Error, "Resource not moved to attached.");
return new AsyncReply<EpResource>(resource);
}
else
{
return requestInfo.Reply;
}
}
else if (resource != null && !resource.DistributedResourceSuspended)
{
// @REVIEW: this should never happen
Global.Log("DCON", LogType.Error, "Resource not moved to attached.");
return new AsyncReply<EpResource>(resource);
}
var newSequence = requestSequence != null ? requestSequence.Concat(new uint[] { id }).ToArray() : new uint[] { id };
var newSequence = requestSequence != null ? requestSequence.Concat(new uint[] { id }).ToArray() : new uint[] { id };
var reply = new AsyncReply<EpResource>();
resourceRequests.Add(id, new EpResourceAttachRequestInfo(reply, newSequence));
var reply = new AsyncReply<EpResource>();
resourceRequests.Add(id, new EpResourceAttachRequestInfo(reply, newSequence));
SendRequest(EpPacketRequest.AttachResource, id)
.Then((result) =>
{
if (result == null)
SendRequest(EpPacketRequest.AttachResource, id)
.Then((result) =>
{
reply.TriggerError(new AsyncException(ErrorType.Management,
(ushort)ExceptionCode.ResourceNotFound, "Null response"));
return;
}
if (result == null)
{
reply.TriggerError(new AsyncException(ErrorType.Management,
(ushort)ExceptionCode.ResourceNotFound, "Null response"));
return;
}
// TypeId, Age, Link, Hops, PropertyValue[]
var args = (object[])result;
var typeId = (Uuid)args[0];
var age = Convert.ToUInt64(args[1]);
var link = (string)args[2];
var hops = (byte)args[3];
var pvData = (byte[])args[4];
// TypeId, Age, Link, Hops, PropertyValue[]
var args = (object[])result;
var typeId = (Uuid)args[0];
var age = Convert.ToUInt64(args[1]);
var link = (string)args[2];
var hops = (byte)args[3];
var pvData = (byte[])args[4];
EpResource dr;
TypeDef typeDef = null;
EpResource dr;
TypeDef typeDef = null;
if (resource == null)
{
typeDef = Instance.Warehouse.GetTypeDefById(typeId, TypeDefKind.Resource);
if (typeDef?.DefinedType != null && typeDef.IsWrapper)
dr = Activator.CreateInstance(typeDef.DefinedType, this, id, Convert.ToUInt64(args[1]), (string)args[2]) as EpResource;
if (resource == null)
{
typeDef = Instance.Warehouse.GetTypeDefById(typeId, TypeDefKind.Resource);
if (typeDef?.DefinedType != null && typeDef.IsWrapper)
dr = Activator.CreateInstance(typeDef.DefinedType, this, id, Convert.ToUInt64(args[1]), (string)args[2]) as EpResource;
else
dr = new EpResource(this, id, Convert.ToUInt64(args[1]), (string)args[2]);
}
else
dr = new EpResource(this, id, Convert.ToUInt64(args[1]), (string)args[2]);
}
else
{
dr = resource;
typeDef = resource.Instance.Definition;
}
var initResource = (EpResource ok) =>
{
var parsedReply = DataDeserializer.PropertyValueArrayParserAsync(pvData, 0, (uint)pvData.Length, this, newSequence);// Codec.proper (content, 0, this, newSequence, transmissionType);
parsedReply.Then(results =>
{
var pvs = results as PropertyValue[];
//var pvs = new List<PropertyValue>();
//for (var i = 0; i < ar.Length; i += 3)
// pvs.Add(new PropertyValue(ar[i + 2], Convert.ToUInt64(ar[i]), (DateTime)ar[i + 1]));
dr._Attach(pvs);
resourceRequests.Remove(id);
// move from needed to attached.
neededResources.Remove(id);
attachedResources[id] = new WeakReference<EpResource>(dr);
reply.Trigger(dr);
}).Error(ex => reply.TriggerError(ex));
dr = resource;
typeDef = resource.Instance.Definition;
}
};
if (typeDef == null)
{
GetTypeDefById(typeId).Then((tmp) =>
var initResource = (EpResource ok) =>
{
var parsedReply = DataDeserializer.PropertyValueArrayParserAsync(pvData, 0, (uint)pvData.Length, this, newSequence);// Codec.proper (content, 0, this, newSequence, transmissionType);
parsedReply.Then(results =>
{
var pvs = results as PropertyValue[];
//var pvs = new List<PropertyValue>();
//for (var i = 0; i < ar.Length; i += 3)
// pvs.Add(new PropertyValue(ar[i + 2], Convert.ToUInt64(ar[i]), (DateTime)ar[i + 1]));
dr._Attach(pvs);
resourceRequests.Remove(id);
// move from needed to attached.
neededResources.Remove(id);
attachedResources[id] = new WeakReference<EpResource>(dr);
reply.Trigger(dr);
}).Error(ex => reply.TriggerError(ex));
};
if (typeDef == null)
{
GetTypeDefById(typeId).Then((tmp) =>
{
// typeId, ResourceAge, ResourceLink, Content
if (resource == null)
{
dr.ResourceDefinition = tmp;
Instance.Warehouse.Put(this.Instance.Link + "/" + id.ToString(), dr)
.Then(initResource)
.Error(ex => reply.TriggerError(ex));
}
else
{
initResource(resource);
}
}).Error((ex) =>
{
reply.TriggerError(ex);
});
}
else
{
// typeId, ResourceAge, ResourceLink, Content
if (resource == null)
{
dr.ResourceDefinition = tmp;
dr.ResourceDefinition = typeDef;
Instance.Warehouse.Put(this.Instance.Link + "/" + id.ToString(), dr)
.Then(initResource)
.Error(ex => reply.TriggerError(ex));
.Then(initResource).Error((ex) => reply.TriggerError(ex));
}
else
{
initResource(resource);
}
}).Error((ex) =>
{
reply.TriggerError(ex);
});
}
else
}
}).Error((ex) =>
{
if (resource == null)
{
Instance.Warehouse.Put(this.Instance.Link + "/" + id.ToString(), dr)
.Then(initResource).Error((ex) => reply.TriggerError(ex));
}
else
{
initResource(resource);
}
}
}).Error((ex) =>
{
reply.TriggerError(ex);
});
reply.TriggerError(ex);
});
return reply;
return reply;
//}
}