2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2025-05-06 11:32:59 +00:00

deadlock prevention

This commit is contained in:
Ahmed Zamil 2022-03-31 02:27:30 +03:00
parent f258464063
commit 20fcaba518
7 changed files with 268 additions and 216 deletions

View File

@ -43,7 +43,7 @@ namespace Esiur.Data;
public static class Codec public static class Codec
{ {
delegate AsyncReply Parser(byte[] data, uint offset, uint length, DistributedConnection connection); delegate AsyncReply Parser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence);
static Parser[][] FixedParsers = new Parser[][] static Parser[][] FixedParsers = new Parser[][]
@ -114,7 +114,7 @@ public static class Codec
/// <param name="connection">DistributedConnection is required in case a structure in the array holds items at the other end.</param> /// <param name="connection">DistributedConnection is required in case a structure in the array holds items at the other end.</param>
/// <param name="dataType">DataType, in case the data is not prepended with DataType</param> /// <param name="dataType">DataType, in case the data is not prepended with DataType</param>
/// <returns>Value</returns> /// <returns>Value</returns>
public static (uint, AsyncReply) Parse(byte[] data, uint offset, DistributedConnection connection, TransmissionType? dataType = null) public static (uint, AsyncReply) Parse(byte[] data, uint offset, DistributedConnection connection, uint[] requestSequence, TransmissionType? dataType = null)
{ {
uint len = 0; uint len = 0;
@ -132,15 +132,15 @@ public static class Codec
if (tt.Class == TransmissionTypeClass.Fixed) if (tt.Class == TransmissionTypeClass.Fixed)
{ {
return (len, FixedParsers[tt.Exponent][tt.Index](data, dataType.Value.Offset, (uint)tt.ContentLength, connection)); return (len, FixedParsers[tt.Exponent][tt.Index](data, dataType.Value.Offset, (uint)tt.ContentLength, connection, requestSequence));
} }
else if (tt.Class == TransmissionTypeClass.Dynamic) else if (tt.Class == TransmissionTypeClass.Dynamic)
{ {
return (len, DynamicParsers[tt.Index](data, dataType.Value.Offset, (uint)tt.ContentLength, connection)); return (len, DynamicParsers[tt.Index](data, dataType.Value.Offset, (uint)tt.ContentLength, connection, requestSequence));
} }
else //if (tt.Class == TransmissionTypeClass.Typed) else //if (tt.Class == TransmissionTypeClass.Typed)
{ {
return (len, TypedParsers[tt.Index](data, dataType.Value.Offset, (uint)tt.ContentLength, connection)); return (len, TypedParsers[tt.Index](data, dataType.Value.Offset, (uint)tt.ContentLength, connection, requestSequence));
} }
} }

View File

@ -12,115 +12,115 @@ namespace Esiur.Data;
public static class DataDeserializer public static class DataDeserializer
{ {
public static AsyncReply NullParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static AsyncReply NullParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
return new AsyncReply(null); return new AsyncReply(null);
} }
public static AsyncReply BooleanTrueParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static AsyncReply BooleanTrueParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
return new AsyncReply<bool>(true); return new AsyncReply<bool>(true);
} }
public static AsyncReply BooleanFalseParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static AsyncReply BooleanFalseParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
return new AsyncReply<bool>(false); return new AsyncReply<bool>(false);
} }
public static AsyncReply NotModifiedParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static AsyncReply NotModifiedParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
return new AsyncReply<NotModified>(new NotModified()); return new AsyncReply<NotModified>(new NotModified());
} }
public static AsyncReply ByteParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static AsyncReply ByteParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
return new AsyncReply<byte>(data[offset]); return new AsyncReply<byte>(data[offset]);
} }
public static AsyncReply SByteParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static AsyncReply SByteParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
return new AsyncReply<sbyte>((sbyte)data[offset]); return new AsyncReply<sbyte>((sbyte)data[offset]);
} }
public static unsafe AsyncReply Char16Parser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply Char16Parser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
fixed (byte* ptr = &data[offset]) fixed (byte* ptr = &data[offset])
return new AsyncReply<char>(*(char*)ptr); return new AsyncReply<char>(*(char*)ptr);
} }
public static AsyncReply Char8Parser(byte[] data, uint offset, uint length, DistributedConnection connection) public static AsyncReply Char8Parser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
return new AsyncReply<char>((char)data[offset]); return new AsyncReply<char>((char)data[offset]);
} }
public static unsafe AsyncReply Int16Parser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply Int16Parser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
fixed (byte* ptr = &data[offset]) fixed (byte* ptr = &data[offset])
return new AsyncReply<short>(*(short*)ptr); return new AsyncReply<short>(*(short*)ptr);
} }
public static unsafe AsyncReply UInt16Parser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply UInt16Parser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
fixed (byte* ptr = &data[offset]) fixed (byte* ptr = &data[offset])
return new AsyncReply<ushort>(*(ushort*)ptr); return new AsyncReply<ushort>(*(ushort*)ptr);
} }
public static unsafe AsyncReply Int32Parser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply Int32Parser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
fixed (byte* ptr = &data[offset]) fixed (byte* ptr = &data[offset])
return new AsyncReply<int>(*(int*)ptr); return new AsyncReply<int>(*(int*)ptr);
} }
public static unsafe AsyncReply UInt32Parser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply UInt32Parser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
fixed (byte* ptr = &data[offset]) fixed (byte* ptr = &data[offset])
return new AsyncReply<uint>(*(uint*)ptr); return new AsyncReply<uint>(*(uint*)ptr);
} }
public static unsafe AsyncReply Float32Parser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply Float32Parser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
fixed (byte* ptr = &data[offset]) fixed (byte* ptr = &data[offset])
return new AsyncReply<float>(*(float*)ptr); return new AsyncReply<float>(*(float*)ptr);
} }
public static unsafe AsyncReply Float64Parser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply Float64Parser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
fixed (byte* ptr = &data[offset]) fixed (byte* ptr = &data[offset])
return new AsyncReply<double>(*(double*)ptr); return new AsyncReply<double>(*(double*)ptr);
} }
public static unsafe AsyncReply Float128Parser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply Float128Parser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
fixed (byte* ptr = &data[offset]) fixed (byte* ptr = &data[offset])
return new AsyncReply<decimal>(*(decimal*)ptr); return new AsyncReply<decimal>(*(decimal*)ptr);
} }
public static unsafe AsyncReply Int128Parser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply Int128Parser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
fixed (byte* ptr = &data[offset]) fixed (byte* ptr = &data[offset])
return new AsyncReply<decimal>(*(decimal*)ptr); return new AsyncReply<decimal>(*(decimal*)ptr);
} }
public static unsafe AsyncReply UInt128Parser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply UInt128Parser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
fixed (byte* ptr = &data[offset]) fixed (byte* ptr = &data[offset])
return new AsyncReply<decimal>(*(decimal*)ptr); return new AsyncReply<decimal>(*(decimal*)ptr);
} }
public static unsafe AsyncReply Int64Parser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply Int64Parser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
fixed (byte* ptr = &data[offset]) fixed (byte* ptr = &data[offset])
return new AsyncReply<long>(*(long*)ptr); return new AsyncReply<long>(*(long*)ptr);
} }
public static unsafe AsyncReply UInt64Parser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply UInt64Parser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
fixed (byte* ptr = &data[offset]) fixed (byte* ptr = &data[offset])
return new AsyncReply<ulong>(*(ulong*)ptr); return new AsyncReply<ulong>(*(ulong*)ptr);
} }
public static unsafe AsyncReply DateTimeParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply DateTimeParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
fixed (byte* ptr = &data[offset]) fixed (byte* ptr = &data[offset])
return new AsyncReply<DateTime>(new DateTime(*(long*)ptr, DateTimeKind.Utc)); return new AsyncReply<DateTime>(new DateTime(*(long*)ptr, DateTimeKind.Utc));
@ -128,14 +128,14 @@ public static class DataDeserializer
} }
public static unsafe AsyncReply ResourceParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply ResourceParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
fixed (byte* ptr = &data[offset]) fixed (byte* ptr = &data[offset])
return connection.Fetch(*(uint*)ptr); return connection.Fetch(*(uint*)ptr, requestSequence);
} }
public static unsafe AsyncReply LocalResourceParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply LocalResourceParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
fixed (byte* ptr = &data[offset]) fixed (byte* ptr = &data[offset])
return Warehouse.GetById(*(uint*)ptr); return Warehouse.GetById(*(uint*)ptr);
@ -143,17 +143,17 @@ public static class DataDeserializer
} }
public static unsafe AsyncReply RawDataParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply RawDataParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
return new AsyncReply<byte[]>(data.Clip(offset, length)); return new AsyncReply<byte[]>(data.Clip(offset, length));
} }
public static unsafe AsyncReply StringParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply StringParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
return new AsyncReply<string>(data.GetString(offset, length)); return new AsyncReply<string>(data.GetString(offset, length));
} }
public static unsafe AsyncReply RecordParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply RecordParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
var reply = new AsyncReply<IRecord>(); var reply = new AsyncReply<IRecord>();
@ -165,10 +165,9 @@ public static class DataDeserializer
var template = Warehouse.GetTemplateByClassId((Guid)classId, TemplateType.Record); var template = Warehouse.GetTemplateByClassId((Guid)classId, TemplateType.Record);
if (template != null) var initRecord = (TypeTemplate template) =>
{ {
//ListParser(data, offset, length, connection) ListParser(data, offset, length, connection, requestSequence).Then(r =>
ListParser(data, offset, length, connection).Then(r =>
{ {
var ar = (object[])r; var ar = (object[])r;
@ -181,7 +180,8 @@ public static class DataDeserializer
{ {
var v = Convert.ChangeType(ar[i], template.Properties[i].PropertyInfo.PropertyType); var v = Convert.ChangeType(ar[i], template.Properties[i].PropertyInfo.PropertyType);
template.Properties[i].PropertyInfo.SetValue(record, v); template.Properties[i].PropertyInfo.SetValue(record, v);
} catch ( Exception ex) }
catch (Exception ex)
{ {
Console.WriteLine(ex); Console.WriteLine(ex);
} }
@ -199,21 +199,24 @@ public static class DataDeserializer
reply.Trigger(record); reply.Trigger(record);
} }
}); });
};
if (template != null)
{
initRecord(template);
} }
else else
{ {
connection.GetTemplate((Guid)classId).Then(tmp => connection.GetTemplate((Guid)classId).Then(tmp =>
{ {
ListParser(data, offset, length, connection).Then(r => ListParser(data, offset, length, connection, requestSequence).Then(r =>
{ {
var ar = (object[])r; if (tmp == null)
reply.TriggerError(new AsyncException(ErrorType.Management, (ushort)ExceptionCode.TemplateNotFound,
"Template not found for record."));
else
initRecord(tmp);
var record = new Record();
for (var i = 0; i < tmp.Properties.Length; i++)
record.Add(tmp.Properties[i].Name, ar[i]);
reply.Trigger(record);
}); });
}).Error(x => reply.TriggerError(x)); }).Error(x => reply.TriggerError(x));
} }
@ -221,12 +224,12 @@ public static class DataDeserializer
return reply; return reply;
} }
public static unsafe AsyncReply ConstantParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply ConstantParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public static unsafe AsyncReply EnumParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static unsafe AsyncReply EnumParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
var classId = data.GetGuid(offset); var classId = data.GetGuid(offset);
@ -254,13 +257,13 @@ public static class DataDeserializer
public static AsyncReply RecordListParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static AsyncReply RecordListParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
var rt = new AsyncBag<IRecord>(); var rt = new AsyncBag<IRecord>();
while (length > 0) while (length > 0)
{ {
var (cs, reply) = Codec.Parse(data, offset, connection); var (cs, reply) = Codec.Parse(data, offset, connection, requestSequence);
rt.Add(reply); rt.Add(reply);
@ -278,13 +281,13 @@ public static class DataDeserializer
return rt; return rt;
} }
public static AsyncReply ResourceListParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static AsyncReply ResourceListParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
var rt = new AsyncBag<IResource>(); var rt = new AsyncBag<IResource>();
while (length > 0) while (length > 0)
{ {
var (cs, reply) = Codec.Parse(data, offset, connection); var (cs, reply) = Codec.Parse(data, offset, connection, requestSequence);
rt.Add(reply); rt.Add(reply);
@ -303,13 +306,13 @@ public static class DataDeserializer
} }
public static AsyncBag<object> ListParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static AsyncBag<object> ListParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
var rt = new AsyncBag<object>(); var rt = new AsyncBag<object>();
while (length > 0) while (length > 0)
{ {
var (cs, reply) = Codec.Parse(data, offset, connection); var (cs, reply) = Codec.Parse(data, offset, connection, requestSequence);
rt.Add(reply); rt.Add(reply);
@ -327,7 +330,7 @@ public static class DataDeserializer
return rt; return rt;
} }
public static AsyncReply TypedMapParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static AsyncReply TypedMapParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
// get key type // get key type
var (keyCs, keyRepType) = RepresentationType.Parse(data, offset); var (keyCs, keyRepType) = RepresentationType.Parse(data, offset);
@ -346,7 +349,7 @@ public static class DataDeserializer
while (length > 0) while (length > 0)
{ {
var (cs, reply) = Codec.Parse(data, offset, connection); var (cs, reply) = Codec.Parse(data, offset, connection, requestSequence);
results.Add(reply); results.Add(reply);
@ -376,7 +379,7 @@ public static class DataDeserializer
} }
public static AsyncReply TupleParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static AsyncReply TupleParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
var results = new AsyncBag<object>(); var results = new AsyncBag<object>();
var rt = new AsyncReply(); var rt = new AsyncReply();
@ -396,7 +399,7 @@ public static class DataDeserializer
while (length > 0) while (length > 0)
{ {
var (cs, reply) = Codec.Parse(data, offset, connection); var (cs, reply) = Codec.Parse(data, offset, connection, requestSequence);
results.Add(reply); results.Add(reply);
@ -435,7 +438,7 @@ public static class DataDeserializer
return rt; return rt;
} }
public static AsyncReply TypedListParser(byte[] data, uint offset, uint length, DistributedConnection connection) public static AsyncReply TypedListParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)
{ {
var rt = new AsyncBag<object>(); var rt = new AsyncBag<object>();
@ -451,7 +454,7 @@ public static class DataDeserializer
while (length > 0) while (length > 0)
{ {
var (cs, reply) = Codec.Parse(data, offset, connection); var (cs, reply) = Codec.Parse(data, offset, connection, requestSequence);
rt.Add(reply); rt.Add(reply);
@ -470,12 +473,12 @@ public static class DataDeserializer
} }
public static AsyncBag<PropertyValue> PropertyValueArrayParser(byte[] data, uint offset, uint length, DistributedConnection connection)//, bool ageIncluded = true) public static AsyncBag<PropertyValue> PropertyValueArrayParser(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)//, bool ageIncluded = true)
{ {
var rt = new AsyncBag<PropertyValue>(); var rt = new AsyncBag<PropertyValue>();
ListParser(data, offset, length, connection).Then(x => ListParser(data, offset, length, connection, requestSequence).Then(x =>
{ {
var ar = (object[])x; var ar = (object[])x;
var pvs = new List<PropertyValue>(); var pvs = new List<PropertyValue>();
@ -491,7 +494,7 @@ public static class DataDeserializer
} }
public static (uint, AsyncReply<PropertyValue>) PropertyValueParser(byte[] data, uint offset, DistributedConnection connection)//, bool ageIncluded = true) public static (uint, AsyncReply<PropertyValue>) PropertyValueParser(byte[] data, uint offset, DistributedConnection connection, uint[] requestSequence)//, bool ageIncluded = true)
{ {
var reply = new AsyncReply<PropertyValue>(); var reply = new AsyncReply<PropertyValue>();
@ -502,7 +505,7 @@ public static class DataDeserializer
offset += 8; offset += 8;
var (valueSize, results) = Codec.Parse(data, offset, connection); var (valueSize, results) = Codec.Parse(data, offset, connection, requestSequence);
results.Then(value => results.Then(value =>
{ {
@ -512,7 +515,7 @@ public static class DataDeserializer
return (16 + valueSize, reply); return (16 + valueSize, reply);
} }
public static AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> HistoryParser(byte[] data, uint offset, uint length, IResource resource, DistributedConnection connection) public static AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> HistoryParser(byte[] data, uint offset, uint length, IResource resource, DistributedConnection connection, uint[] requestSequence)
{ {
//var count = (int)toAge - (int)fromAge; //var count = (int)toAge - (int)fromAge;
@ -531,7 +534,7 @@ public static class DataDeserializer
var cs = data.GetUInt32(offset, Endian.Little); var cs = data.GetUInt32(offset, Endian.Little);
offset += 4; offset += 4;
var (len, pv) = PropertyValueParser(data, offset, connection); var (len, pv) = PropertyValueParser(data, offset, connection, requestSequence);
bagOfBags.Add(pv);// ParsePropertyValueArray(data, offset, cs, connection)); bagOfBags.Add(pv);// ParsePropertyValueArray(data, offset, cs, connection));
offset += len; offset += len;

View File

@ -274,11 +274,10 @@ public class HTTPServer : NetworkServer<HTTPConnection>, IResource
internal bool Execute(HTTPConnection sender) internal bool Execute(HTTPConnection sender)
{ {
foreach (var route in routes[sender.Request.Method]) if (!sender.WSMode)
{ foreach (var route in routes[sender.Request.Method])
if (route.Invoke(sender)) if (route.Invoke(sender))
return true; return true;
}
foreach (var resource in filters) foreach (var resource in filters)

View File

@ -1225,7 +1225,7 @@ public partial class DistributedConnection : NetworkConnection, IStore
for (var i = 0; i < resources.Keys.Count; i++) for (var i = 0; i < resources.Keys.Count; i++)
{ {
var index = resources.Keys.ElementAt(i); var index = resources.Keys.ElementAt(i);
bag.Add(Fetch(index)); bag.Add(Fetch(index, null));
} }
bag.Seal(); bag.Seal();

View File

@ -232,7 +232,7 @@ partial class DistributedConnection
{ {
var req = requests.Take(callbackId); var req = requests.Take(callbackId);
var (_, parsed) = Codec.Parse(content, 0, this, transmissionType); var (_, parsed) = Codec.Parse(content, 0, this, null, transmissionType);
parsed.Then((rt) => parsed.Then((rt) =>
{ {
req?.Trigger(rt); req?.Trigger(rt);
@ -256,7 +256,7 @@ partial class DistributedConnection
if (requests.ContainsKey(callbackId)) if (requests.ContainsKey(callbackId))
{ {
var req = requests[callbackId]; var req = requests[callbackId];
var (_, parsed) = Codec.Parse(data, dataType.Offset, this, dataType); var (_, parsed) = Codec.Parse(data, dataType.Offset, this, null, dataType);
parsed.Then((x) => parsed.Then((x) =>
{ {
req.TriggerChunk(x); req.TriggerChunk(x);
@ -282,12 +282,12 @@ partial class DistributedConnection
void IIPEventPropertyUpdated(uint resourceId, byte index, TransmissionType dataType, byte[] data) void IIPEventPropertyUpdated(uint resourceId, byte index, TransmissionType dataType, byte[] data)
{ {
Fetch(resourceId).Then(r => Fetch(resourceId, null).Then(r =>
{ {
var item = new AsyncReply<DistributedResourceQueueItem>(); var item = new AsyncReply<DistributedResourceQueueItem>();
queue.Add(item); queue.Add(item);
var (_, parsed) = Codec.Parse(data, dataType.Offset, this, dataType);// 0, this); var (_, parsed) = Codec.Parse(data, dataType.Offset, this, null, dataType);// 0, this);
parsed.Then((arguments) => parsed.Then((arguments) =>
{ {
var pt = r.Instance.Template.GetPropertyTemplateByIndex(index); var pt = r.Instance.Template.GetPropertyTemplateByIndex(index);
@ -345,13 +345,13 @@ partial class DistributedConnection
void IIPEventEventOccurred(uint resourceId, byte index, TransmissionType dataType, byte[] data) void IIPEventEventOccurred(uint resourceId, byte index, TransmissionType dataType, byte[] data)
{ {
Fetch(resourceId).Then(r => Fetch(resourceId, null).Then(r =>
{ {
// push to the queue to gaurantee serialization // push to the queue to gaurantee serialization
var item = new AsyncReply<DistributedResourceQueueItem>(); var item = new AsyncReply<DistributedResourceQueueItem>();
queue.Add(item); queue.Add(item);
var (_, parsed) = Codec.Parse(data, dataType.Offset, this, dataType);//, 0, this); var (_, parsed) = Codec.Parse(data, dataType.Offset, this, null, dataType);//, 0, this);
parsed.Then((arguments) => parsed.Then((arguments) =>
{ {
var et = r.Instance.Template.GetEventTemplateByIndex(index); var et = r.Instance.Template.GetEventTemplateByIndex(index);
@ -406,9 +406,9 @@ partial class DistributedConnection
void IIPEventChildAdded(uint resourceId, uint childId) void IIPEventChildAdded(uint resourceId, uint childId)
{ {
Fetch(resourceId).Then(parent => Fetch(resourceId, null).Then(parent =>
{ {
Fetch(childId).Then(child => Fetch(childId, null).Then(child =>
{ {
parent.children.Add(child); parent.children.Add(child);
child.parents.Add(parent); child.parents.Add(parent);
@ -420,9 +420,9 @@ partial class DistributedConnection
void IIPEventChildRemoved(uint resourceId, uint childId) void IIPEventChildRemoved(uint resourceId, uint childId)
{ {
Fetch(resourceId).Then(parent => Fetch(resourceId, null).Then(parent =>
{ {
Fetch(childId).Then(child => Fetch(childId, null).Then(child =>
{ {
parent.children.Remove(child); parent.children.Remove(child);
child.parents.Remove(parent); child.parents.Remove(parent);
@ -434,7 +434,7 @@ partial class DistributedConnection
void IIPEventRenamed(uint resourceId, string name) void IIPEventRenamed(uint resourceId, string name)
{ {
Fetch(resourceId).Then(resource => Fetch(resourceId, null).Then(resource =>
{ {
resource.Instance.Variables["name"] = name; resource.Instance.Variables["name"] = name;
}); });
@ -443,7 +443,7 @@ partial class DistributedConnection
void IIPEventAttributesUpdated(uint resourceId, byte[] attributes) void IIPEventAttributesUpdated(uint resourceId, byte[] attributes)
{ {
Fetch(resourceId).Then(resource => Fetch(resourceId, null).Then(resource =>
{ {
var attrs = attributes.GetStringArray(0, (uint)attributes.Length); var attrs = attributes.GetStringArray(0, (uint)attributes.Length);
@ -724,19 +724,19 @@ partial class DistributedConnection
return; return;
} }
DataDeserializer.ListParser(content, offset, cl, this).Then(parameters => DataDeserializer.ListParser(content, offset, cl, this, null).Then(parameters =>
{ {
offset += cl; offset += cl;
cl = content.GetUInt32(offset, Endian.Little); cl = content.GetUInt32(offset, Endian.Little);
//Codec.ParseStructure(content, offset, cl, this).Then(attributes => //Codec.ParseStructure(content, offset, cl, this).Then(attributes =>
DataDeserializer.TypedMapParser(content, offset, cl, this).Then(attributes => DataDeserializer.TypedMapParser(content, offset, cl, this, null).Then(attributes =>
{ {
offset += cl; offset += cl;
cl = (uint)content.Length - offset; cl = (uint)content.Length - offset;
//Codec.ParseStructure(content, offset, cl, this).Then(values => //Codec.ParseStructure(content, offset, cl, this).Then(values =>
DataDeserializer.TypedMapParser(content, offset, cl, this).Then(values => DataDeserializer.TypedMapParser(content, offset, cl, this, null).Then(values =>
{ {
#if NETSTANDARD #if NETSTANDARD
@ -1049,7 +1049,7 @@ partial class DistributedConnection
} }
DataDeserializer.TypedMapParser(attributes, 0, (uint)attributes.Length, this).Then(attrs => DataDeserializer.TypedMapParser(attributes, 0, (uint)attributes.Length, this, null).Then(attrs =>
{ {
if (r.Instance.SetAttributes((Map<string, object>)attrs, clearAttributes)) if (r.Instance.SetAttributes((Map<string, object>)attrs, clearAttributes))
SendReply(clearAttributes ? IIPPacket.IIPPacketAction.ClearAllAttributes : IIPPacket.IIPPacketAction.ClearAttributes, SendReply(clearAttributes ? IIPPacket.IIPPacketAction.ClearAllAttributes : IIPPacket.IIPPacketAction.ClearAttributes,
@ -1232,11 +1232,11 @@ partial class DistributedConnection
return; return;
} }
var (_, parsed) = Codec.Parse(content, 0, this, transmissionType); var (_, parsed) = Codec.Parse(content, 0, this, null, transmissionType);
parsed.Then(results => parsed.Then(results =>
{ {
var arguments = (Map<byte, object>)results ;// (object[])results; var arguments = (Map<byte, object>)results;// (object[])results;
// un hold the socket to send data immediately // un hold the socket to send data immediately
this.Socket.Unhold(); this.Socket.Unhold();
@ -1281,14 +1281,14 @@ partial class DistributedConnection
{ {
if (pis.Last().ParameterType == typeof(DistributedConnection)) if (pis.Last().ParameterType == typeof(DistributedConnection))
{ {
for(byte i = 0; i< pis.Length - 1; i++) for (byte i = 0; i < pis.Length - 1; i++)
args[i] = arguments.ContainsKey(i) ? args[i] = arguments.ContainsKey(i) ?
DC.CastConvert(arguments[i], pis[i].ParameterType) : Type.Missing; DC.CastConvert(arguments[i], pis[i].ParameterType) : Type.Missing;
args[args.Length - 1] = this; args[args.Length - 1] = this;
} }
else else
{ {
for (byte i = 0; i < pis.Length ; i++) for (byte i = 0; i < pis.Length; i++)
args[i] = arguments.ContainsKey(i) ? args[i] = arguments.ContainsKey(i) ?
DC.CastConvert(arguments[i], pis[i].ParameterType) : Type.Missing; DC.CastConvert(arguments[i], pis[i].ParameterType) : Type.Missing;
} }
@ -1331,13 +1331,13 @@ partial class DistributedConnection
(rt as Task).ContinueWith(t => (rt as Task).ContinueWith(t =>
{ {
#if NETSTANDARD #if NETSTANDARD
var res = t.GetType().GetTypeInfo().GetProperty("Result").GetValue(t); var res = t.GetType().GetTypeInfo().GetProperty("Result").GetValue(t);
#else #else
var res = t.GetType().GetProperty("Result").GetValue(t); var res = t.GetType().GetProperty("Result").GetValue(t);
#endif #endif
SendReply(IIPPacket.IIPPacketAction.InvokeFunction, callback) SendReply(IIPPacket.IIPPacketAction.InvokeFunction, callback)
.AddUInt8Array(Codec.Compose(res, this)) .AddUInt8Array(Codec.Compose(res, this))
.Done(); .Done();
}); });
//await t; //await t;
@ -1631,7 +1631,7 @@ partial class DistributedConnection
var pt = r.Instance.Template.GetPropertyTemplateByIndex(index); var pt = r.Instance.Template.GetPropertyTemplateByIndex(index);
if (pt != null) if (pt != null)
{ {
var (_, parsed) = Codec.Parse(content, 0, this, transmissionType); var (_, parsed) = Codec.Parse(content, 0, this, null, transmissionType);
parsed.Then((value) => parsed.Then((value) =>
{ {
if (r is DistributedResource) if (r is DistributedResource)
@ -2000,15 +2000,14 @@ partial class DistributedConnection
/// <param name="classId">Class GUID</param> /// <param name="classId">Class GUID</param>
/// <param name="id">Resource Id</param>Guid classId /// <param name="id">Resource Id</param>Guid classId
/// <returns>DistributedResource</returns> /// <returns>DistributedResource</returns>
public AsyncReply<DistributedResource> Fetch(uint id) public AsyncReply<DistributedResource> Fetch(uint id, uint[] requestSequence)
{ {
var resource = resources[id]; var resource = resources[id];
var request = resourceRequests[id]; var request = resourceRequests[id];
if (request != null) if (request != null)
{ {
if (resource != null) if (resource != null && (requestSequence?.Contains(id) ?? false))
// dig for dead locks // or not
return new AsyncReply<DistributedResource>(resource); return new AsyncReply<DistributedResource>(resource);
else else
return request; return request;
@ -2022,17 +2021,28 @@ partial class DistributedConnection
var reply = new AsyncReply<DistributedResource>(); var reply = new AsyncReply<DistributedResource>();
resourceRequests.Add(id, reply); resourceRequests.Add(id, reply);
var newSequence = requestSequence != null ? requestSequence.Concat(new uint[] { id }).ToArray() : new uint[] { id };
SendRequest(IIPPacket.IIPPacketAction.AttachResource) SendRequest(IIPPacket.IIPPacketAction.AttachResource)
.AddUInt32(id) .AddUInt32(id)
.Done() .Done()
.Then((rt) => .Then((rt) =>
{ {
if (rt == null)
{
reply.TriggerError(new AsyncException(ErrorType.Management,
(ushort)ExceptionCode.ResourceNotFound, "Null response"));
return;
}
DistributedResource dr; DistributedResource dr;
TypeTemplate template = null;
Guid classId = (Guid)rt[0];
if (resource == null) if (resource == null)
{ {
var template = Warehouse.GetTemplateByClassId((Guid)rt[0], TemplateType.Wrapper); template = Warehouse.GetTemplateByClassId(classId, TemplateType.Wrapper);
if (template?.DefinedType != null) if (template?.DefinedType != null)
dr = Activator.CreateInstance(template.DefinedType, this, id, (ulong)rt[1], (string)rt[2]) as DistributedResource; dr = Activator.CreateInstance(template.DefinedType, this, id, (ulong)rt[1], (string)rt[2]) as DistributedResource;
else else
@ -2044,57 +2054,64 @@ partial class DistributedConnection
var transmissionType = (TransmissionType)rt[3]; var transmissionType = (TransmissionType)rt[3];
var content = (byte[])rt[4]; var content = (byte[])rt[4];
GetTemplate((Guid)rt[0]).Then((tmp) => var initResource = (DistributedResource ok) =>
{
var (_, parsed) = Codec.Parse(content, 0, this, newSequence, transmissionType);
parsed.Then(results =>
{
var ar = results as object[];
var pvs = new List<PropertyValue>();
for (var i = 0; i < ar.Length; i += 3)
pvs.Add(new PropertyValue(ar[i + 2], (ulong?)ar[i], (DateTime?)ar[i + 1]));
dr._Attach(pvs.ToArray());// (PropertyValue[])pvs);
resourceRequests.Remove(id);
reply.Trigger(dr);
}).Error(ex => reply.TriggerError(ex));
};
if (template == null)
{
GetTemplate((Guid)rt[0]).Then((tmp) =>
{
// ClassId, ResourceAge, ResourceLink, Content
if (resource == null)
{
Warehouse.Put(id.ToString(), dr, this, null, tmp).Then(initResource).Error(ex => reply.TriggerError(ex));
}
else
{
initResource(resource);
}
}).Error((ex) =>
{
reply.TriggerError(ex);
});
}
else
{ {
// ClassId, ResourceAge, ResourceLink, Content
if (resource == null) if (resource == null)
{ {
Warehouse.Put(id.ToString(), dr, this, null, tmp).Then((ok) => Warehouse.Put(id.ToString(), dr, this, null, template)
{ .Then(initResource).Error((ex) => reply.TriggerError(ex));
var (_, parsed) = Codec.Parse(content, 0, this, transmissionType);
parsed.Then(results =>
{
var ar = results as object[];
var pvs = new List<PropertyValue>();
for (var i = 0; i < ar.Length; i += 3)
pvs.Add(new PropertyValue(ar[i + 2], (ulong?)ar[i], (DateTime?)ar[i + 1]));
dr._Attach(pvs.ToArray());// (PropertyValue[])pvs);
resourceRequests.Remove(id);
reply.Trigger(dr);
}).Error(ex => reply.TriggerError(ex));
}).Error(ex => reply.TriggerError(ex));
} }
else else
{ {
var (_, parsed) = Codec.Parse(content, 0, this, transmissionType); initResource(resource);
parsed.Then((results) =>
{
var ar = results as object[];
var pvs = new List<PropertyValue>();
for (var i = 0; i < ar.Length; i += 3)
pvs.Add(new PropertyValue(ar[i + 2], (ulong?)ar[i], (DateTime?)ar[i + 1]));
dr._Attach(pvs.ToArray());// (PropertyValue[])pvs);
// resourceRequests.Remove(id);
reply.Trigger(dr);
}).Error(ex => reply.TriggerError(ex));
} }
}).Error((ex) =>
{ }
reply.TriggerError(ex);
});
}).Error((ex) => }).Error((ex) =>
{ {
reply.TriggerError(ex); reply.TriggerError(ex);
}); });
return reply; return reply;
} }
@ -2111,7 +2128,7 @@ partial class DistributedConnection
var dataType = (TransmissionType)ar[0]; var dataType = (TransmissionType)ar[0];
var data = (byte[])ar[1]; var data = (byte[])ar[1];
var (_, parsed) = Codec.Parse(data, dataType.Offset, this, dataType); var (_, parsed) = Codec.Parse(data, dataType.Offset, this, null, dataType);
parsed.Then(resources => rt.Trigger(resources)) parsed.Then(resources => rt.Trigger(resources))
.Error(ex => rt.TriggerError(ex)); .Error(ex => rt.TriggerError(ex));
@ -2136,7 +2153,7 @@ partial class DistributedConnection
{ {
var dataType = (TransmissionType)ar[0]; var dataType = (TransmissionType)ar[0];
var data = (byte[])ar[1]; var data = (byte[])ar[1];
var (_, parsed) = Codec.Parse(data, dataType.Offset, this, dataType); var (_, parsed) = Codec.Parse(data, dataType.Offset, this, null, dataType);
parsed.Then(resources => rt.Trigger(resources)) parsed.Then(resources => rt.Trigger(resources))
.Error(ex => rt.TriggerError(ex)); .Error(ex => rt.TriggerError(ex));
@ -2204,7 +2221,7 @@ partial class DistributedConnection
var dataType = (TransmissionType)ar[0]; var dataType = (TransmissionType)ar[0];
var data = (byte[])ar[1]; var data = (byte[])ar[1];
//Codec.Parse(d, ) //Codec.Parse(d, )
var (_, parsed) = Codec.Parse(data, 0, this, dataType); var (_, parsed) = Codec.Parse(data, 0, this, null, dataType);
parsed.Then(st => parsed.Then(st =>
{ {
@ -2227,7 +2244,7 @@ partial class DistributedConnection
var dataType = (TransmissionType)ar[0]; var dataType = (TransmissionType)ar[0];
var data = (byte[])ar[1]; var data = (byte[])ar[1];
var (_, parsed) = Codec.Parse(data, 0, this, dataType); var (_, parsed) = Codec.Parse(data, 0, this, null, dataType);
parsed.Then(st => parsed.Then(st =>
{ {
@ -2268,7 +2285,7 @@ partial class DistributedConnection
{ {
var content = (byte[])rt[0]; var content = (byte[])rt[0];
DataDeserializer.HistoryParser(content, 0, (uint)content.Length, resource, this) DataDeserializer.HistoryParser(content, 0, (uint)content.Length, resource, this, null)
.Then((history) => reply.Trigger(history)); .Then((history) => reply.Trigger(history));
}).Error((ex) => reply.TriggerError(ex)); }).Error((ex) => reply.TriggerError(ex));
@ -2298,7 +2315,7 @@ partial class DistributedConnection
var dataType = (TransmissionType)ar[0]; var dataType = (TransmissionType)ar[0];
var data = ar[1] as byte[]; var data = ar[1] as byte[];
var (_, parsed) = Codec.Parse(data, dataType.Offset, this, dataType); var (_, parsed) = Codec.Parse(data, dataType.Offset, this, null, dataType);
parsed.Then(resources => reply.Trigger(resources)) parsed.Then(resources => reply.Trigger(resources))
.Error(ex => reply.TriggerError(ex)); .Error(ex => reply.TriggerError(ex));
@ -2342,7 +2359,7 @@ partial class DistributedConnection
{ {
var rid = (uint)args[0]; var rid = (uint)args[0];
Fetch(rid).Then((r) => Fetch(rid, null).Then((r) =>
{ {
reply.Trigger(r); reply.Trigger(r);
}); });

View File

@ -167,13 +167,45 @@ public class TypeTemplate
return new Guid(hash); return new Guid(hash);
} }
static Type GetElementType(Type type) => type switch static Type[] GetDistributedTypes(Type type)
{ {
{ IsArray: true } => type.GetElementType(), if (type.IsArray)
// { IsEnum: true } => type.GetEnumUnderlyingType(), return GetDistributedTypes(type.GetElementType());
(_) => type else if (type.IsEnum)
}; return new Type[] { type };
else if (type.IsGenericType)
{
var genericType = type.GetGenericTypeDefinition();
var genericTypeArgs = type.GetGenericArguments();
if (genericType == typeof(List<>)
|| genericType == typeof(DistributedPropertyContext<>))
{
return GetDistributedTypes(genericTypeArgs[0]);
}
else if (genericType == typeof(Tuple<>)
|| genericType == typeof(Map<,>))
{
var rt = new List<Type>();
for (var i = 0; i < genericTypeArgs.Length; i++)
{
var depTypes = GetDistributedTypes(genericTypeArgs[i]);
foreach (var depType in depTypes)
if (!rt.Contains(depType))
rt.Add(depType);
}
return rt.ToArray();
}
}
else if (Codec.ImplementsInterface(type, typeof(IRecord))
|| Codec.ImplementsInterface(type, typeof(IResource)))
{
return new Type[] { type };
}
return new Type[0];
}
public static TypeTemplate[] GetDependencies(TypeTemplate template) public static TypeTemplate[] GetDependencies(TypeTemplate template)
@ -205,13 +237,20 @@ public class TypeTemplate
// functions // functions
foreach (var f in tmp.functions) foreach (var f in tmp.functions)
{ {
var frtt = Warehouse.GetTemplateByType(GetElementType(f.MethodInfo.ReturnType)); var functionReturnTypes = GetDistributedTypes(f.MethodInfo.ReturnType);
if (frtt != null) //.Select(x => Warehouse.GetTemplateByType(x))
//.Where(x => x != null && !bag.Contains(x))
foreach (var functionReturnType in functionReturnTypes)
{ {
if (!bag.Contains(frtt)) var functionReturnTemplate = Warehouse.GetTemplateByType(functionReturnType);
if (functionReturnTemplate != null)
{ {
list.Add(frtt); if (!bag.Contains(functionReturnTemplate))
getDependenciesFunc(frtt, bag); {
list.Add(functionReturnTemplate);
getDependenciesFunc(functionReturnTemplate, bag);
}
} }
} }
@ -219,24 +258,11 @@ public class TypeTemplate
for (var i = 0; i < args.Length - 1; i++) for (var i = 0; i < args.Length - 1; i++)
{ {
var fpt = Warehouse.GetTemplateByType(GetElementType(args[i].ParameterType)); var fpTypes = GetDistributedTypes(args[i].ParameterType);
if (fpt != null)
{
if (!bag.Contains(fpt))
{
bag.Add(fpt);
getDependenciesFunc(fpt, bag);
}
}
}
// skip DistributedConnection argument foreach (var fpType in fpTypes)
if (args.Length > 0)
{
var last = args.Last();
if (last.ParameterType != typeof(DistributedConnection))
{ {
var fpt = Warehouse.GetTemplateByType(GetElementType(last.ParameterType)); var fpt = Warehouse.GetTemplateByType(fpType);
if (fpt != null) if (fpt != null)
{ {
if (!bag.Contains(fpt)) if (!bag.Contains(fpt))
@ -248,18 +274,47 @@ public class TypeTemplate
} }
} }
// skip DistributedConnection argument
if (args.Length > 0)
{
var last = args.Last();
if (last.ParameterType != typeof(DistributedConnection))
{
var fpTypes = GetDistributedTypes(last.ParameterType);
foreach (var fpType in fpTypes)
{
var fpt = Warehouse.GetTemplateByType(fpType);
if (fpt != null)
{
if (!bag.Contains(fpt))
{
bag.Add(fpt);
getDependenciesFunc(fpt, bag);
}
}
}
}
}
} }
// properties // properties
foreach (var p in tmp.properties) foreach (var p in tmp.properties)
{ {
var pt = Warehouse.GetTemplateByType(GetElementType(p.PropertyInfo.PropertyType)); var propertyTypes = GetDistributedTypes(p.PropertyInfo.PropertyType);
if (pt != null)
foreach (var propertyType in propertyTypes)
{ {
if (!bag.Contains(pt)) var propertyTemplate = Warehouse.GetTemplateByType(propertyType);
if (propertyTemplate != null)
{ {
bag.Add(pt); if (!bag.Contains(propertyTemplate))
getDependenciesFunc(pt, bag); {
bag.Add(propertyTemplate);
getDependenciesFunc(propertyTemplate, bag);
}
} }
} }
} }
@ -267,14 +322,19 @@ public class TypeTemplate
// events // events
foreach (var e in tmp.events) foreach (var e in tmp.events)
{ {
var et = Warehouse.GetTemplateByType(GetElementType(e.EventInfo.EventHandlerType.GenericTypeArguments[0])); var eventTypes = GetDistributedTypes(e.EventInfo.EventHandlerType.GenericTypeArguments[0]);
if (et != null) foreach (var eventType in eventTypes)
{ {
if (!bag.Contains(et)) var eventTemplate = Warehouse.GetTemplateByType(eventType);
if (eventTemplate != null)
{ {
bag.Add(et); if (!bag.Contains(eventTemplate))
getDependenciesFunc(et, bag); {
bag.Add(eventTemplate);
getDependenciesFunc(eventTemplate, bag);
}
} }
} }
} }
@ -707,7 +767,7 @@ public class TypeTemplate
} }
public static bool HasParent (Type type) public static bool HasParent(Type type)
{ {
var parent = type.BaseType; var parent = type.BaseType;
@ -887,7 +947,7 @@ public class TypeTemplate
offset += dts; offset += dts;
(dts, var value) = Codec.Parse(data, offset, null); (dts, var value) = Codec.Parse(data, offset, null, null);
offset += dts; offset += dts;

View File

@ -51,33 +51,6 @@ namespace Test
static async Task Main(string[] args) static async Task Main(string[] args)
{ {
//foreach (var a in ma)
// Console.WriteLine(a);
//var route = "users/{id:int:min(1)}/{name:string}.jpg";
//var route = "users/{id}/{name}.jpg";
//var rr = getRouteRegex(route);
// var m = rr.Match("users/222/fun.jpg");
// Console.WriteLine(m.Value);
// var escaped = Regex.Escape(route);
// var replace = Regex.Replace(route, @"\{([^}]*)\}", @"\{([^}]*)\}");
// var ss = route.Split('{', '}');
//var regex = "users/\"
//Regex regex = new Regex(@"\(([^()]+)\)*");
//foreach (Match match in regex.Matches("You id is (1) and your number is (0000000000)"))
//{
// Console.WriteLine(match.Value);
//}
// Create stores to keep objects. // Create stores to keep objects.
var system = await Warehouse.Put("mem", new MemoryStore()); var system = await Warehouse.Put("mem", new MemoryStore());
var server = await Warehouse.Put("mem/server", new DistributedServer()); var server = await Warehouse.Put("mem/server", new DistributedServer());