mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2025-05-06 19:42:58 +00:00
WeakRef
This commit is contained in:
parent
8d06fd05ad
commit
5e87ea5247
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard1.5</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<Authors>Ahmed Kh. Zamil</Authors>
|
<Authors>Ahmed Kh. Zamil</Authors>
|
||||||
<Company>Esiur</Company>
|
<Company>Esiur</Company>
|
||||||
<Product>Esiur MongoDB Store</Product>
|
<Product>Esiur MongoDB Store</Product>
|
||||||
@ -11,12 +11,12 @@
|
|||||||
<PackageProjectUrl>http://www.esiur.com</PackageProjectUrl>
|
<PackageProjectUrl>http://www.esiur.com</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://github.com/esiur/esiur-dotnet/</RepositoryUrl>
|
<RepositoryUrl>https://github.com/esiur/esiur-dotnet/</RepositoryUrl>
|
||||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
<Version>1.2.5</Version>
|
<Version>1.2.8</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="MongoDB.Bson" Version="2.4.4" />
|
<PackageReference Include="MongoDB.Bson" Version="2.9.1" />
|
||||||
<PackageReference Include="MongoDB.Driver" Version="2.4.4" />
|
<PackageReference Include="MongoDB.Driver" Version="2.9.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -23,15 +23,22 @@ namespace Esiur.Stores.MongoDB
|
|||||||
MongoClient client;
|
MongoClient client;
|
||||||
IMongoDatabase database;
|
IMongoDatabase database;
|
||||||
IMongoCollection<BsonDocument> resourcesCollection;
|
IMongoCollection<BsonDocument> resourcesCollection;
|
||||||
|
|
||||||
|
//List<IResource> storeParents = new List<IResource>();
|
||||||
|
//List<IResource> storeChildren = new List<IResource>();
|
||||||
|
|
||||||
//string collectionName;
|
//string collectionName;
|
||||||
//string dbName;
|
//string dbName;
|
||||||
|
|
||||||
Dictionary<string, IResource> resources = new Dictionary<string, IResource>();
|
Dictionary<string, WeakReference> resources = new Dictionary<string, WeakReference>();
|
||||||
|
|
||||||
|
|
||||||
public int Count
|
public long Count
|
||||||
{
|
{
|
||||||
get { return resources.Count; }
|
get
|
||||||
|
{
|
||||||
|
return resourcesCollection.CountDocuments(x => true);
|
||||||
|
}// resources.Count; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Destroy()
|
public void Destroy()
|
||||||
@ -77,21 +84,35 @@ namespace Esiur.Stores.MongoDB
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncReply<IResource> Fetch(string id)
|
AsyncReply<T> Fetch<T>(string id) where T : IResource
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (resources.ContainsKey(id) && resources[id].IsAlive)
|
||||||
|
{
|
||||||
|
if (resources[id].Target is T)
|
||||||
|
return new AsyncReply<T>((T)resources[id].Target);
|
||||||
|
else
|
||||||
|
return new AsyncReply<T>(default(T)); ;
|
||||||
|
}
|
||||||
|
|
||||||
var filter = Builders<BsonDocument>.Filter.Eq("_id", new BsonObjectId(new ObjectId(id)));
|
var filter = Builders<BsonDocument>.Filter.Eq("_id", new BsonObjectId(new ObjectId(id)));
|
||||||
var list = resourcesCollection.Find(filter).ToList();
|
var list = resourcesCollection.Find(filter).ToList();
|
||||||
if (list.Count == 0)
|
if (list.Count == 0)
|
||||||
return new AsyncReply<IResource>(null);
|
return new AsyncReply<T>(default(T));
|
||||||
var document = list[0];
|
var document = list[0];
|
||||||
|
|
||||||
var type = Type.GetType(document["classname"].AsString);
|
var type = Type.GetType(document["classname"].AsString);
|
||||||
|
|
||||||
if (type == null)
|
if (type == null)
|
||||||
return new AsyncReply<IResource>(null);
|
return new AsyncReply<T>(default(T));
|
||||||
|
|
||||||
IResource resource = (IResource)Activator.CreateInstance(ResourceProxy.GetProxy(type));
|
IResource resource = (IResource)Activator.CreateInstance(ResourceProxy.GetProxy(type));
|
||||||
resources.Add(document["_id"].AsObjectId.ToString(), resource);
|
|
||||||
|
//var iid = document["_id"].AsObjectId.ToString();
|
||||||
|
if (resources.ContainsKey(id))
|
||||||
|
resources[id] = new WeakReference(resource);
|
||||||
|
else
|
||||||
|
resources.Add(id, new WeakReference(resource));
|
||||||
|
|
||||||
Warehouse.Put(resource, document["name"].AsString, this);
|
Warehouse.Put(resource, document["name"].AsString, this);
|
||||||
|
|
||||||
@ -100,12 +121,14 @@ namespace Esiur.Stores.MongoDB
|
|||||||
var children = document["children"].AsBsonArray;
|
var children = document["children"].AsBsonArray;
|
||||||
//var managers = document["managers"].AsBsonArray;
|
//var managers = document["managers"].AsBsonArray;
|
||||||
|
|
||||||
var attributes = Parse(document["attributes"]).Then(x=> {
|
var attributes = Parse(document["attributes"]).Then(x =>
|
||||||
|
{
|
||||||
resource.Instance.SetAttributes(x as Structure);
|
resource.Instance.SetAttributes(x as Structure);
|
||||||
});
|
});
|
||||||
|
|
||||||
var bag = new AsyncBag<object>();
|
var bag = new AsyncBag<object>();
|
||||||
|
|
||||||
|
/*
|
||||||
foreach (var p in parents)
|
foreach (var p in parents)
|
||||||
{
|
{
|
||||||
var ap = Warehouse.Get(p.AsString);
|
var ap = Warehouse.Get(p.AsString);
|
||||||
@ -128,6 +151,10 @@ namespace Esiur.Stores.MongoDB
|
|||||||
resource.Instance.Children.Add(x);
|
resource.Instance.Children.Add(x);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
resource.Instance.Attributes.Add("children", children.Select(x => x.AsString).ToArray());
|
||||||
|
resource.Instance.Attributes.Add("parents", parents.Select(x => x.AsString).ToArray());
|
||||||
|
|
||||||
// Apply store managers
|
// Apply store managers
|
||||||
foreach (var m in this.Instance.Managers)
|
foreach (var m in this.Instance.Managers)
|
||||||
@ -154,27 +181,34 @@ namespace Esiur.Stores.MongoDB
|
|||||||
|
|
||||||
foreach (var v in values)
|
foreach (var v in values)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
var valueInfo = v.Value as BsonDocument;
|
var valueInfo = v.Value as BsonDocument;
|
||||||
|
|
||||||
var av = Parse(valueInfo["value"]);
|
var av = Parse(valueInfo["value"]);
|
||||||
bag.Add(av);
|
|
||||||
av.Then((x) =>
|
av.Then((x) =>
|
||||||
{
|
{
|
||||||
resource.Instance.LoadProperty(v.Name, (ulong)valueInfo["age"].AsInt64, valueInfo["modification"].ToUniversalTime(), x);
|
resource.Instance.LoadProperty(v.Name,
|
||||||
|
(ulong)valueInfo["age"].AsInt64,
|
||||||
|
valueInfo["modification"].ToUniversalTime(),
|
||||||
|
x);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
bag.Add(av);
|
||||||
}
|
}
|
||||||
|
|
||||||
bag.Seal();
|
var rt = new AsyncReply<T>();
|
||||||
|
|
||||||
var rt = new AsyncReply<IResource>();
|
|
||||||
|
|
||||||
bag.Then((x) =>
|
bag.Then((x) =>
|
||||||
{
|
{
|
||||||
rt.Trigger(resource);
|
if (resource is T)
|
||||||
|
rt.Trigger(resource);
|
||||||
|
else
|
||||||
|
rt.Trigger(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
bag.Seal();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return rt;
|
return rt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,16 +276,22 @@ namespace Esiur.Stores.MongoDB
|
|||||||
if (p[0] == "id")
|
if (p[0] == "id")
|
||||||
{
|
{
|
||||||
// load from Id
|
// load from Id
|
||||||
|
return Fetch<IResource>(p[1]);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
if (resources.ContainsKey(p[1]))
|
if (resources.ContainsKey(p[1]))
|
||||||
return new AsyncReply<IResource>(resources[p[1]]);
|
return new AsyncReply<IResource>(resources[p[1]]);
|
||||||
else
|
else
|
||||||
return Fetch(p[1]);
|
return Fetch(p[1]);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
return new AsyncReply<IResource>(null);
|
return new AsyncReply<IResource>(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public string Link(IResource resource)
|
public string Link(IResource resource)
|
||||||
{
|
{
|
||||||
return this.Instance.Name + "/id/" + (string)resource.Instance.Attributes["objectId"];
|
return this.Instance.Name + "/id/" + (string)resource.Instance.Attributes["objectId"];
|
||||||
@ -259,11 +299,17 @@ namespace Esiur.Stores.MongoDB
|
|||||||
|
|
||||||
public bool Put(IResource resource)
|
public bool Put(IResource resource)
|
||||||
{
|
{
|
||||||
|
PutResource(resource).Wait();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<bool> PutResource(IResource resource)
|
||||||
|
{
|
||||||
var attrs = resource.Instance.GetAttributes();
|
var attrs = resource.Instance.GetAttributes();
|
||||||
|
|
||||||
foreach (var kv in resources)
|
foreach (var kv in resources)
|
||||||
if (kv.Value == resource)
|
if (kv.Value.Target == resource)
|
||||||
{
|
{
|
||||||
resource.Instance.Attributes.Add("objectId", kv.Key);
|
resource.Instance.Attributes.Add("objectId", kv.Key);
|
||||||
return true;
|
return true;
|
||||||
@ -290,18 +336,41 @@ namespace Esiur.Stores.MongoDB
|
|||||||
|
|
||||||
var template = resource.Instance.Template;
|
var template = resource.Instance.Template;
|
||||||
|
|
||||||
foreach (IResource c in resource.Instance.Children)
|
// setup attributes
|
||||||
children.Add(c.Instance.Link);
|
resource.Instance.Attributes["children"] = new string[0];
|
||||||
|
resource.Instance.Attributes["parents"] = new string[] { this.Instance.Link };
|
||||||
|
|
||||||
foreach (IResource p in resource.Instance.Parents)
|
// copy old children (in case we are moving a resource from a store to another.
|
||||||
parents.Add(p.Instance.Link);
|
if (resource.Instance.Store != this)
|
||||||
|
{
|
||||||
|
var resourceChildren = await resource.Instance.Children<IResource>();
|
||||||
|
|
||||||
|
if (resourceChildren != null)
|
||||||
|
foreach (IResource c in resourceChildren)
|
||||||
|
children.Add(c.Instance.Link);
|
||||||
|
|
||||||
|
var resourceParents = await resource.Instance.Parents<IResource>();
|
||||||
|
|
||||||
|
if (resourceParents == null)
|
||||||
|
{
|
||||||
|
parents.Add(this.Instance.Link);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (IResource p in resourceParents)
|
||||||
|
parents.Add(p.Instance.Link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// just add self
|
||||||
|
parents.Add(this.Instance.Link);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var attrsDoc = ComposeStructure(attrs);
|
var attrsDoc = ComposeStructure(attrs);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var values = new BsonDocument();
|
var values = new BsonDocument();
|
||||||
|
|
||||||
foreach (var pt in template.Properties)
|
foreach (var pt in template.Properties)
|
||||||
@ -314,10 +383,11 @@ namespace Esiur.Stores.MongoDB
|
|||||||
{ "value", Compose(rt) } });
|
{ "value", Compose(rt) } });
|
||||||
}
|
}
|
||||||
|
|
||||||
// var filter = Builders<BsonDocument>.Filter.Eq("_id", document["_id"]);
|
|
||||||
// var update = Builders<BsonDocument>.Update
|
// var filter = Builders<BsonDocument>.Filter.Eq("_id", document["_id"]);
|
||||||
// .Set("values", values);
|
// var update = Builders<BsonDocument>.Update
|
||||||
// col.UpdateOne(filter, update);
|
// .Set("values", values);
|
||||||
|
// col.UpdateOne(filter, update);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -340,6 +410,7 @@ namespace Esiur.Stores.MongoDB
|
|||||||
|
|
||||||
//resource.Instance.Attributes["objectId"] = document["_id"].ToString();
|
//resource.Instance.Attributes["objectId"] = document["_id"].ToString();
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -454,8 +525,10 @@ namespace Esiur.Stores.MongoDB
|
|||||||
|
|
||||||
resourcesCollection = this.database.GetCollection<BsonDocument>(collectionName);
|
resourcesCollection = this.database.GetCollection<BsonDocument>(collectionName);
|
||||||
|
|
||||||
// return new AsyncReply<bool>(true);
|
// return new AsyncReply<bool>(true);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
var filter = new BsonDocument();
|
var filter = new BsonDocument();
|
||||||
|
|
||||||
var list = resourcesCollection.Find(filter).ToList();
|
var list = resourcesCollection.Find(filter).ToList();
|
||||||
@ -476,15 +549,24 @@ namespace Esiur.Stores.MongoDB
|
|||||||
|
|
||||||
var rt = new AsyncReply<bool>();
|
var rt = new AsyncReply<bool>();
|
||||||
|
|
||||||
bag.Then((x) => { rt.Trigger(true); });
|
bag.Then((x) => {
|
||||||
|
|
||||||
|
// storeChildren.AddRange(x);
|
||||||
|
rt.Trigger(true);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
return rt;
|
return rt;
|
||||||
|
*/
|
||||||
|
|
||||||
|
return new AsyncReply<bool>(true);
|
||||||
}
|
}
|
||||||
else if (trigger == ResourceTrigger.Terminate)
|
else if (trigger == ResourceTrigger.Terminate)
|
||||||
{
|
{
|
||||||
// save all resources
|
// save all resources
|
||||||
foreach (var resource in resources.Values)
|
foreach (var resource in resources.Values)
|
||||||
SaveResource(resource);
|
if (resource.IsAlive)
|
||||||
|
SaveResource(resource.Target as IResource);
|
||||||
|
|
||||||
return new AsyncReply<bool>(true);
|
return new AsyncReply<bool>(true);
|
||||||
}
|
}
|
||||||
@ -501,11 +583,13 @@ namespace Esiur.Stores.MongoDB
|
|||||||
var children = new BsonArray();
|
var children = new BsonArray();
|
||||||
var template = resource.Instance.Template;
|
var template = resource.Instance.Template;
|
||||||
|
|
||||||
foreach (IResource c in resource.Instance.Children)
|
//foreach (IResource c in resource.Instance.Children)
|
||||||
children.Add(c.Instance.Link);
|
// children.Add(c.Instance.Link);
|
||||||
|
|
||||||
foreach (IResource p in resource.Instance.Parents)
|
var plist = resource.Instance.Attributes["parents"] as string[];
|
||||||
parents.Add(p.Instance.Link);
|
|
||||||
|
foreach (var link in plist)// Parents)
|
||||||
|
parents.Add(link);
|
||||||
|
|
||||||
|
|
||||||
var values = new BsonDocument();
|
var values = new BsonDocument();
|
||||||
@ -536,7 +620,7 @@ namespace Esiur.Stores.MongoDB
|
|||||||
{
|
{
|
||||||
{ "parents", parents },
|
{ "parents", parents },
|
||||||
{ "children", children },
|
{ "children", children },
|
||||||
{"attributes", attrsDoc },
|
{ "attributes", attrsDoc },
|
||||||
{ "classname", type.FullName + "," + type.GetTypeInfo().Assembly.GetName().Name },
|
{ "classname", type.FullName + "," + type.GetTypeInfo().Assembly.GetName().Name },
|
||||||
{ "name", resource.Instance.Name },
|
{ "name", resource.Instance.Name },
|
||||||
{ "_id", new BsonObjectId(new ObjectId(resource.Instance.Attributes["objectId"].ToString())) },
|
{ "_id", new BsonObjectId(new ObjectId(resource.Instance.Attributes["objectId"].ToString())) },
|
||||||
@ -576,7 +660,7 @@ namespace Esiur.Stores.MongoDB
|
|||||||
|
|
||||||
var bag = new AsyncBag<object>();
|
var bag = new AsyncBag<object>();
|
||||||
|
|
||||||
foreach(var v in values)
|
foreach (var v in values)
|
||||||
bag.Add(Parse(v["value"]));
|
bag.Add(Parse(v["value"]));
|
||||||
|
|
||||||
bag.Seal();
|
bag.Seal();
|
||||||
@ -584,7 +668,7 @@ namespace Esiur.Stores.MongoDB
|
|||||||
bag.Then((results) =>
|
bag.Then((results) =>
|
||||||
{
|
{
|
||||||
var list = new List<PropertyValue>();
|
var list = new List<PropertyValue>();
|
||||||
for(var i = 0; i < results.Length; i++)
|
for (var i = 0; i < results.Length; i++)
|
||||||
list.Add(new PropertyValue(results[i], (ulong)values[i]["age"].AsInt64, values[i]["date"].ToUniversalTime()));
|
list.Add(new PropertyValue(results[i], (ulong)values[i]["age"].AsInt64, values[i]["date"].ToUniversalTime()));
|
||||||
|
|
||||||
reply.Trigger(list.ToArray());
|
reply.Trigger(list.ToArray());
|
||||||
@ -701,5 +785,130 @@ namespace Esiur.Stores.MongoDB
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public AsyncBag<T> Children<T>(IResource resource, string name) where T : IResource
|
||||||
|
{
|
||||||
|
|
||||||
|
if (resource == this)
|
||||||
|
{
|
||||||
|
IFindFluent<BsonDocument, BsonDocument> match;
|
||||||
|
|
||||||
|
if (name == null)
|
||||||
|
match = resourcesCollection.Find(x => (x["parents"] as BsonArray).Contains(this.Instance.Name));
|
||||||
|
else
|
||||||
|
match = resourcesCollection.Find(x => (x["parents"] as BsonArray).Contains(this.Instance.Name) && x["name"] == name);
|
||||||
|
|
||||||
|
|
||||||
|
var st = match.ToList().Select(x => x["_id"].ToString()).ToArray();
|
||||||
|
|
||||||
|
|
||||||
|
var bag = new AsyncBag<T>();
|
||||||
|
|
||||||
|
foreach (var s in st)
|
||||||
|
{
|
||||||
|
var r = Fetch<T>(s);
|
||||||
|
if (r.Ready && r.Result == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bag.Add(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
bag.Seal();
|
||||||
|
return bag;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var children = (string[])resource.Instance.Attributes["children"];
|
||||||
|
|
||||||
|
if (children == null)
|
||||||
|
{
|
||||||
|
return new AsyncBag<T>(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
var rt = new AsyncBag<T>();
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var child in children)
|
||||||
|
{
|
||||||
|
var r = Warehouse.Get(child);
|
||||||
|
if (r is IAsyncReply<T>)
|
||||||
|
rt.Add((IAsyncReply<T>)r);
|
||||||
|
}
|
||||||
|
|
||||||
|
rt.Seal();
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncBag<T> Parents<T>(IResource resource, string name) where T : IResource
|
||||||
|
{
|
||||||
|
Console.WriteLine("Parents start");
|
||||||
|
|
||||||
|
if (resource == this)
|
||||||
|
{
|
||||||
|
return new AsyncBag<T>(null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("Parents 1");
|
||||||
|
|
||||||
|
var parents = (string[])resource.Instance.Attributes["parents"];
|
||||||
|
|
||||||
|
if (parents == null)
|
||||||
|
{
|
||||||
|
return new AsyncBag<T>(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
var rt = new AsyncBag<T>();
|
||||||
|
|
||||||
|
Console.WriteLine("Parents 2");
|
||||||
|
|
||||||
|
foreach (var parent in parents)
|
||||||
|
{
|
||||||
|
var r = Warehouse.Get(parent);
|
||||||
|
if (r is IAsyncReply<T>)
|
||||||
|
rt.Add((IAsyncReply<T>)r);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"Parents 3 {parents.Length}");
|
||||||
|
|
||||||
|
rt.Seal();
|
||||||
|
|
||||||
|
Console.WriteLine("Parents end");
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public AsyncReply<bool> AddChild(IResource resource, IResource child)
|
||||||
|
{
|
||||||
|
var list = (string[])resource.Instance.Attributes["children"];
|
||||||
|
resource.Instance.Attributes["children"] = list.Concat(new string[] { child.Instance.Link }).ToArray();
|
||||||
|
|
||||||
|
SaveResource(resource);
|
||||||
|
|
||||||
|
return new AsyncReply<bool>(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncReply<bool> RemoveChild(IResource parent, IResource child)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncReply<bool> AddParent(IResource resource, IResource parent)
|
||||||
|
{
|
||||||
|
var list = (string[])resource.Instance.Attributes["parents"];
|
||||||
|
resource.Instance.Attributes["parents"] = list.Concat(new string[] { parent.Instance.Link }).ToArray();
|
||||||
|
|
||||||
|
SaveResource(resource);
|
||||||
|
|
||||||
|
return new AsyncReply<bool>(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncReply<bool> RemoveParent(IResource child, IResource parent)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
Esiur.Stores.MySql/Esiur.Stores.MySql.csproj
Normal file
15
Esiur.Stores.MySql/Esiur.Stores.MySql.csproj
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MySql.Data" Version="8.0.17" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Esiur\Esiur.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
718
Esiur.Stores.MySql/MySqlStore.cs
Normal file
718
Esiur.Stores.MySql/MySqlStore.cs
Normal file
@ -0,0 +1,718 @@
|
|||||||
|
using Esiur.Resource;
|
||||||
|
using System;
|
||||||
|
using Esiur.Core;
|
||||||
|
using Esiur.Data;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Esiur.Resource.Template;
|
||||||
|
using System.Linq;
|
||||||
|
using Esiur.Security.Permissions;
|
||||||
|
using Esiur.Proxy;
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
|
|
||||||
|
namespace Esiur.Stores.MySql
|
||||||
|
{
|
||||||
|
public class MySqlStore : IStore
|
||||||
|
{
|
||||||
|
public Instance Instance { get; set; }
|
||||||
|
|
||||||
|
public event DestroyedEvent OnDestroy;
|
||||||
|
|
||||||
|
string connectionString;
|
||||||
|
|
||||||
|
|
||||||
|
Dictionary<string, IResource> resources = new Dictionary<string, IResource>();
|
||||||
|
|
||||||
|
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get { return resources.Count; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Destroy()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool Record(IResource resource, string propertyName, object value, ulong age, DateTime date)
|
||||||
|
{
|
||||||
|
var objectId = resource.Instance.Attributes["objectId"].ToString();
|
||||||
|
//var bsonObjectId = new BsonObjectId(new ObjectId(objectId));
|
||||||
|
|
||||||
|
var record = this.database.GetCollection<BsonDocument>("record_" + objectId);
|
||||||
|
|
||||||
|
record.InsertOne(new BsonDocument()
|
||||||
|
{
|
||||||
|
{"property", propertyName}, {"age", BsonValue.Create(age) }, {"date", date}, {"value", Compose(value) }
|
||||||
|
});
|
||||||
|
|
||||||
|
//var col = this.database.GetCollection<BsonDocument>(collectionName);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var filter = Builders<BsonDocument>.Filter.Eq("_id", new BsonObjectId(new ObjectId(objectId)));
|
||||||
|
var update = Builders<BsonDocument>.Update
|
||||||
|
.Set("values." + propertyName, new BsonDocument { { "age", BsonValue.Create(age) },
|
||||||
|
{ "modification", date },
|
||||||
|
{ "value", Compose(value) } });
|
||||||
|
resourcesCollection.UpdateOne(filter, update);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(IResource resource)
|
||||||
|
{
|
||||||
|
var objectId = resource.Instance.Attributes["objectId"].ToString();
|
||||||
|
var filter = Builders<BsonDocument>.Filter.Eq("_id", new BsonObjectId(new ObjectId(objectId)));
|
||||||
|
|
||||||
|
this.database.DropCollection("record_" + objectId);
|
||||||
|
resourcesCollection.DeleteOne(filter);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncReply<IResource> Fetch(string id)
|
||||||
|
{
|
||||||
|
|
||||||
|
MySqlHelper.
|
||||||
|
|
||||||
|
var filter = Builders<BsonDocument>.Filter.Eq("_id", new BsonObjectId(new ObjectId(id)));
|
||||||
|
var list = resourcesCollection.Find(filter).ToList();
|
||||||
|
if (list.Count == 0)
|
||||||
|
return new AsyncReply<IResource>(null);
|
||||||
|
var document = list[0];
|
||||||
|
|
||||||
|
var type = Type.GetType(document["classname"].AsString);
|
||||||
|
|
||||||
|
if (type == null)
|
||||||
|
return new AsyncReply<IResource>(null);
|
||||||
|
|
||||||
|
IResource resource = (IResource)Activator.CreateInstance(ResourceProxy.GetProxy(type));
|
||||||
|
resources.Add(document["_id"].AsObjectId.ToString(), resource);
|
||||||
|
|
||||||
|
Warehouse.Put(resource, document["name"].AsString, this);
|
||||||
|
|
||||||
|
|
||||||
|
var parents = document["parents"].AsBsonArray;
|
||||||
|
var children = document["children"].AsBsonArray;
|
||||||
|
//var managers = document["managers"].AsBsonArray;
|
||||||
|
|
||||||
|
var attributes = Parse(document["attributes"]).Then(x => {
|
||||||
|
resource.Instance.SetAttributes(x as Structure);
|
||||||
|
});
|
||||||
|
|
||||||
|
var bag = new AsyncBag<object>();
|
||||||
|
|
||||||
|
foreach (var p in parents)
|
||||||
|
{
|
||||||
|
var ap = Warehouse.Get(p.AsString);
|
||||||
|
bag.Add(ap);
|
||||||
|
ap.Then((x) =>
|
||||||
|
{
|
||||||
|
if (!resource.Instance.Parents.Contains(x))
|
||||||
|
resource.Instance.Parents.Add(x);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var c in children)
|
||||||
|
{
|
||||||
|
|
||||||
|
var ac = Warehouse.Get(c.AsString);
|
||||||
|
bag.Add(ac);
|
||||||
|
ac.Then((x) =>
|
||||||
|
{
|
||||||
|
if (!resource.Instance.Children.Contains(x))
|
||||||
|
resource.Instance.Children.Add(x);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply store managers
|
||||||
|
foreach (var m in this.Instance.Managers)
|
||||||
|
resource.Instance.Managers.Add(m);
|
||||||
|
|
||||||
|
/*
|
||||||
|
// load managers
|
||||||
|
foreach(var m in managers)
|
||||||
|
{
|
||||||
|
IPermissionsManager pm = (IPermissionsManager)Activator.CreateInstance(Type.GetType(m["classname"].AsString));
|
||||||
|
var sr = Parse(m["settings"]);
|
||||||
|
bag.Add(sr);
|
||||||
|
sr.Then((x) =>
|
||||||
|
{
|
||||||
|
pm.Initialize((Structure)x, resource);
|
||||||
|
resource.Instance.Managers.Add(pm);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Load values
|
||||||
|
var values = document["values"].AsBsonDocument;
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var v in values)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
var valueInfo = v.Value as BsonDocument;
|
||||||
|
|
||||||
|
var av = Parse(valueInfo["value"]);
|
||||||
|
bag.Add(av);
|
||||||
|
av.Then((x) =>
|
||||||
|
{
|
||||||
|
resource.Instance.LoadProperty(v.Name, (ulong)valueInfo["age"].AsInt64, valueInfo["modification"].ToUniversalTime(), x);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bag.Seal();
|
||||||
|
|
||||||
|
var rt = new AsyncReply<IResource>();
|
||||||
|
|
||||||
|
bag.Then((x) =>
|
||||||
|
{
|
||||||
|
rt.Trigger(resource);
|
||||||
|
});
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
|
||||||
|
IAsyncReply<object> Parse(BsonValue value)
|
||||||
|
{
|
||||||
|
if (value.BsonType == BsonType.Document)
|
||||||
|
{
|
||||||
|
var doc = value.AsBsonDocument;
|
||||||
|
if (doc["type"] == 0)
|
||||||
|
{
|
||||||
|
return Warehouse.Get(doc["link"].AsString);
|
||||||
|
} // structure
|
||||||
|
else if (doc["type"] == 1)
|
||||||
|
{
|
||||||
|
var bag = new AsyncBag<object>();
|
||||||
|
var rt = new AsyncReply<Structure>();
|
||||||
|
|
||||||
|
var bs = (BsonDocument)doc["values"].AsBsonDocument;
|
||||||
|
var s = new Structure();
|
||||||
|
|
||||||
|
foreach (var v in bs)
|
||||||
|
bag.Add(Parse(v.Value));
|
||||||
|
|
||||||
|
bag.Seal();
|
||||||
|
bag.Then((x) =>
|
||||||
|
{
|
||||||
|
for (var i = 0; i < x.Length; i++)
|
||||||
|
s[bs.GetElement(i).Name] = x[i];
|
||||||
|
|
||||||
|
rt.Trigger(s);
|
||||||
|
});
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return new AsyncReply<object>(null);
|
||||||
|
}
|
||||||
|
else if (value.BsonType == BsonType.Array)
|
||||||
|
{
|
||||||
|
var array = value.AsBsonArray;
|
||||||
|
var bag = new AsyncBag<object>();
|
||||||
|
|
||||||
|
foreach (var v in array)
|
||||||
|
bag.Add(Parse(v));
|
||||||
|
|
||||||
|
bag.Seal();
|
||||||
|
|
||||||
|
return bag;
|
||||||
|
}
|
||||||
|
else if (value.BsonType == BsonType.DateTime)
|
||||||
|
{
|
||||||
|
return new AsyncReply<object>(value.ToUniversalTime());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
return new AsyncReply<object>(value.RawValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncReply<IResource> Get(string path)
|
||||||
|
{
|
||||||
|
var p = path.Split('/');
|
||||||
|
if (p.Length == 2)
|
||||||
|
if (p[0] == "id")
|
||||||
|
{
|
||||||
|
// load from Id
|
||||||
|
|
||||||
|
if (resources.ContainsKey(p[1]))
|
||||||
|
return new AsyncReply<IResource>(resources[p[1]]);
|
||||||
|
else
|
||||||
|
return Fetch(p[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AsyncReply<IResource>(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Link(IResource resource)
|
||||||
|
{
|
||||||
|
return this.Instance.Name + "/id/" + (string)resource.Instance.Attributes["objectId"];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string MakeTable(Type type)
|
||||||
|
{
|
||||||
|
var props = type.GetTypeInfo().GetProperties();
|
||||||
|
|
||||||
|
|
||||||
|
foreach(var p in props)
|
||||||
|
{
|
||||||
|
var rp = p.GetCustomAttribute<ResourceProperty>();
|
||||||
|
if (rp == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Put(IResource resource)
|
||||||
|
{
|
||||||
|
|
||||||
|
var attrs = resource.Instance.GetAttributes();
|
||||||
|
|
||||||
|
foreach (var kv in resources)
|
||||||
|
if (kv.Value == resource)
|
||||||
|
{
|
||||||
|
resource.Instance.Attributes.Add("objectId", kv.Key);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var type = ResourceProxy.GetBaseType(resource);
|
||||||
|
|
||||||
|
// insert the document
|
||||||
|
var document = new BsonDocument
|
||||||
|
{
|
||||||
|
{ "classname", type.FullName + "," + type.GetTypeInfo().Assembly.GetName().Name },
|
||||||
|
{ "name", resource.Instance.Name },
|
||||||
|
};
|
||||||
|
|
||||||
|
resourcesCollection.InsertOne(document);
|
||||||
|
resource.Instance.Attributes["objectId"] = document["_id"].ToString();
|
||||||
|
|
||||||
|
|
||||||
|
// now update the document
|
||||||
|
// * insert first to get the object id, update values, attributes, children and parents after in case the same resource has a property references self
|
||||||
|
|
||||||
|
var parents = new BsonArray();
|
||||||
|
var children = new BsonArray();
|
||||||
|
|
||||||
|
var template = resource.Instance.Template;
|
||||||
|
|
||||||
|
foreach (IResource c in resource.Instance.Children)
|
||||||
|
children.Add(c.Instance.Link);
|
||||||
|
|
||||||
|
foreach (IResource p in resource.Instance.Parents)
|
||||||
|
parents.Add(p.Instance.Link);
|
||||||
|
|
||||||
|
|
||||||
|
var attrsDoc = ComposeStructure(attrs);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var values = new BsonDocument();
|
||||||
|
|
||||||
|
foreach (var pt in template.Properties)
|
||||||
|
{
|
||||||
|
var rt = pt.Info.GetValue(resource, null);
|
||||||
|
|
||||||
|
values.Add(pt.Name,
|
||||||
|
new BsonDocument { { "age", BsonValue.Create(resource.Instance.GetAge(pt.Index)) },
|
||||||
|
{ "modification", resource.Instance.GetModificationDate(pt.Index) },
|
||||||
|
{ "value", Compose(rt) } });
|
||||||
|
}
|
||||||
|
|
||||||
|
// var filter = Builders<BsonDocument>.Filter.Eq("_id", document["_id"]);
|
||||||
|
// var update = Builders<BsonDocument>.Update
|
||||||
|
// .Set("values", values);
|
||||||
|
// col.UpdateOne(filter, update);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
var document = new BsonDocument
|
||||||
|
{
|
||||||
|
{ "parents", parents },
|
||||||
|
{ "children", children },
|
||||||
|
{ "attributes", attrsDoc },
|
||||||
|
{ "classname", resource.GetType().FullName + "," + resource.GetType().GetTypeInfo().Assembly.GetName().Name },
|
||||||
|
{ "name", resource.Instance.Name },
|
||||||
|
{ "values", values }
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
var filter = Builders<BsonDocument>.Filter.Eq("_id", document["_id"]);
|
||||||
|
var update = Builders<BsonDocument>.Update
|
||||||
|
.Set("values", values).Set("parents", parents).Set("children", children).Set("attributes", attrsDoc);
|
||||||
|
resourcesCollection.UpdateOne(filter, update);
|
||||||
|
|
||||||
|
|
||||||
|
//resource.Instance.Attributes["objectId"] = document["_id"].ToString();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public BsonDocument ComposeStructure(Structure value)
|
||||||
|
{
|
||||||
|
var rt = new BsonDocument { { "type", 1 } };
|
||||||
|
|
||||||
|
var values = new BsonDocument();
|
||||||
|
foreach (var i in value)
|
||||||
|
values.Add(i.Key, Compose(i.Value));
|
||||||
|
|
||||||
|
rt.Add("values", values);
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BsonArray ComposeVarArray(object[] array)
|
||||||
|
{
|
||||||
|
var rt = new BsonArray();
|
||||||
|
|
||||||
|
for (var i = 0; i < array.Length; i++)
|
||||||
|
rt.Add(Compose(array[i]));
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
|
||||||
|
BsonArray ComposeStructureArray(Structure[] structures)
|
||||||
|
{
|
||||||
|
var rt = new BsonArray();
|
||||||
|
|
||||||
|
if (structures == null || structures?.Length == 0)
|
||||||
|
return rt;
|
||||||
|
|
||||||
|
foreach (var s in structures)
|
||||||
|
rt.Add(ComposeStructure(s));
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
|
||||||
|
BsonArray ComposeResourceArray(IResource[] array)
|
||||||
|
{
|
||||||
|
var rt = new BsonArray();
|
||||||
|
foreach (var r in array)
|
||||||
|
{
|
||||||
|
rt.Add(new BsonDocument { { "type", 0 }, { "link", r.Instance.Link } });
|
||||||
|
|
||||||
|
//if (r.Instance.Attributes.ContainsKey("objectId"))
|
||||||
|
|
||||||
|
//rt.Add(new BsonObjectId(new ObjectId((string)r.Instance.Attributes["objectId"])));
|
||||||
|
}
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BsonValue Compose(object value)
|
||||||
|
{
|
||||||
|
var type = Codec.GetDataType(value, null);
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case DataType.Void:
|
||||||
|
// nothing to do;
|
||||||
|
return BsonNull.Value;
|
||||||
|
|
||||||
|
case DataType.String:
|
||||||
|
return new BsonString((string)value);
|
||||||
|
|
||||||
|
case DataType.Resource:
|
||||||
|
case DataType.DistributedResource:
|
||||||
|
|
||||||
|
return new BsonDocument { { "type", 0 }, { "link", (value as IResource).Instance.Link } };
|
||||||
|
|
||||||
|
//return new BsonObjectId(new ObjectId((string)(value as IResource).Instance.Attributes["objectId"]));
|
||||||
|
|
||||||
|
case DataType.Structure:
|
||||||
|
return ComposeStructure((Structure)value);
|
||||||
|
|
||||||
|
case DataType.VarArray:
|
||||||
|
return ComposeVarArray((object[])value);
|
||||||
|
|
||||||
|
case DataType.ResourceArray:
|
||||||
|
if (value is IResource[])
|
||||||
|
return ComposeResourceArray((IResource[])value);
|
||||||
|
else
|
||||||
|
return ComposeResourceArray((IResource[])DC.CastConvert(value, typeof(IResource[])));
|
||||||
|
|
||||||
|
|
||||||
|
case DataType.StructureArray:
|
||||||
|
return ComposeStructureArray((Structure[])value);
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
return BsonValue.Create(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncReply<IResource> Retrieve(uint iid)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (trigger == ResourceTrigger.Initialize)
|
||||||
|
{
|
||||||
|
|
||||||
|
var collectionName = Instance.Attributes["Collection"] as string ?? "resources";
|
||||||
|
var dbName = Instance.Attributes["Database"] as string ?? "esiur";
|
||||||
|
client = new MongoClient(Instance.Attributes["Connection"] as string ?? "mongodb://localhost");
|
||||||
|
database = client.GetDatabase(dbName);
|
||||||
|
|
||||||
|
resourcesCollection = this.database.GetCollection<BsonDocument>(collectionName);
|
||||||
|
|
||||||
|
// return new AsyncReply<bool>(true);
|
||||||
|
|
||||||
|
var filter = new BsonDocument();
|
||||||
|
|
||||||
|
var list = resourcesCollection.Find(filter).ToList();
|
||||||
|
|
||||||
|
|
||||||
|
// if (list.Count == 0)
|
||||||
|
// return new AsyncBag<IResource>(new IResource[0]);
|
||||||
|
|
||||||
|
var bag = new AsyncBag<IResource>();
|
||||||
|
|
||||||
|
for (var i = 0; i < list.Count; i++)
|
||||||
|
{
|
||||||
|
//Console.WriteLine("Loading {0}/{1}", i, list.Count);
|
||||||
|
bag.Add(Get("id/" + list[i]["_id"].AsObjectId.ToString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bag.Seal();
|
||||||
|
|
||||||
|
var rt = new AsyncReply<bool>();
|
||||||
|
|
||||||
|
bag.Then((x) => { rt.Trigger(true); });
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
else if (trigger == ResourceTrigger.Terminate)
|
||||||
|
{
|
||||||
|
// save all resources
|
||||||
|
foreach (var resource in resources.Values)
|
||||||
|
SaveResource(resource);
|
||||||
|
|
||||||
|
return new AsyncReply<bool>(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return new AsyncReply<bool>(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void SaveResource(IResource resource)
|
||||||
|
{
|
||||||
|
var attrs = resource.Instance.GetAttributes();
|
||||||
|
|
||||||
|
var parents = new BsonArray();
|
||||||
|
var children = new BsonArray();
|
||||||
|
var template = resource.Instance.Template;
|
||||||
|
|
||||||
|
foreach (IResource c in resource.Instance.Children)
|
||||||
|
children.Add(c.Instance.Link);
|
||||||
|
|
||||||
|
foreach (IResource p in resource.Instance.Parents)
|
||||||
|
parents.Add(p.Instance.Link);
|
||||||
|
|
||||||
|
|
||||||
|
var values = new BsonDocument();
|
||||||
|
|
||||||
|
foreach (var pt in template.Properties)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
#if NETSTANDARD1_5
|
||||||
|
var pi = resource.GetType().GetTypeInfo().GetProperty(pt.Name);
|
||||||
|
#else
|
||||||
|
var pi = resource.GetType().GetProperty(pt.Name);
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
var rt = pt.Info.GetValue(resource, null);
|
||||||
|
|
||||||
|
values.Add(pt.Name,
|
||||||
|
new BsonDocument { { "age", BsonValue.Create(resource.Instance.GetAge(pt.Index)) },
|
||||||
|
{ "modification", resource.Instance.GetModificationDate(pt.Index) },
|
||||||
|
{ "value", Compose(rt) } });
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var attrsDoc = ComposeStructure(attrs);
|
||||||
|
|
||||||
|
var type = ResourceProxy.GetBaseType(resource);
|
||||||
|
|
||||||
|
var document = new BsonDocument
|
||||||
|
{
|
||||||
|
{ "parents", parents },
|
||||||
|
{ "children", children },
|
||||||
|
{"attributes", attrsDoc },
|
||||||
|
{ "classname", type.FullName + "," + type.GetTypeInfo().Assembly.GetName().Name },
|
||||||
|
{ "name", resource.Instance.Name },
|
||||||
|
{ "_id", new BsonObjectId(new ObjectId(resource.Instance.Attributes["objectId"].ToString())) },
|
||||||
|
{"values", values }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var filter = Builders<BsonDocument>.Filter.Eq("_id", document["_id"]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
var update = Builders<BsonDocument>.Update
|
||||||
|
.Set("values", values);
|
||||||
|
|
||||||
|
var update = Builders<BsonDocument>.Update.Set("values", values).Set("parents", parents;
|
||||||
|
col.UpdateOne(filter, update);
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
resourcesCollection.ReplaceOne(filter, document);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncReply<PropertyValue[]> GetPropertyRecordByAge(IResource resource, string propertyName, ulong fromAge, ulong toAge)
|
||||||
|
{
|
||||||
|
var objectId = resource.Instance.Attributes["objectId"].ToString();
|
||||||
|
|
||||||
|
var record = this.database.GetCollection<BsonDocument>("record_" + objectId);
|
||||||
|
var builder = Builders<BsonDocument>.Filter;
|
||||||
|
|
||||||
|
var filter = builder.Gte("age", fromAge) & builder.Lte("age", toAge) & builder.Eq("property", propertyName);
|
||||||
|
|
||||||
|
var reply = new AsyncReply<PropertyValue[]>();
|
||||||
|
|
||||||
|
record.FindAsync(filter).ContinueWith((x) =>
|
||||||
|
{
|
||||||
|
var values = ((Task<IAsyncCursor<BsonDocument>>)x).Result.ToList();
|
||||||
|
|
||||||
|
var bag = new AsyncBag<object>();
|
||||||
|
|
||||||
|
foreach (var v in values)
|
||||||
|
bag.Add(Parse(v["value"]));
|
||||||
|
|
||||||
|
bag.Seal();
|
||||||
|
|
||||||
|
bag.Then((results) =>
|
||||||
|
{
|
||||||
|
var list = new List<PropertyValue>();
|
||||||
|
for (var i = 0; i < results.Length; i++)
|
||||||
|
list.Add(new PropertyValue(results[i], (ulong)values[i]["age"].AsInt64, values[i]["date"].ToUniversalTime()));
|
||||||
|
|
||||||
|
reply.Trigger(list.ToArray());
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncReply<PropertyValue[]> GetPropertyRecordByDate(IResource resource, string propertyName, DateTime fromDate, DateTime toDate)
|
||||||
|
{
|
||||||
|
var objectId = resource.Instance.Attributes["objectId"].ToString();
|
||||||
|
|
||||||
|
var record = this.database.GetCollection<BsonDocument>("record_" + objectId);
|
||||||
|
var builder = Builders<BsonDocument>.Filter;
|
||||||
|
|
||||||
|
var filter = builder.Gte("date", fromDate) & builder.Lte("date", toDate) & builder.Eq("property", propertyName);
|
||||||
|
|
||||||
|
var reply = new AsyncReply<PropertyValue[]>();
|
||||||
|
|
||||||
|
record.FindAsync(filter).ContinueWith((x) =>
|
||||||
|
{
|
||||||
|
var values = ((Task<IAsyncCursor<BsonDocument>>)x).Result.ToList();
|
||||||
|
|
||||||
|
var bag = new AsyncBag<object>();
|
||||||
|
|
||||||
|
foreach (var v in values)
|
||||||
|
bag.Add(Parse(v["value"]));
|
||||||
|
|
||||||
|
bag.Seal();
|
||||||
|
|
||||||
|
bag.Then((results) =>
|
||||||
|
{
|
||||||
|
var list = new List<PropertyValue>();
|
||||||
|
for (var i = 0; i < results.Length; i++)
|
||||||
|
list.Add(new PropertyValue(results[i], (ulong)values[i]["age"].AsInt64, values[i]["date"].ToUniversalTime()));
|
||||||
|
|
||||||
|
reply.Trigger(list.ToArray());
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> GetRecordByAge(IResource resource, ulong fromAge, ulong toAge)
|
||||||
|
{
|
||||||
|
var properties = resource.Instance.Template.Properties.Where(x => x.Storage == StorageMode.Recordable).ToList();
|
||||||
|
|
||||||
|
var reply = new AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>>();
|
||||||
|
|
||||||
|
AsyncBag<PropertyValue[]> bag = new AsyncBag<PropertyValue[]>();
|
||||||
|
|
||||||
|
foreach (var p in properties)
|
||||||
|
bag.Add(GetPropertyRecordByAge(resource, p.Name, fromAge, toAge));
|
||||||
|
|
||||||
|
bag.Seal();
|
||||||
|
|
||||||
|
bag.Then(x =>
|
||||||
|
{
|
||||||
|
var list = new KeyList<PropertyTemplate, PropertyValue[]>();
|
||||||
|
|
||||||
|
for (var i = 0; i < x.Length; i++)
|
||||||
|
list.Add(properties[i], x[i]);
|
||||||
|
|
||||||
|
reply.Trigger(list);
|
||||||
|
});
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> GetRecord(IResource resource, DateTime fromDate, DateTime toDate)
|
||||||
|
{
|
||||||
|
var properties = resource.Instance.Template.Properties.Where(x => x.Storage == StorageMode.Recordable).ToList();
|
||||||
|
|
||||||
|
var reply = new AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>>();
|
||||||
|
|
||||||
|
AsyncBag<PropertyValue[]> bag = new AsyncBag<PropertyValue[]>();
|
||||||
|
|
||||||
|
foreach (var p in properties)
|
||||||
|
bag.Add(GetPropertyRecordByDate(resource, p.Name, fromDate, toDate));
|
||||||
|
|
||||||
|
bag.Seal();
|
||||||
|
|
||||||
|
bag.Then(x =>
|
||||||
|
{
|
||||||
|
var list = new KeyList<PropertyTemplate, PropertyValue[]>();
|
||||||
|
|
||||||
|
for (var i = 0; i < x.Length; i++)
|
||||||
|
list.Add(properties[i], x[i]);
|
||||||
|
|
||||||
|
reply.Trigger(list);
|
||||||
|
});
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Modify(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
|
||||||
|
{
|
||||||
|
|
||||||
|
var sql = $"UPDATE `{resource.Instance.Template.ClassName}` SET `{propertyName}` = @value, `{propertyName}_age` = @age, `{propertyName}_date` = @date WHERE `_id` = @id";
|
||||||
|
|
||||||
|
MySqlHelper.ExecuteNonQuery(connectionString, sql,
|
||||||
|
new MySqlParameter("@value", value),
|
||||||
|
new MySqlParameter("@age", age),
|
||||||
|
new MySqlParameter("@date", dateTime),
|
||||||
|
new MySqlParameter("@id", resource.Instance.Attributes["objectId"]));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
38
Esiur.sln
38
Esiur.sln
@ -1,13 +1,12 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio Version 16
|
||||||
VisualStudioVersion = 15.0.26228.9
|
VisualStudioVersion = 16.0.29324.140
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Esiur", "Esiur\Esiur.csproj", "{DEBF78DB-E3B3-47F4-994C-5C970E98C686}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Esiur", "Esiur\Esiur.csproj", "{4F74A8C1-D38F-4CC0-ACD1-24459BA0EAFC}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{08AC2E1C-24F0-4309-B35E-73D36A427D2D}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Esiur.Stores.MongoDB", "Esiur.Stores.MongoDB\Esiur.Stores.MongoDB.csproj", "{4C90D4B3-8EA2-48AE-A2F9-2B722FCEF9C4}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Esiur.Stores.MongoDB", "Esiur.Stores.MongoDB\Esiur.Stores.MongoDB.csproj", "{F7FB2243-12AB-46A6-9DA4-FF8DABC77D8F}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Esiur.Stores.MySql", "Esiur.Stores.MySql\Esiur.Stores.MySql.csproj", "{7BD6148A-3335-411C-9189-3803B1824264}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@ -15,20 +14,23 @@ Global
|
|||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{DEBF78DB-E3B3-47F4-994C-5C970E98C686}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{4F74A8C1-D38F-4CC0-ACD1-24459BA0EAFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{DEBF78DB-E3B3-47F4-994C-5C970E98C686}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{4F74A8C1-D38F-4CC0-ACD1-24459BA0EAFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{DEBF78DB-E3B3-47F4-994C-5C970E98C686}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{4F74A8C1-D38F-4CC0-ACD1-24459BA0EAFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{DEBF78DB-E3B3-47F4-994C-5C970E98C686}.Release|Any CPU.Build.0 = Release|Any CPU
|
{4F74A8C1-D38F-4CC0-ACD1-24459BA0EAFC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{08AC2E1C-24F0-4309-B35E-73D36A427D2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{4C90D4B3-8EA2-48AE-A2F9-2B722FCEF9C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{08AC2E1C-24F0-4309-B35E-73D36A427D2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{4C90D4B3-8EA2-48AE-A2F9-2B722FCEF9C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{08AC2E1C-24F0-4309-B35E-73D36A427D2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{4C90D4B3-8EA2-48AE-A2F9-2B722FCEF9C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{08AC2E1C-24F0-4309-B35E-73D36A427D2D}.Release|Any CPU.Build.0 = Release|Any CPU
|
{4C90D4B3-8EA2-48AE-A2F9-2B722FCEF9C4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{F7FB2243-12AB-46A6-9DA4-FF8DABC77D8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{7BD6148A-3335-411C-9189-3803B1824264}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{F7FB2243-12AB-46A6-9DA4-FF8DABC77D8F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{7BD6148A-3335-411C-9189-3803B1824264}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{F7FB2243-12AB-46A6-9DA4-FF8DABC77D8F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{7BD6148A-3335-411C-9189-3803B1824264}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{F7FB2243-12AB-46A6-9DA4-FF8DABC77D8F}.Release|Any CPU.Build.0 = Release|Any CPU
|
{7BD6148A-3335-411C-9189-3803B1824264}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {C584421D-5EC0-4821-B7D8-2633D8D405F2}
|
||||||
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@ -2,39 +2,51 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Esiur.Core
|
namespace Esiur.Core
|
||||||
{
|
{
|
||||||
public class AsyncAwaiter<T> : INotifyCompletion
|
public class AsyncAwaiter<T> : INotifyCompletion
|
||||||
{
|
{
|
||||||
public Action callback = null;
|
Action callback = null;
|
||||||
public T result;
|
|
||||||
private bool completed;
|
AsyncException exception = null;
|
||||||
|
|
||||||
|
T result;
|
||||||
|
|
||||||
public AsyncAwaiter(AsyncReply<T> reply)
|
public AsyncAwaiter(AsyncReply<T> reply)
|
||||||
{
|
{
|
||||||
reply.Then(x =>
|
reply.Then(x =>
|
||||||
{
|
{
|
||||||
this.completed = true;
|
this.IsCompleted = true;
|
||||||
this.result = x;
|
this.result = x;
|
||||||
this.callback?.Invoke();
|
this.callback?.Invoke();
|
||||||
|
}).Error(x =>
|
||||||
|
{
|
||||||
|
exception = x;
|
||||||
|
this.IsCompleted = true;
|
||||||
|
this.callback?.Invoke();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public T GetResult()
|
public T GetResult()
|
||||||
{
|
{
|
||||||
|
if (exception != null)
|
||||||
|
throw exception;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsCompleted => completed;
|
public bool IsCompleted { get; private set; }
|
||||||
|
|
||||||
public void OnCompleted(Action continuation)
|
public void OnCompleted(Action continuation)
|
||||||
{
|
{
|
||||||
// Continue....
|
if (IsCompleted)
|
||||||
callback = continuation;
|
continuation?.Invoke();
|
||||||
|
else
|
||||||
|
// Continue....
|
||||||
|
callback = continuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,5 +95,11 @@ namespace Esiur.Core
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AsyncBag(T[] results)
|
||||||
|
{
|
||||||
|
resultReady = true;
|
||||||
|
base.result = results;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,9 +34,12 @@ using System.Runtime.CompilerServices;
|
|||||||
|
|
||||||
namespace Esiur.Core
|
namespace Esiur.Core
|
||||||
{
|
{
|
||||||
public class AsyncReply<T>: IAsyncReply<T>
|
[AsyncMethodBuilder(typeof(AsyncReply<>))]
|
||||||
|
public class AsyncReply<T> : IAsyncReply<T>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public bool Debug = false;
|
||||||
|
|
||||||
protected List<Action<T>> callbacks = new List<Action<T>>();
|
protected List<Action<T>> callbacks = new List<Action<T>>();
|
||||||
protected T result;
|
protected T result;
|
||||||
|
|
||||||
@ -48,11 +51,12 @@ namespace Esiur.Core
|
|||||||
|
|
||||||
//List<AsyncAwaiter> awaiters = new List<AsyncAwaiter>();
|
//List<AsyncAwaiter> awaiters = new List<AsyncAwaiter>();
|
||||||
|
|
||||||
object callbacksLock = new object();
|
// object callbacksLock = new object();
|
||||||
|
|
||||||
protected bool resultReady = false;
|
protected bool resultReady = false;
|
||||||
AsyncException exception;
|
AsyncException exception;
|
||||||
|
|
||||||
|
AutoResetEvent mutex = new AutoResetEvent(false);
|
||||||
|
|
||||||
public bool Ready
|
public bool Ready
|
||||||
{
|
{
|
||||||
@ -60,6 +64,23 @@ namespace Esiur.Core
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public T Wait()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (resultReady)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (Debug)
|
||||||
|
Console.WriteLine($"AsyncReply: {GetHashCode()} Wait");
|
||||||
|
|
||||||
|
//mutex = new AutoResetEvent(false);
|
||||||
|
mutex.WaitOne();
|
||||||
|
|
||||||
|
if (Debug)
|
||||||
|
Console.WriteLine($"AsyncReply: {GetHashCode()} Wait ended");
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public object Result
|
public object Result
|
||||||
@ -69,53 +90,91 @@ namespace Esiur.Core
|
|||||||
|
|
||||||
public IAsyncReply<T> Then(Action<T> callback)
|
public IAsyncReply<T> Then(Action<T> callback)
|
||||||
{
|
{
|
||||||
callbacks.Add(callback);
|
//lock (callbacksLock)
|
||||||
|
//{
|
||||||
|
|
||||||
|
|
||||||
if (resultReady)
|
if (resultReady)
|
||||||
|
{
|
||||||
|
if (Debug)
|
||||||
|
Console.WriteLine($"AsyncReply: {GetHashCode()} Then ready");
|
||||||
|
|
||||||
callback(result);
|
callback(result);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (Debug)
|
||||||
|
Console.WriteLine($"AsyncReply: {GetHashCode()} Then pending");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
callbacks.Add(callback);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IAsyncReply<T> Error(Action<AsyncException> callback)
|
public IAsyncReply<T> Error(Action<AsyncException> callback)
|
||||||
{
|
{
|
||||||
|
// lock (callbacksLock)
|
||||||
|
// {
|
||||||
errorCallbacks.Add(callback);
|
errorCallbacks.Add(callback);
|
||||||
|
|
||||||
if (exception != null)
|
if (exception != null)
|
||||||
callback(exception);
|
callback(exception);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IAsyncReply<T> Progress(Action<ProgressType, int, int> callback)
|
public IAsyncReply<T> Progress(Action<ProgressType, int, int> callback)
|
||||||
{
|
{
|
||||||
|
//lock (callbacksLock)
|
||||||
|
//{
|
||||||
progressCallbacks.Add(callback);
|
progressCallbacks.Add(callback);
|
||||||
return this;
|
return this;
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public IAsyncReply<T> Chunk(Action<T> callback)
|
public IAsyncReply<T> Chunk(Action<T> callback)
|
||||||
{
|
{
|
||||||
|
// lock (callbacksLock)
|
||||||
|
// {
|
||||||
chunkCallbacks.Add(callback);
|
chunkCallbacks.Add(callback);
|
||||||
return this;
|
return this;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Trigger(object result)
|
public void Trigger(object result)
|
||||||
{
|
{
|
||||||
|
|
||||||
lock (callbacksLock)
|
if (Debug)
|
||||||
{
|
Console.WriteLine($"AsyncReply: {GetHashCode()} Trigger");
|
||||||
if (resultReady)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.result = (T)result;
|
|
||||||
resultReady = true;
|
|
||||||
|
|
||||||
foreach (var cb in callbacks)
|
|
||||||
cb((T)result);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
//lock (callbacksLock)
|
||||||
|
//{
|
||||||
|
if (resultReady)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.result = (T)result;
|
||||||
|
|
||||||
|
resultReady = true;
|
||||||
|
|
||||||
|
//if (mutex != null)
|
||||||
|
mutex.Set();
|
||||||
|
|
||||||
|
foreach (var cb in callbacks)
|
||||||
|
cb((T)result);
|
||||||
|
|
||||||
|
|
||||||
|
if (Debug)
|
||||||
|
Console.WriteLine($"AsyncReply: {GetHashCode()} Trigger ended");
|
||||||
|
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,11 +189,13 @@ namespace Esiur.Core
|
|||||||
this.exception = new AsyncException(ErrorType.Management, 0, exception.Message);
|
this.exception = new AsyncException(ErrorType.Management, 0, exception.Message);
|
||||||
|
|
||||||
|
|
||||||
lock (callbacksLock)
|
// lock (callbacksLock)
|
||||||
{
|
// {
|
||||||
foreach (var cb in errorCallbacks)
|
foreach (var cb in errorCallbacks)
|
||||||
cb(this.exception);
|
cb(this.exception);
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
mutex?.Set();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,12 +204,12 @@ namespace Esiur.Core
|
|||||||
if (resultReady)
|
if (resultReady)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lock (callbacksLock)
|
//lock (callbacksLock)
|
||||||
{
|
//{
|
||||||
foreach (var cb in progressCallbacks)
|
foreach (var cb in progressCallbacks)
|
||||||
cb(type, value, max);
|
cb(type, value, max);
|
||||||
|
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -157,12 +218,12 @@ namespace Esiur.Core
|
|||||||
if (resultReady)
|
if (resultReady)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lock (callbacksLock)
|
//lock (callbacksLock)
|
||||||
{
|
//{
|
||||||
foreach (var cb in chunkCallbacks)
|
foreach (var cb in chunkCallbacks)
|
||||||
cb((T)value);
|
cb((T)value);
|
||||||
|
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AsyncAwaiter<T> GetAwaiter()
|
public AsyncAwaiter<T> GetAwaiter()
|
||||||
@ -172,15 +233,14 @@ namespace Esiur.Core
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public AsyncReply()
|
public AsyncReply()
|
||||||
{
|
{
|
||||||
|
//this.Debug = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AsyncReply(T result)
|
public AsyncReply(T result)
|
||||||
{
|
{
|
||||||
|
//this.Debug = true;
|
||||||
resultReady = true;
|
resultReady = true;
|
||||||
this.result = result;
|
this.result = result;
|
||||||
}
|
}
|
||||||
@ -218,7 +278,7 @@ namespace Esiur.Core
|
|||||||
return base.Task.ContinueWith<T>((t) =>
|
return base.Task.ContinueWith<T>((t) =>
|
||||||
{
|
{
|
||||||
|
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
return (T)t.GetType().GetTypeInfo().GetProperty("Result").GetValue(t);
|
return (T)t.GetType().GetTypeInfo().GetProperty("Result").GetValue(t);
|
||||||
#else
|
#else
|
||||||
return (T)t.GetType().GetProperty("Result").GetValue(t);
|
return (T)t.GetType().GetProperty("Result").GetValue(t);
|
||||||
|
@ -16,6 +16,6 @@ namespace Esiur.Core
|
|||||||
void TriggerProgress(ProgressType type, int value, int max);
|
void TriggerProgress(ProgressType type, int value, int max);
|
||||||
void TriggerChunk(object value);
|
void TriggerChunk(object value);
|
||||||
|
|
||||||
|
T Wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ namespace Esiur.Data
|
|||||||
public AutoList(ST state)
|
public AutoList(ST state)
|
||||||
{
|
{
|
||||||
this.state = state;
|
this.state = state;
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
removableList = (typeof(IDestructible).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()));
|
removableList = (typeof(IDestructible).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()));
|
||||||
#else
|
#else
|
||||||
removableList = (typeof(IDestructible).IsAssignableFrom(typeof(T)));
|
removableList = (typeof(IDestructible).IsAssignableFrom(typeof(T)));
|
||||||
@ -111,7 +111,7 @@ namespace Esiur.Data
|
|||||||
public AutoList(ST state, T[] values)
|
public AutoList(ST state, T[] values)
|
||||||
{
|
{
|
||||||
this.state = state;
|
this.state = state;
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
removableList = (typeof(IDestructible).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()));
|
removableList = (typeof(IDestructible).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()));
|
||||||
#else
|
#else
|
||||||
removableList = (typeof(IDestructible).IsAssignableFrom(typeof(T)));
|
removableList = (typeof(IDestructible).IsAssignableFrom(typeof(T)));
|
||||||
|
@ -62,7 +62,7 @@ namespace Esiur.Data
|
|||||||
list.Add((byte)i);
|
list.Add((byte)i);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
MethodInfo mi = typeof(DC).GetTypeInfo().GetMethod("ToBytes", new Type[] { i.GetType() });
|
MethodInfo mi = typeof(DC).GetTypeInfo().GetMethod("ToBytes", new Type[] { i.GetType() });
|
||||||
#else
|
#else
|
||||||
MethodInfo mi = typeof(DC).GetMethod("ToBytes", new Type[] { i.GetType() });
|
MethodInfo mi = typeof(DC).GetMethod("ToBytes", new Type[] { i.GetType() });
|
||||||
@ -100,7 +100,7 @@ namespace Esiur.Data
|
|||||||
list.Add((byte)i);
|
list.Add((byte)i);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
MethodInfo mi = typeof(DC).GetTypeInfo().GetMethod("ToBytes", new Type[] { i.GetType() });
|
MethodInfo mi = typeof(DC).GetTypeInfo().GetMethod("ToBytes", new Type[] { i.GetType() });
|
||||||
#else
|
#else
|
||||||
MethodInfo mi = typeof(DC).GetMethod("ToBytes", new Type[] { i.GetType() });
|
MethodInfo mi = typeof(DC).GetMethod("ToBytes", new Type[] { i.GetType() });
|
||||||
@ -138,7 +138,7 @@ namespace Esiur.Data
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
MethodInfo mi = typeof(DC).GetTypeInfo().GetMethod("ToBytes", new Type[] { i.GetType() });
|
MethodInfo mi = typeof(DC).GetTypeInfo().GetMethod("ToBytes", new Type[] { i.GetType() });
|
||||||
#else
|
#else
|
||||||
MethodInfo mi = typeof(DC).GetMethod("ToBytes", new Type[] { i.GetType() });
|
MethodInfo mi = typeof(DC).GetMethod("ToBytes", new Type[] { i.GetType() });
|
||||||
|
@ -34,6 +34,7 @@ using Esiur.Resource;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Esiur.Resource.Template;
|
using Esiur.Resource.Template;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Esiur.Data
|
namespace Esiur.Data
|
||||||
{
|
{
|
||||||
@ -171,7 +172,7 @@ namespace Esiur.Data
|
|||||||
|
|
||||||
var result = (StructureComparisonResult)data[offset++];
|
var result = (StructureComparisonResult)data[offset++];
|
||||||
|
|
||||||
IAsyncReply<Structure> previous = null;
|
AsyncReply<Structure> previous = null;
|
||||||
// string[] previousKeys = null;
|
// string[] previousKeys = null;
|
||||||
// DataType[] previousTypes = null;
|
// DataType[] previousTypes = null;
|
||||||
|
|
||||||
@ -1064,6 +1065,16 @@ namespace Esiur.Data
|
|||||||
return rt.ToArray();
|
return rt.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static bool IsAnonymous(Type type)
|
||||||
|
{
|
||||||
|
// Detect anonymous types
|
||||||
|
var info = type.GetTypeInfo();
|
||||||
|
var hasCompilerGeneratedAttribute = info.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Count() > 0;
|
||||||
|
var nameContainsAnonymousType = type.FullName.Contains("AnonymousType");
|
||||||
|
return hasCompilerGeneratedAttribute && nameContainsAnonymousType;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if a type implements an interface
|
/// Check if a type implements an interface
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -1086,7 +1097,7 @@ namespace Esiur.Data
|
|||||||
if (type == iface)
|
if (type == iface)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
if (type.GetTypeInfo().GetInterfaces().Contains(iface))// (x=>x.GetTypeInfo().IsGenericType (iface))
|
if (type.GetTypeInfo().GetInterfaces().Contains(iface))// (x=>x.GetTypeInfo().IsGenericType (iface))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -1109,7 +1120,7 @@ namespace Esiur.Data
|
|||||||
if (type == iface)
|
if (type == iface)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
if (type.GetTypeInfo().GetInterfaces().Contains(iface))
|
if (type.GetTypeInfo().GetInterfaces().Contains(iface))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -1137,7 +1148,7 @@ namespace Esiur.Data
|
|||||||
{
|
{
|
||||||
if (childType == parentType)
|
if (childType == parentType)
|
||||||
return true;
|
return true;
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
childType = childType.GetTypeInfo().BaseType;
|
childType = childType.GetTypeInfo().BaseType;
|
||||||
#else
|
#else
|
||||||
childType = childType.BaseType;
|
childType = childType.BaseType;
|
||||||
|
@ -67,7 +67,7 @@ namespace Esiur.Data
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
if (destinationType.GetTypeInfo().IsInstanceOfType(v.GetValue(i)))
|
if (destinationType.GetTypeInfo().IsInstanceOfType(v.GetValue(i)))
|
||||||
#else
|
#else
|
||||||
if (destinationType.IsInstanceOfType(v.GetValue(i)))
|
if (destinationType.IsInstanceOfType(v.GetValue(i)))
|
||||||
@ -97,7 +97,7 @@ namespace Esiur.Data
|
|||||||
destinationType = underType;
|
destinationType = underType;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
if (destinationType.GetTypeInfo().IsInstanceOfType(value))
|
if (destinationType.GetTypeInfo().IsInstanceOfType(value))
|
||||||
#else
|
#else
|
||||||
if (destinationType.IsInstanceOfType(value))
|
if (destinationType.IsInstanceOfType(value))
|
||||||
@ -589,7 +589,7 @@ namespace Esiur.Data
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
var tryParse = typeof(T).GetTypeInfo().GetDeclaredMethod("TryParse");
|
var tryParse = typeof(T).GetTypeInfo().GetDeclaredMethod("TryParse");
|
||||||
if ((bool)tryParse.Invoke(null, new object[] { Input, null }))
|
if ((bool)tryParse.Invoke(null, new object[] { Input, null }))
|
||||||
{
|
{
|
||||||
|
@ -220,7 +220,7 @@ namespace Esiur.Data
|
|||||||
|
|
||||||
public KeyList(object owner = null)
|
public KeyList(object owner = null)
|
||||||
{
|
{
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
removableList = (typeof(IDestructible).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()));
|
removableList = (typeof(IDestructible).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()));
|
||||||
#else
|
#else
|
||||||
removableList = (typeof(IDestructible).IsAssignableFrom(typeof(T)));
|
removableList = (typeof(IDestructible).IsAssignableFrom(typeof(T)));
|
||||||
|
@ -31,6 +31,7 @@ using System.Threading.Tasks;
|
|||||||
using Esiur.Data;
|
using Esiur.Data;
|
||||||
using Esiur.Misc;
|
using Esiur.Misc;
|
||||||
using Esiur.Core;
|
using Esiur.Core;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Esiur.Data
|
namespace Esiur.Data
|
||||||
{
|
{
|
||||||
@ -61,6 +62,26 @@ namespace Esiur.Data
|
|||||||
return rt.TrimEnd('\r', '\n');
|
return rt.TrimEnd('\r', '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Structure FromObject(object obj)
|
||||||
|
{
|
||||||
|
var type = obj.GetType();
|
||||||
|
|
||||||
|
if (obj is Structure)
|
||||||
|
return obj as Structure;
|
||||||
|
else if (Codec.IsAnonymous(type))
|
||||||
|
{
|
||||||
|
var st = new Structure();
|
||||||
|
|
||||||
|
var pi = type.GetTypeInfo().GetProperties();
|
||||||
|
foreach (var p in pi)
|
||||||
|
st[p.Name] = p.GetValue(obj);
|
||||||
|
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
||||||
{
|
{
|
||||||
return dic.GetEnumerator();
|
return dic.GetEnumerator();
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard1.5</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<Description>Distributed Resources Platform</Description>
|
<Description>Distributed Resources Platform</Description>
|
||||||
<Copyright>Ahmed Kh. Zamil</Copyright>
|
<Copyright>Ahmed Kh. Zamil</Copyright>
|
||||||
<PackageLicenseUrl>https://github.com/esiur/esiur-dotnet/blob/master/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/esiur/esiur-dotnet/blob/master/LICENSE</PackageLicenseUrl>
|
||||||
<PackageProjectUrl>http://www.esiur.com</PackageProjectUrl>
|
<PackageProjectUrl>http://www.esiur.com</PackageProjectUrl>
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
<Version>1.2.7</Version>
|
<Version>1.4.0</Version>
|
||||||
<RepositoryUrl>https://github.com/esiur/esiur-dotnet</RepositoryUrl>
|
<RepositoryUrl>https://github.com/esiur/esiur-dotnet</RepositoryUrl>
|
||||||
<Authors>Ahmed Kh. Zamil</Authors>
|
<Authors>Ahmed Kh. Zamil</Authors>
|
||||||
<AssemblyVersion>1.2.7.0</AssemblyVersion>
|
<AssemblyVersion>1.3.1.0</AssemblyVersion>
|
||||||
<Company>Esiur Foundation</Company>
|
<Company>Esiur Foundation</Company>
|
||||||
<FileVersion>1.2.7.0</FileVersion>
|
<FileVersion>1.3.1.0</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
<DefineConstants>TRACE;DEBUG;NETSTANDARD1_5</DefineConstants>
|
<DefineConstants>TRACE;DEBUG;NETSTANDARD</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
@ -46,6 +46,7 @@
|
|||||||
<PackageReference Include="System.Net.NetworkInformation" Version="4.3.0" />
|
<PackageReference Include="System.Net.NetworkInformation" Version="4.3.0" />
|
||||||
<PackageReference Include="System.Net.Security" Version="4.3.1" />
|
<PackageReference Include="System.Net.Security" Version="4.3.1" />
|
||||||
<PackageReference Include="System.Reflection.Emit" Version="4.3.0" />
|
<PackageReference Include="System.Reflection.Emit" Version="4.3.0" />
|
||||||
|
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
@ -72,20 +72,20 @@ namespace Esiur.Net.DataLink
|
|||||||
{
|
{
|
||||||
if (trigger == ResourceTrigger.Initialize)
|
if (trigger == ResourceTrigger.Initialize)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
foreach (Instance instance in Instance.Children)
|
foreach (var resource in Instance.Children<IResource>())
|
||||||
{
|
{
|
||||||
|
|
||||||
if (instance.Resource is PacketFilter)
|
if (resource is PacketFilter)
|
||||||
{
|
{
|
||||||
filters.Add(instance.Resource as PacketFilter);
|
filters.Add(resource as PacketFilter);
|
||||||
}
|
}
|
||||||
else if (instance.Resource is PacketSource)
|
else if (resource is PacketSource)
|
||||||
{
|
{
|
||||||
sources.Add(instance.Resource as PacketSource);
|
sources.Add(resource as PacketSource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
foreach (var src in sources)
|
foreach (var src in sources)
|
||||||
{
|
{
|
||||||
src.OnNewPacket += PacketReceived;
|
src.OnNewPacket += PacketReceived;
|
||||||
|
@ -44,6 +44,7 @@ namespace Esiur.Net.HTTP
|
|||||||
public class HTTPServer : NetworkServer<HTTPConnection>, IResource
|
public class HTTPServer : NetworkServer<HTTPConnection>, IResource
|
||||||
{
|
{
|
||||||
Dictionary<string, HTTPSession> sessions= new Dictionary<string, HTTPSession>();
|
Dictionary<string, HTTPSession> sessions= new Dictionary<string, HTTPSession>();
|
||||||
|
HTTPFilter[] filters = null;
|
||||||
|
|
||||||
public Instance Instance
|
public Instance Instance
|
||||||
{
|
{
|
||||||
@ -183,13 +184,8 @@ namespace Esiur.Net.HTTP
|
|||||||
{
|
{
|
||||||
//Console.WriteLine("OUT: " + this.Connections.Count);
|
//Console.WriteLine("OUT: " + this.Connections.Count);
|
||||||
|
|
||||||
foreach (IResource resource in Instance.Children)
|
foreach (var filter in filters)
|
||||||
{
|
filter.ClientDisconnected(sender);
|
||||||
if (resource is HTTPFilter)
|
|
||||||
{
|
|
||||||
(resource as HTTPFilter).ClientDisconnected(sender);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -268,16 +264,11 @@ namespace Esiur.Net.HTTP
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
foreach (IResource resource in Instance.Children)
|
foreach (var resource in filters)
|
||||||
{
|
resource.Execute(sender);
|
||||||
if (resource is HTTPFilter)
|
|
||||||
{
|
|
||||||
if ((resource as HTTPFilter).Execute(sender))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sender.Send("Bad Request");
|
|
||||||
|
sender.Send("Bad Request");
|
||||||
sender.Close();
|
sender.Close();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -289,21 +280,19 @@ namespace Esiur.Net.HTTP
|
|||||||
|
|
||||||
//Console.WriteLine(ex.ToString());
|
//Console.WriteLine(ex.ToString());
|
||||||
//EventLog.WriteEntry("HttpServer", ex.ToString(), EventLogEntryType.Error);
|
//EventLog.WriteEntry("HttpServer", ex.ToString(), EventLogEntryType.Error);
|
||||||
sender.Send(Return500(ex.Message));
|
sender.Send(Error500(ex.Message));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Return500(string sMessage)
|
private string Error500(string msg)
|
||||||
{
|
{
|
||||||
string sTMP = null;
|
return "<html><head><title>500 Internal Server Error</title></head><br>\r\n"
|
||||||
sTMP = "<HTML><HEAD><TITLE>500 Internal Server Error</TITLE></HEAD><br>\r\n";
|
+ "<body><br>\r\n"
|
||||||
sTMP = sTMP + "<BODY BGCOLOR=" + (char)(34) + "#FFFFFF" + (char)(34) + " Text=" + (char)(34) + "#000000" + (char)(34) + " LINK=" + (char)(34) + "#0000FF" + (char)(34) + " VLINK=" + (char)(34) + "#000080" + (char)(34) + " ALINK=" + (char)(34) + "#008000" + (char)(34) + "><br>\r\n";
|
+ "<b>500</b> Internal Server Error<br>" + msg + "\r\n"
|
||||||
sTMP = sTMP + "<b>500</b> Sorry - Internal Server Error<br>" + sMessage + "\r\n";
|
+ "</body><br>\r\n"
|
||||||
sTMP = sTMP + "</BODY><br>\r\n";
|
+ "</html><br>\r\n";
|
||||||
sTMP = sTMP + "</HTML><br>\r\n";
|
|
||||||
return sTMP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -382,6 +371,10 @@ namespace Esiur.Net.HTTP
|
|||||||
Trigger(ResourceTrigger.Terminate);
|
Trigger(ResourceTrigger.Terminate);
|
||||||
Trigger(ResourceTrigger.Initialize);
|
Trigger(ResourceTrigger.Initialize);
|
||||||
}
|
}
|
||||||
|
else if (trigger == ResourceTrigger.SystemInitialized)
|
||||||
|
{
|
||||||
|
Instance.Children<HTTPFilter>().Then(x => filters = x);
|
||||||
|
}
|
||||||
|
|
||||||
return new AsyncReply<bool>(true);
|
return new AsyncReply<bool>(true);
|
||||||
|
|
||||||
@ -395,12 +388,9 @@ namespace Esiur.Net.HTTP
|
|||||||
|
|
||||||
//Console.WriteLine("IN: " + this.Connections.Count);
|
//Console.WriteLine("IN: " + this.Connections.Count);
|
||||||
|
|
||||||
foreach (var resource in Instance.Children)
|
foreach (var resource in filters)
|
||||||
{
|
{
|
||||||
if (resource is HTTPFilter)
|
resource.ClientConnected(sender);
|
||||||
{
|
|
||||||
(resource as HTTPFilter).ClientConnected(sender);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,25 +46,31 @@ namespace Esiur.Net.HTTP
|
|||||||
public override bool Execute(HTTPConnection sender)
|
public override bool Execute(HTTPConnection sender)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (DistributedServer == null)
|
if (sender.IsWebsocketRequest())
|
||||||
return false;
|
{
|
||||||
|
if (DistributedServer == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
var tcpSocket = sender.Unassign();
|
var tcpSocket = sender.Unassign();
|
||||||
|
|
||||||
if (tcpSocket == null)
|
if (tcpSocket == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var httpServer = sender.Parent;
|
var httpServer = sender.Parent;
|
||||||
var wsSocket = new WSSocket(tcpSocket);
|
var wsSocket = new WSSocket(tcpSocket);
|
||||||
httpServer.RemoveConnection(sender);
|
httpServer.RemoveConnection(sender);
|
||||||
|
|
||||||
var iipConnection = new DistributedConnection();
|
var iipConnection = new DistributedConnection();
|
||||||
|
|
||||||
DistributedServer.AddConnection(iipConnection);
|
DistributedServer.AddConnection(iipConnection);
|
||||||
iipConnection.Assign(wsSocket);
|
iipConnection.Assign(wsSocket);
|
||||||
wsSocket.Begin();
|
wsSocket.Begin();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
|
||||||
/*
|
/*
|
||||||
if (sender.Request.Filename.StartsWith("/iip/"))
|
if (sender.Request.Filename.StartsWith("/iip/"))
|
||||||
{
|
{
|
||||||
|
@ -326,16 +326,22 @@ namespace Esiur.Net.IIP
|
|||||||
//packs.Add(packet.Command.ToString() + " " + packet.Action.ToString() + " " + packet.Event.ToString());
|
//packs.Add(packet.Command.ToString() + " " + packet.Action.ToString() + " " + packet.Event.ToString());
|
||||||
|
|
||||||
//if (packs.Count > 1)
|
//if (packs.Count > 1)
|
||||||
// Console.WriteLine("P2");
|
// Console.WriteLine("P2");
|
||||||
|
|
||||||
|
//Console.WriteLine("");
|
||||||
|
|
||||||
if (rt <= 0)
|
if (rt <= 0)
|
||||||
{
|
{
|
||||||
|
//Console.WriteLine("Hold");
|
||||||
var size = ends - offset;
|
var size = ends - offset;
|
||||||
data.HoldFor(msg, offset, size, size + (uint)(-rt));
|
data.HoldFor(msg, offset, size, size + (uint)(-rt));
|
||||||
return ends;
|
return ends;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//Console.WriteLine($"CMD {packet.Command} {offset} {ends}");
|
||||||
|
|
||||||
offset += (uint)rt;
|
offset += (uint)rt;
|
||||||
|
|
||||||
if (packet.Command == IIPPacket.IIPPacketCommand.Event)
|
if (packet.Command == IIPPacket.IIPPacketCommand.Event)
|
||||||
@ -807,7 +813,9 @@ namespace Esiur.Net.IIP
|
|||||||
sock.Connect(domain, port).Then((x)=> {
|
sock.Connect(domain, port).Then((x)=> {
|
||||||
Assign(sock);
|
Assign(sock);
|
||||||
//rt.trigger(true);
|
//rt.trigger(true);
|
||||||
}).Error((x) => openReply.TriggerError(x));
|
}).Error((x) =>
|
||||||
|
openReply.TriggerError(x)
|
||||||
|
);
|
||||||
|
|
||||||
return openReply;
|
return openReply;
|
||||||
}
|
}
|
||||||
@ -841,5 +849,64 @@ namespace Esiur.Net.IIP
|
|||||||
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
|
||||||
|
{
|
||||||
|
throw new Exception("SS");
|
||||||
|
|
||||||
|
//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("SS");
|
||||||
|
//if (Codec.IsLocalResource(resource, this))
|
||||||
|
// return (resource as DistributedResource).parents.Where(x => x.GetType() == typeof(T)).Select(x => (T)x);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
public AsyncBag<T> Children<T>(IResource resource)
|
||||||
|
{
|
||||||
|
if (Codec.IsLocalResource(resource, this))
|
||||||
|
return (resource as DistributedResource).children.Where(x => x.GetType() == typeof(T)).Select(x => (T)x);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncBag<T> Parents<T>(IResource resource)
|
||||||
|
{
|
||||||
|
if (Codec.IsLocalResource(resource, this))
|
||||||
|
return (resource as DistributedResource).parents.Where(x => x.GetType() == typeof(T)).Select(x => (T)x);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -387,7 +387,10 @@ namespace Esiur.Net.IIP
|
|||||||
{
|
{
|
||||||
Fetch(childId).Then(child =>
|
Fetch(childId).Then(child =>
|
||||||
{
|
{
|
||||||
parent.Instance.Children.Add(child);
|
parent.children.Add(child);
|
||||||
|
child.parents.Add(parent);
|
||||||
|
|
||||||
|
//parent.Instance.Children.Add(child);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -398,7 +401,10 @@ namespace Esiur.Net.IIP
|
|||||||
{
|
{
|
||||||
Fetch(childId).Then(child =>
|
Fetch(childId).Then(child =>
|
||||||
{
|
{
|
||||||
parent.Instance.Children.Remove(child);
|
parent.children.Remove(child);
|
||||||
|
child.parents.Remove(parent);
|
||||||
|
|
||||||
|
// parent.Instance.Children.Remove(child);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -443,16 +449,16 @@ namespace Esiur.Net.IIP
|
|||||||
r.Instance.ResourceEventOccurred -= Instance_EventOccurred;
|
r.Instance.ResourceEventOccurred -= Instance_EventOccurred;
|
||||||
r.Instance.ResourceModified -= Instance_PropertyModified;
|
r.Instance.ResourceModified -= Instance_PropertyModified;
|
||||||
r.Instance.ResourceDestroyed -= Instance_ResourceDestroyed;
|
r.Instance.ResourceDestroyed -= Instance_ResourceDestroyed;
|
||||||
r.Instance.Children.OnAdd -= Children_OnAdd;
|
// r.Instance.Children.OnAdd -= Children_OnAdd;
|
||||||
r.Instance.Children.OnRemoved -= Children_OnRemoved;
|
// r.Instance.Children.OnRemoved -= Children_OnRemoved;
|
||||||
r.Instance.Attributes.OnModified -= Attributes_OnModified;
|
r.Instance.Attributes.OnModified -= Attributes_OnModified;
|
||||||
|
|
||||||
// subscribe
|
// subscribe
|
||||||
r.Instance.ResourceEventOccurred += Instance_EventOccurred;
|
r.Instance.ResourceEventOccurred += Instance_EventOccurred;
|
||||||
r.Instance.ResourceModified += Instance_PropertyModified;
|
r.Instance.ResourceModified += Instance_PropertyModified;
|
||||||
r.Instance.ResourceDestroyed += Instance_ResourceDestroyed;
|
r.Instance.ResourceDestroyed += Instance_ResourceDestroyed;
|
||||||
r.Instance.Children.OnAdd += Children_OnAdd;
|
//r.Instance.Children.OnAdd += Children_OnAdd;
|
||||||
r.Instance.Children.OnRemoved += Children_OnRemoved;
|
//r.Instance.Children.OnRemoved += Children_OnRemoved;
|
||||||
r.Instance.Attributes.OnModified += Attributes_OnModified;
|
r.Instance.Attributes.OnModified += Attributes_OnModified;
|
||||||
|
|
||||||
var link = DC.ToBytes(r.Instance.Link);
|
var link = DC.ToBytes(r.Instance.Link);
|
||||||
@ -520,6 +526,28 @@ namespace Esiur.Net.IIP
|
|||||||
.Done();
|
.Done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool RemoveChild(IResource parent, IResource child)
|
||||||
|
{
|
||||||
|
SendEvent(IIPPacket.IIPPacketEvent.ChildRemoved)
|
||||||
|
.AddUInt32((parent as DistributedResource).Id)
|
||||||
|
.AddUInt32((child as DistributedResource).Id)
|
||||||
|
.Done();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddChild(IResource parent, IResource child)
|
||||||
|
{
|
||||||
|
SendEvent(IIPPacket.IIPPacketEvent.ChildAdded)
|
||||||
|
.AddUInt32((parent as DistributedResource).Id)
|
||||||
|
.AddUInt32((child as DistributedResource).Id)
|
||||||
|
.Done();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void IIPRequestReattachResource(uint callback, uint resourceId, ulong resourceAge)
|
void IIPRequestReattachResource(uint callback, uint resourceId, ulong resourceAge)
|
||||||
{
|
{
|
||||||
Warehouse.Get(resourceId).Then((res) =>
|
Warehouse.Get(resourceId).Then((res) =>
|
||||||
@ -531,16 +559,16 @@ namespace Esiur.Net.IIP
|
|||||||
r.Instance.ResourceEventOccurred -= Instance_EventOccurred;
|
r.Instance.ResourceEventOccurred -= Instance_EventOccurred;
|
||||||
r.Instance.ResourceModified -= Instance_PropertyModified;
|
r.Instance.ResourceModified -= Instance_PropertyModified;
|
||||||
r.Instance.ResourceDestroyed -= Instance_ResourceDestroyed;
|
r.Instance.ResourceDestroyed -= Instance_ResourceDestroyed;
|
||||||
r.Instance.Children.OnAdd -= Children_OnAdd;
|
//r.Instance.Children.OnAdd -= Children_OnAdd;
|
||||||
r.Instance.Children.OnRemoved -= Children_OnRemoved;
|
//r.Instance.Children.OnRemoved -= Children_OnRemoved;
|
||||||
r.Instance.Attributes.OnModified -= Attributes_OnModified;
|
r.Instance.Attributes.OnModified -= Attributes_OnModified;
|
||||||
|
|
||||||
// subscribe
|
// subscribe
|
||||||
r.Instance.ResourceEventOccurred += Instance_EventOccurred;
|
r.Instance.ResourceEventOccurred += Instance_EventOccurred;
|
||||||
r.Instance.ResourceModified += Instance_PropertyModified;
|
r.Instance.ResourceModified += Instance_PropertyModified;
|
||||||
r.Instance.ResourceDestroyed += Instance_ResourceDestroyed;
|
r.Instance.ResourceDestroyed += Instance_ResourceDestroyed;
|
||||||
r.Instance.Children.OnAdd += Children_OnAdd;
|
//r.Instance.Children.OnAdd += Children_OnAdd;
|
||||||
r.Instance.Children.OnRemoved += Children_OnRemoved;
|
//r.Instance.Children.OnRemoved += Children_OnRemoved;
|
||||||
r.Instance.Attributes.OnModified += Attributes_OnModified;
|
r.Instance.Attributes.OnModified += Attributes_OnModified;
|
||||||
|
|
||||||
// reply ok
|
// reply ok
|
||||||
@ -646,7 +674,7 @@ namespace Esiur.Net.IIP
|
|||||||
Codec.ParseStructure(content, offset, cl, this).Then(values =>
|
Codec.ParseStructure(content, offset, cl, this).Then(values =>
|
||||||
{
|
{
|
||||||
|
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
var constructors = Type.GetType(className).GetTypeInfo().GetConstructors();
|
var constructors = Type.GetType(className).GetTypeInfo().GetConstructors();
|
||||||
#else
|
#else
|
||||||
var constructors = Type.GetType(className).GetConstructors();
|
var constructors = Type.GetType(className).GetConstructors();
|
||||||
@ -791,7 +819,7 @@ namespace Esiur.Net.IIP
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent.Instance.Children.Add(child);
|
parent.Instance.Store.AddChild(parent, child);
|
||||||
|
|
||||||
SendReply(IIPPacket.IIPPacketAction.AddChild, callback).Done();
|
SendReply(IIPPacket.IIPPacketAction.AddChild, callback).Done();
|
||||||
//child.Instance.Parents
|
//child.Instance.Parents
|
||||||
@ -830,7 +858,7 @@ namespace Esiur.Net.IIP
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent.Instance.Children.Remove(child);
|
parent.Instance.Store.RemoveChild(parent, child);// Children.Remove(child);
|
||||||
|
|
||||||
SendReply(IIPPacket.IIPPacketAction.RemoveChild, callback).Done();
|
SendReply(IIPPacket.IIPPacketAction.RemoveChild, callback).Done();
|
||||||
//child.Instance.Parents
|
//child.Instance.Parents
|
||||||
@ -871,9 +899,14 @@ namespace Esiur.Net.IIP
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SendReply(IIPPacket.IIPPacketAction.ResourceChildren, callback)
|
resource.Instance.Children<IResource>().Then(children =>
|
||||||
.AddUInt8Array(Codec.ComposeResourceArray(resource.Instance.Children.ToArray(), this, true))
|
{
|
||||||
.Done();
|
SendReply(IIPPacket.IIPPacketAction.ResourceChildren, callback)
|
||||||
|
.AddUInt8Array(Codec.ComposeResourceArray(children, this, true))
|
||||||
|
.Done();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -888,9 +921,14 @@ namespace Esiur.Net.IIP
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SendReply(IIPPacket.IIPPacketAction.ResourceParents, callback)
|
resource.Instance.Parents<IResource>().Then(parents =>
|
||||||
.AddUInt8Array(Codec.ComposeResourceArray(resource.Instance.Parents.ToArray(), this, true))
|
{
|
||||||
.Done();
|
SendReply(IIPPacket.IIPPacketAction.ResourceParents, callback)
|
||||||
|
.AddUInt8Array(Codec.ComposeResourceArray(parents, this, true))
|
||||||
|
.Done();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1010,7 +1048,8 @@ namespace Esiur.Net.IIP
|
|||||||
|
|
||||||
void IIPRequestQueryResources(uint callback, string resourceLink)
|
void IIPRequestQueryResources(uint callback, string resourceLink)
|
||||||
{
|
{
|
||||||
Warehouse.Query(resourceLink).Then((r) =>
|
|
||||||
|
Action<IResource[]> queryCallback = (r) =>
|
||||||
{
|
{
|
||||||
//if (r != null)
|
//if (r != null)
|
||||||
//{
|
//{
|
||||||
@ -1022,12 +1061,12 @@ namespace Esiur.Net.IIP
|
|||||||
SendReply(IIPPacket.IIPPacketAction.QueryLink, callback)
|
SendReply(IIPPacket.IIPPacketAction.QueryLink, callback)
|
||||||
.AddUInt8Array(Codec.ComposeResourceArray(list, this, true))
|
.AddUInt8Array(Codec.ComposeResourceArray(list, this, true))
|
||||||
.Done();
|
.Done();
|
||||||
//}
|
};
|
||||||
//else
|
|
||||||
//{
|
if (Server?.EntryPoint != null)
|
||||||
// reply failed
|
Server.EntryPoint.Query(resourceLink, this).Then(queryCallback);
|
||||||
//}
|
else
|
||||||
});
|
Warehouse.Query(resourceLink).ContinueWith(x => queryCallback(x.Result));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IIPRequestResourceAttribute(uint callback, uint resourceId)
|
void IIPRequestResourceAttribute(uint callback, uint resourceId)
|
||||||
@ -1068,7 +1107,7 @@ namespace Esiur.Net.IIP
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
var fi = r.GetType().GetTypeInfo().GetMethod(ft.Name);
|
var fi = r.GetType().GetTypeInfo().GetMethod(ft.Name);
|
||||||
#else
|
#else
|
||||||
var fi = r.GetType().GetMethod(ft.Name);
|
var fi = r.GetType().GetMethod(ft.Name);
|
||||||
@ -1134,7 +1173,7 @@ namespace Esiur.Net.IIP
|
|||||||
{
|
{
|
||||||
(rt as Task).ContinueWith(t =>
|
(rt as Task).ContinueWith(t =>
|
||||||
{
|
{
|
||||||
#if NETSTANDARD1_5
|
#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);
|
||||||
@ -1225,7 +1264,7 @@ namespace Esiur.Net.IIP
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
var fi = r.GetType().GetTypeInfo().GetMethod(ft.Name);
|
var fi = r.GetType().GetTypeInfo().GetMethod(ft.Name);
|
||||||
#else
|
#else
|
||||||
var fi = r.GetType().GetMethod(ft.Name);
|
var fi = r.GetType().GetMethod(ft.Name);
|
||||||
@ -1285,7 +1324,7 @@ namespace Esiur.Net.IIP
|
|||||||
{
|
{
|
||||||
(rt as Task).ContinueWith(t =>
|
(rt as Task).ContinueWith(t =>
|
||||||
{
|
{
|
||||||
#if NETSTANDARD1_5
|
#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);
|
||||||
@ -1358,7 +1397,7 @@ namespace Esiur.Net.IIP
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
var pi = r.GetType().GetTypeInfo().GetProperty(pt.Name);
|
var pi = r.GetType().GetTypeInfo().GetProperty(pt.Name);
|
||||||
#else
|
#else
|
||||||
var pi = r.GetType().GetProperty(pt.Name);
|
var pi = r.GetType().GetProperty(pt.Name);
|
||||||
@ -1435,7 +1474,7 @@ namespace Esiur.Net.IIP
|
|||||||
{
|
{
|
||||||
if (r.Instance.GetAge(index) > age)
|
if (r.Instance.GetAge(index) > age)
|
||||||
{
|
{
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
var pi = r.GetType().GetTypeInfo().GetProperty(pt.Name);
|
var pi = r.GetType().GetTypeInfo().GetProperty(pt.Name);
|
||||||
#else
|
#else
|
||||||
var pi = r.GetType().GetProperty(pt.Name);
|
var pi = r.GetType().GetProperty(pt.Name);
|
||||||
@ -1498,7 +1537,7 @@ namespace Esiur.Net.IIP
|
|||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
var pi = r.GetType().GetTypeInfo().GetProperty(pt.Name);
|
var pi = r.GetType().GetTypeInfo().GetProperty(pt.Name);
|
||||||
#else
|
#else
|
||||||
var pi = r.GetType().GetProperty(pt.Name);
|
var pi = r.GetType().GetProperty(pt.Name);
|
||||||
@ -1748,12 +1787,18 @@ namespace Esiur.Net.IIP
|
|||||||
|
|
||||||
Query(path).Then(ar =>
|
Query(path).Then(ar =>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//if (filter != null)
|
||||||
|
// ar = ar?.Where(filter).ToArray();
|
||||||
|
|
||||||
|
// MISSING: should dispatch the unused resources.
|
||||||
if (ar?.Length > 0)
|
if (ar?.Length > 0)
|
||||||
rt.Trigger(ar[0]);
|
rt.Trigger(ar[0]);
|
||||||
else
|
else
|
||||||
rt.Trigger(null);
|
rt.Trigger(null);
|
||||||
}).Error(ex => rt.TriggerError(ex));
|
}).Error(ex => rt.TriggerError(ex));
|
||||||
|
|
||||||
|
|
||||||
return rt;
|
return rt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -53,7 +53,7 @@ namespace Esiur.Net.IIP
|
|||||||
/// Raised when the distributed resource is destroyed.
|
/// Raised when the distributed resource is destroyed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event DestroyedEvent OnDestroy;
|
public event DestroyedEvent OnDestroy;
|
||||||
|
public event Instance.ResourceModifiedEvent OnModified;
|
||||||
uint instanceId;
|
uint instanceId;
|
||||||
DistributedConnection connection;
|
DistributedConnection connection;
|
||||||
|
|
||||||
@ -68,6 +68,9 @@ namespace Esiur.Net.IIP
|
|||||||
//ulong age;
|
//ulong age;
|
||||||
//ulong[] ages;
|
//ulong[] ages;
|
||||||
object[] properties;
|
object[] properties;
|
||||||
|
internal List<DistributedResource> parents = new List<DistributedResource>();
|
||||||
|
internal List<DistributedResource> children = new List<DistributedResource>();
|
||||||
|
|
||||||
DistributedResourceEvent[] events;
|
DistributedResourceEvent[] events;
|
||||||
|
|
||||||
//ResourceTemplate template;
|
//ResourceTemplate template;
|
||||||
@ -171,10 +174,12 @@ namespace Esiur.Net.IIP
|
|||||||
this.link = link;
|
this.link = link;
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
this.instanceId = instanceId;
|
this.instanceId = instanceId;
|
||||||
|
|
||||||
//this.Instance.Template = template;
|
//this.Instance.Template = template;
|
||||||
//this.Instance.Age = age;
|
//this.Instance.Age = age;
|
||||||
//this.template = template;
|
//this.template = template;
|
||||||
//this.age = age;
|
//this.age = age;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void _Ready()
|
internal void _Ready()
|
||||||
@ -270,16 +275,12 @@ namespace Esiur.Net.IIP
|
|||||||
if (args.Length == 1)
|
if (args.Length == 1)
|
||||||
{
|
{
|
||||||
// Detect anonymous types
|
// Detect anonymous types
|
||||||
var type = args[0].GetType().GetTypeInfo();
|
var type = args[0].GetType();
|
||||||
var hasCompilerGeneratedAttribute = type.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Count() > 0;
|
if (Codec.IsAnonymous(type))
|
||||||
var nameContainsAnonymousType = type.FullName.Contains("AnonymousType");
|
|
||||||
var isAnonymousType = hasCompilerGeneratedAttribute && nameContainsAnonymousType;
|
|
||||||
|
|
||||||
if (isAnonymousType)
|
|
||||||
{
|
{
|
||||||
var namedArgs = new Structure();
|
var namedArgs = new Structure();
|
||||||
|
|
||||||
var pi = type.GetProperties();
|
var pi = type.GetTypeInfo().GetProperties();
|
||||||
foreach (var p in pi)
|
foreach (var p in pi)
|
||||||
namedArgs[p.Name] = p.GetValue(args[0]);
|
namedArgs[p.Name] = p.GetValue(args[0]);
|
||||||
result = _InvokeByNamedArguments(ft.Index, namedArgs);
|
result = _InvokeByNamedArguments(ft.Index, namedArgs);
|
||||||
@ -453,6 +454,7 @@ namespace Esiur.Net.IIP
|
|||||||
public DistributedResource()
|
public DistributedResource()
|
||||||
{
|
{
|
||||||
//stack = new DistributedResourceStack(this);
|
//stack = new DistributedResourceStack(this);
|
||||||
|
//this.Instance.ResourceModified += this.OnModified;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,6 +465,10 @@ namespace Esiur.Net.IIP
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
|
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (trigger == ResourceTrigger.Initialize)
|
||||||
|
this.Instance.ResourceModified += this.OnModified;
|
||||||
|
|
||||||
// do nothing.
|
// do nothing.
|
||||||
return new AsyncReply<bool>(true);
|
return new AsyncReply<bool>(true);
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,12 @@ namespace Esiur.Net.IIP
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EntryPoint EntryPoint
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
//[Storable]
|
//[Storable]
|
||||||
//[ResourceProperty]
|
//[ResourceProperty]
|
||||||
public ushort port
|
public ushort port
|
||||||
@ -128,8 +134,7 @@ namespace Esiur.Net.IIP
|
|||||||
|
|
||||||
protected override void ClientConnected(DistributedConnection sender)
|
protected override void ClientConnected(DistributedConnection sender)
|
||||||
{
|
{
|
||||||
Console.WriteLine("DistributedConnection Client Connected");
|
//Console.WriteLine("DistributedConnection Client Connected");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Sender_OnReady(DistributedConnection sender)
|
private void Sender_OnReady(DistributedConnection sender)
|
||||||
|
40
Esiur/Net/IIP/EntryPoint.cs
Normal file
40
Esiur/Net/IIP/EntryPoint.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2019 Ahmed Kh. Zamil
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Esiur.Core;
|
||||||
|
using Esiur.Data;
|
||||||
|
using Esiur.Resource;
|
||||||
|
using Esiur.Resource.Template;
|
||||||
|
|
||||||
|
namespace Esiur.Net.IIP
|
||||||
|
{
|
||||||
|
public abstract class EntryPoint : Esiur.Resource.Resource
|
||||||
|
{
|
||||||
|
|
||||||
|
public abstract AsyncReply<IResource[]> Query(string path, DistributedConnection sender);
|
||||||
|
public abstract override bool Create();
|
||||||
|
}
|
||||||
|
}
|
@ -209,8 +209,8 @@ namespace Esiur.Net.Packets
|
|||||||
{
|
{
|
||||||
if (offset + needed > ends)
|
if (offset + needed > ends)
|
||||||
{
|
{
|
||||||
//dataLengthNeeded = needed - (ends - offset);
|
dataLengthNeeded = needed - (ends - offset);
|
||||||
dataLengthNeeded = needed - (ends - originalOffset);
|
//dataLengthNeeded = needed - (ends - originalOffset);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,7 @@ namespace Esiur.Net.Sockets
|
|||||||
bool asyncSending;
|
bool asyncSending;
|
||||||
bool began = false;
|
bool began = false;
|
||||||
|
|
||||||
|
|
||||||
SocketState state = SocketState.Initial;
|
SocketState state = SocketState.Initial;
|
||||||
|
|
||||||
public event ISocketReceiveEvent OnReceive;
|
public event ISocketReceiveEvent OnReceive;
|
||||||
@ -313,23 +314,23 @@ namespace Esiur.Net.Sockets
|
|||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
if (state != SocketState.Closed && state != SocketState.Terminated)
|
if (state != SocketState.Closed && state != SocketState.Terminated)
|
||||||
|
{
|
||||||
state = SocketState.Closed;
|
state = SocketState.Closed;
|
||||||
|
|
||||||
if (sock.Connected)
|
if (sock.Connected)
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
sock.Shutdown(SocketShutdown.Both);
|
try
|
||||||
}
|
{
|
||||||
catch
|
sock.Shutdown(SocketShutdown.Both);
|
||||||
{
|
}
|
||||||
state = SocketState.Terminated;
|
catch
|
||||||
|
{
|
||||||
|
state = SocketState.Terminated;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sock.Shutdown(SocketShutdown.Both);// Close();
|
|
||||||
OnClose?.Invoke();
|
OnClose?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Send(byte[] message)
|
public void Send(byte[] message)
|
||||||
|
@ -65,18 +65,24 @@ namespace Esiur.Net.TCP
|
|||||||
}
|
}
|
||||||
public Instance Instance { get; set; }
|
public Instance Instance { get; set; }
|
||||||
|
|
||||||
|
TCPFilter[] filters = null;
|
||||||
|
|
||||||
|
|
||||||
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
|
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
|
||||||
{
|
{
|
||||||
if (trigger == ResourceTrigger.Initialize)
|
if (trigger == ResourceTrigger.Initialize)
|
||||||
{
|
{
|
||||||
TCPSocket listener;
|
TCPSocket listener;
|
||||||
|
|
||||||
|
|
||||||
if (ip != null)
|
if (ip != null)
|
||||||
listener =new TCPSocket(new IPEndPoint(IPAddress.Parse(ip), port));
|
listener =new TCPSocket(new IPEndPoint(IPAddress.Parse(ip), port));
|
||||||
else
|
else
|
||||||
listener = new TCPSocket(new IPEndPoint(IPAddress.Any, port));
|
listener = new TCPSocket(new IPEndPoint(IPAddress.Any, port));
|
||||||
|
|
||||||
Start(listener, timeout, clock);
|
Start(listener, timeout, clock);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (trigger == ResourceTrigger.Terminate)
|
else if (trigger == ResourceTrigger.Terminate)
|
||||||
{
|
{
|
||||||
@ -87,6 +93,10 @@ namespace Esiur.Net.TCP
|
|||||||
Trigger(ResourceTrigger.Terminate);
|
Trigger(ResourceTrigger.Terminate);
|
||||||
Trigger(ResourceTrigger.Initialize);
|
Trigger(ResourceTrigger.Initialize);
|
||||||
}
|
}
|
||||||
|
else if (trigger == ResourceTrigger.SystemInitialized)
|
||||||
|
{
|
||||||
|
Instance.Children<TCPFilter>().Then(x => filters = x);
|
||||||
|
}
|
||||||
|
|
||||||
return new AsyncReply<bool>(true);
|
return new AsyncReply<bool>(true);
|
||||||
}
|
}
|
||||||
@ -97,14 +107,10 @@ namespace Esiur.Net.TCP
|
|||||||
{
|
{
|
||||||
var msg = data.Read();
|
var msg = data.Read();
|
||||||
|
|
||||||
foreach (var resource in Instance.Children)
|
foreach (var filter in filters)
|
||||||
{
|
{
|
||||||
if (resource is TCPFilter)
|
if (filter.Execute(msg, data, sender))
|
||||||
{
|
|
||||||
var f = resource as TCPFilter;
|
|
||||||
if (f.Execute(msg, data, sender))
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,25 +121,17 @@ namespace Esiur.Net.TCP
|
|||||||
|
|
||||||
protected override void ClientConnected(TCPConnection sender)
|
protected override void ClientConnected(TCPConnection sender)
|
||||||
{
|
{
|
||||||
foreach (var resource in Instance.Children)
|
foreach (var filter in filters)
|
||||||
{
|
{
|
||||||
if (resource is TCPFilter)
|
filter.Connected(sender);
|
||||||
{
|
|
||||||
var f = resource as TCPFilter;
|
|
||||||
f.Connected(sender);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ClientDisconnected(TCPConnection sender)
|
protected override void ClientDisconnected(TCPConnection sender)
|
||||||
{
|
{
|
||||||
foreach (var resource in Instance.Children)
|
foreach (var filter in filters)
|
||||||
{
|
{
|
||||||
if (resource is TCPFilter)
|
filter.Disconnected(sender);
|
||||||
{
|
|
||||||
var f = resource as TCPFilter;
|
|
||||||
f.Disconnected(sender);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
|||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PublishProtocol>FileSystem</PublishProtocol>
|
<PublishProtocol>FileSystem</PublishProtocol>
|
||||||
<Configuration>Release</Configuration>
|
<Configuration>Debug</Configuration>
|
||||||
<TargetFramework>netstandard1.5</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<PublishDir>M:\opt\esiur</PublishDir>
|
<PublishDir>M:\opt\esiur</PublishDir>
|
||||||
<Platform>Any CPU</Platform>
|
<Platform>Any CPU</Platform>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
@ -12,7 +12,7 @@ namespace Esiur.Proxy
|
|||||||
{
|
{
|
||||||
static Dictionary<Type, Type> cache = new Dictionary<Type, Type>();
|
static Dictionary<Type, Type> cache = new Dictionary<Type, Type>();
|
||||||
|
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
static MethodInfo modifyMethod = typeof(Instance).GetTypeInfo().GetMethod("Modified");
|
static MethodInfo modifyMethod = typeof(Instance).GetTypeInfo().GetMethod("Modified");
|
||||||
static MethodInfo instanceGet = typeof(IResource).GetTypeInfo().GetProperty("Instance").GetGetMethod();
|
static MethodInfo instanceGet = typeof(IResource).GetTypeInfo().GetProperty("Instance").GetGetMethod();
|
||||||
#else
|
#else
|
||||||
@ -44,7 +44,7 @@ namespace Esiur.Proxy
|
|||||||
if (cache.ContainsKey(type))
|
if (cache.ContainsKey(type))
|
||||||
return cache[type];
|
return cache[type];
|
||||||
|
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
var typeInfo = type.GetTypeInfo();
|
var typeInfo = type.GetTypeInfo();
|
||||||
|
|
||||||
if (typeInfo.IsSealed)
|
if (typeInfo.IsSealed)
|
||||||
@ -78,7 +78,7 @@ namespace Esiur.Proxy
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
var t = typeBuilder.CreateTypeInfo().AsType();
|
var t = typeBuilder.CreateTypeInfo().AsType();
|
||||||
cache.Add(type, t);
|
cache.Add(type, t);
|
||||||
return t;
|
return t;
|
||||||
|
@ -35,13 +35,27 @@ namespace Esiur.Resource
|
|||||||
{
|
{
|
||||||
public interface IStore:IResource
|
public interface IStore:IResource
|
||||||
{
|
{
|
||||||
AsyncReply<IResource> Get(string path);
|
AsyncReply<IResource> Get(string path);//, Func<IResource, bool> filter = null);
|
||||||
AsyncReply<IResource> Retrieve(uint iid);
|
//AsyncReply<IResource> Retrieve(uint iid);
|
||||||
bool Put(IResource resource);
|
bool Put(IResource resource);
|
||||||
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);
|
bool Remove(IResource resource);
|
||||||
|
|
||||||
|
|
||||||
|
AsyncReply<bool> AddChild(IResource parent, IResource child);
|
||||||
|
AsyncReply<bool> RemoveChild(IResource parent, IResource child);
|
||||||
|
|
||||||
|
AsyncReply<bool> AddParent(IResource child, IResource parent);
|
||||||
|
AsyncReply<bool> RemoveParent(IResource child, IResource parent);
|
||||||
|
|
||||||
|
|
||||||
|
AsyncBag<T> Children<T>(IResource resource, string name) where T : IResource;
|
||||||
|
AsyncBag<T> Parents<T>(IResource resource, string name) where T : IResource;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//AsyncReply<PropertyValue[]> GetPropertyRecord(IResource resource, string propertyName, ulong fromAge, ulong toAge);
|
//AsyncReply<PropertyValue[]> GetPropertyRecord(IResource resource, string propertyName, ulong fromAge, ulong toAge);
|
||||||
//AsyncReply<PropertyValue[]> GetPropertyRecordByDate(IResource resource, string propertyName, DateTime fromDate, DateTime toDate);
|
//AsyncReply<PropertyValue[]> GetPropertyRecordByDate(IResource resource, string propertyName, DateTime fromDate, DateTime toDate);
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ using Esiur.Security.Permissions;
|
|||||||
using Esiur.Resource.Template;
|
using Esiur.Resource.Template;
|
||||||
using Esiur.Security.Authority;
|
using Esiur.Security.Authority;
|
||||||
using Esiur.Proxy;
|
using Esiur.Proxy;
|
||||||
|
using Esiur.Core;
|
||||||
|
|
||||||
namespace Esiur.Resource
|
namespace Esiur.Resource
|
||||||
{
|
{
|
||||||
@ -19,10 +20,11 @@ namespace Esiur.Resource
|
|||||||
{
|
{
|
||||||
string name;
|
string name;
|
||||||
|
|
||||||
AutoList<IResource, Instance> children;// = new AutoList<IResource, Instance>();
|
//IQueryable<IResource> children;//
|
||||||
IResource resource;
|
//AutoList<IResource, Instance> children;// = new AutoList<IResource, Instance>();
|
||||||
|
WeakReference<IResource> resource;
|
||||||
IStore store;
|
IStore store;
|
||||||
AutoList<IResource, Instance> parents;// = new AutoList<IResource>();
|
//AutoList<IResource, Instance> parents;// = new AutoList<IResource>();
|
||||||
//bool inherit;
|
//bool inherit;
|
||||||
ResourceTemplate template;
|
ResourceTemplate template;
|
||||||
|
|
||||||
@ -40,6 +42,8 @@ namespace Esiur.Resource
|
|||||||
public event ResourceEventOccurredEvent ResourceEventOccurred;
|
public event ResourceEventOccurredEvent ResourceEventOccurred;
|
||||||
public event ResourceDestroyedEvent ResourceDestroyed;
|
public event ResourceDestroyedEvent ResourceDestroyed;
|
||||||
|
|
||||||
|
bool loading = false;
|
||||||
|
|
||||||
KeyList<string, object> attributes;
|
KeyList<string, object> attributes;
|
||||||
|
|
||||||
List<ulong> ages = new List<ulong>();
|
List<ulong> ages = new List<ulong>();
|
||||||
@ -90,7 +94,7 @@ namespace Esiur.Resource
|
|||||||
attributes = clone.ToArray();// this.attributes.Keys.ToList().Add("managers");
|
attributes = clone.ToArray();// this.attributes.Keys.ToList().Add("managers");
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(var attr in attributes)
|
foreach (var attr in attributes)
|
||||||
{
|
{
|
||||||
if (attr == "name")
|
if (attr == "name")
|
||||||
st["name"] = this.name;
|
st["name"] = this.name;
|
||||||
@ -109,15 +113,15 @@ namespace Esiur.Resource
|
|||||||
}
|
}
|
||||||
else if (attr == "parents")
|
else if (attr == "parents")
|
||||||
{
|
{
|
||||||
st["parents"] = parents.ToArray();
|
//st["parents"] = parents.ToArray();
|
||||||
}
|
}
|
||||||
else if (attr == "children")
|
else if (attr == "children")
|
||||||
{
|
{
|
||||||
st["children"] = children.ToArray();
|
//st["children"] = children.ToArray();
|
||||||
}
|
}
|
||||||
else if (attr == "childrenCount")
|
else if (attr == "childrenCount")
|
||||||
{
|
{
|
||||||
st["childrenCount"] = children.Count;
|
//st["childrenCount"] = children.Count;
|
||||||
}
|
}
|
||||||
else if (attr == "type")
|
else if (attr == "type")
|
||||||
{
|
{
|
||||||
@ -155,8 +159,13 @@ namespace Esiur.Resource
|
|||||||
{
|
{
|
||||||
var settings = m["settings"] as Structure;
|
var settings = m["settings"] as Structure;
|
||||||
var manager = Activator.CreateInstance(type) as IPermissionsManager;
|
var manager = Activator.CreateInstance(type) as IPermissionsManager;
|
||||||
manager.Initialize(settings, this.resource);
|
|
||||||
this.managers.Add(manager);
|
IResource res;
|
||||||
|
if (this.resource.TryGetTarget(out res))
|
||||||
|
{
|
||||||
|
manager.Initialize(settings, res);
|
||||||
|
this.managers.Add(manager);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
@ -266,13 +275,19 @@ namespace Esiur.Resource
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool LoadProperty(string name, ulong age, DateTime modificationDate, object value)
|
public bool LoadProperty(string name, ulong age, DateTime modificationDate, object value)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
IResource res;
|
||||||
|
|
||||||
|
if (!resource.TryGetTarget(out res))
|
||||||
|
return false;
|
||||||
|
|
||||||
var pt = template.GetPropertyTemplateByName(name);
|
var pt = template.GetPropertyTemplateByName(name);
|
||||||
|
|
||||||
if (pt == null)
|
if (pt == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
var pi = resource.GetType().GetTypeInfo().GetProperty(name, new[] { resource.GetType() });
|
var pi = resource.GetType().GetTypeInfo().GetProperty(name, new[] { resource.GetType() });
|
||||||
#else
|
#else
|
||||||
var pi = resource.GetType().GetProperty(pt.Name);
|
var pi = resource.GetType().GetProperty(pt.Name);
|
||||||
@ -283,17 +298,24 @@ namespace Esiur.Resource
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
||||||
try
|
if (pt.Info.CanWrite)
|
||||||
{
|
{
|
||||||
if (pt.Info.CanWrite)
|
try
|
||||||
pt.Info.SetValue(resource, DC.CastConvert(value, pt.Info.PropertyType));
|
{
|
||||||
}
|
loading = true;
|
||||||
catch(Exception ex)
|
|
||||||
{
|
pt.Info.SetValue(res, DC.CastConvert(value, pt.Info.PropertyType));
|
||||||
//Console.WriteLine(resource.ToString() + " " + name);
|
}
|
||||||
Global.Log(ex);
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
//Console.WriteLine(resource.ToString() + " " + name);
|
||||||
|
Global.Log(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SetAge(pt.Index, age);
|
SetAge(pt.Index, age);
|
||||||
SetModificationDate(pt.Index, modificationDate);
|
SetModificationDate(pt.Index, modificationDate);
|
||||||
|
|
||||||
@ -359,16 +381,19 @@ namespace Esiur.Resource
|
|||||||
foreach (var pt in template.Properties)
|
foreach (var pt in template.Properties)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
var pi = resource.GetType().GetTypeInfo().GetProperty(pt.Name);
|
var pi = resource.GetType().GetTypeInfo().GetProperty(pt.Name);
|
||||||
#else
|
#else
|
||||||
var pi = resource.GetType().GetProperty(pt.Name);
|
var pi = resource.GetType().GetProperty(pt.Name);
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
IResource res;
|
||||||
var rt = pt.Info.GetValue(resource, null);
|
if (resource.TryGetTarget(out res))
|
||||||
props.Add(new PropertyValue(rt, ages[pt.Index], modificationDates[pt.Index]));
|
{
|
||||||
|
var rt = pt.Info.GetValue(res, null);
|
||||||
|
props.Add(new PropertyValue(rt, ages[pt.Index], modificationDates[pt.Index]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return props.ToArray();
|
return props.ToArray();
|
||||||
@ -446,7 +471,7 @@ namespace Esiur.Resource
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool IsStorable()
|
public bool IsStorable()
|
||||||
{
|
{
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
var attrs = resource.GetType().GetTypeInfo().GetCustomAttributes(typeof(Storable), true).ToArray();
|
var attrs = resource.GetType().GetTypeInfo().GetCustomAttributes(typeof(Storable), true).ToArray();
|
||||||
#else
|
#else
|
||||||
var attrs = resource.GetType().GetCustomAttributes(typeof(Storable), true);
|
var attrs = resource.GetType().GetCustomAttributes(typeof(Storable), true);
|
||||||
@ -458,22 +483,27 @@ namespace Esiur.Resource
|
|||||||
|
|
||||||
internal void EmitModification(PropertyTemplate pt, object value)
|
internal void EmitModification(PropertyTemplate pt, object value)
|
||||||
{
|
{
|
||||||
instanceAge++;
|
|
||||||
var now = DateTime.UtcNow;
|
|
||||||
|
|
||||||
ages[pt.Index] = instanceAge;
|
IResource res;
|
||||||
modificationDates[pt.Index] = now;
|
if (this.resource.TryGetTarget(out res))
|
||||||
|
|
||||||
if (pt.Storage == StorageMode.NonVolatile)
|
|
||||||
{
|
{
|
||||||
store.Modify(resource, pt.Name, value, ages[pt.Index], now);
|
instanceAge++;
|
||||||
}
|
var now = DateTime.UtcNow;
|
||||||
else if (pt.Storage == StorageMode.Recordable)
|
|
||||||
{
|
|
||||||
store.Record(resource, pt.Name, value, ages[pt.Index], now);
|
|
||||||
}
|
|
||||||
|
|
||||||
ResourceModified?.Invoke(resource, pt.Name, value);
|
ages[pt.Index] = instanceAge;
|
||||||
|
modificationDates[pt.Index] = now;
|
||||||
|
|
||||||
|
if (pt.Storage == StorageMode.NonVolatile)
|
||||||
|
{
|
||||||
|
store.Modify(res, pt.Name, value, ages[pt.Index], now);
|
||||||
|
}
|
||||||
|
else if (pt.Storage == StorageMode.Recordable)
|
||||||
|
{
|
||||||
|
store.Record(res, pt.Name, value, ages[pt.Index], now);
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceModified?.Invoke(res, pt.Name, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -484,6 +514,9 @@ namespace Esiur.Resource
|
|||||||
/// <param name="oldValue"></param>
|
/// <param name="oldValue"></param>
|
||||||
public void Modified([CallerMemberName] string propertyName = "")
|
public void Modified([CallerMemberName] string propertyName = "")
|
||||||
{
|
{
|
||||||
|
if (loading)
|
||||||
|
return;
|
||||||
|
|
||||||
object value;
|
object value;
|
||||||
if (GetPropertyValue(propertyName, out value))
|
if (GetPropertyValue(propertyName, out value))
|
||||||
{
|
{
|
||||||
@ -496,7 +529,12 @@ namespace Esiur.Resource
|
|||||||
|
|
||||||
internal void EmitResourceEvent(object issuer, Session[] receivers, string name, object[] args)
|
internal void EmitResourceEvent(object issuer, Session[] receivers, string name, object[] args)
|
||||||
{
|
{
|
||||||
ResourceEventOccurred?.Invoke(resource, issuer, receivers, name, args);
|
IResource res;
|
||||||
|
if (this.resource.TryGetTarget(out res))
|
||||||
|
{
|
||||||
|
|
||||||
|
ResourceEventOccurred?.Invoke(res, issuer, receivers, name, args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -508,7 +546,7 @@ namespace Esiur.Resource
|
|||||||
public bool GetPropertyValue(string name, out object value)
|
public bool GetPropertyValue(string name, out object value)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
PropertyInfo pi = resource.GetType().GetTypeInfo().GetProperty(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
|
PropertyInfo pi = resource.GetType().GetTypeInfo().GetProperty(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -521,7 +559,7 @@ namespace Esiur.Resource
|
|||||||
if (pt != null && pt.Info != null)
|
if (pt != null && pt.Info != null)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
object[] ca = pi.GetCustomAttributes(typeof(ResourceProperty), false).ToArray();
|
object[] ca = pi.GetCustomAttributes(typeof(ResourceProperty), false).ToArray();
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -537,7 +575,15 @@ namespace Esiur.Resource
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
value = pt.Info.GetValue(resource, null);
|
IResource res;
|
||||||
|
if (resource.TryGetTarget(out res))
|
||||||
|
value = pt.Info.GetValue(res, null);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -556,10 +602,7 @@ namespace Esiur.Resource
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// List of parents.
|
/// List of parents.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public AutoList<IResource, Instance> Parents
|
//public AutoList<IResource, Instance> Parents => parents;
|
||||||
{
|
|
||||||
get { return parents; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Store responsible for creating and keeping the resource.
|
/// Store responsible for creating and keeping the resource.
|
||||||
@ -572,15 +615,54 @@ namespace Esiur.Resource
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// List of children.
|
/// List of children.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public AutoList<IResource, Instance> Children
|
// public AutoList<IResource, Instance> Children => children;
|
||||||
{
|
|
||||||
get { return children; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The unique and permanent link to the resource.
|
/// The unique and permanent link to the resource.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Link
|
public string Link
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
IResource res;
|
||||||
|
if (this.resource.TryGetTarget(out res))
|
||||||
|
{
|
||||||
|
if (res == res.Instance.store)
|
||||||
|
return name; // root store
|
||||||
|
else
|
||||||
|
return store.Link(res);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncBag<T> Children<T>(string name = null) where T : IResource
|
||||||
|
{
|
||||||
|
IResource res;
|
||||||
|
if (this.resource.TryGetTarget(out res))
|
||||||
|
{
|
||||||
|
//if (!(store is null))
|
||||||
|
return store.Children<T>(res, name);
|
||||||
|
//else
|
||||||
|
// return (res as IStore).Children<T>(res, name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return new AsyncBag<T>(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncBag<T> Parents<T>(string name = null) where T : IResource
|
||||||
|
{
|
||||||
|
IResource res;
|
||||||
|
if (this.resource.TryGetTarget(out res))
|
||||||
|
{
|
||||||
|
return store.Parents<T>(res, name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return new AsyncBag<T>(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
@ -607,6 +689,8 @@ namespace Esiur.Resource
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Instance name.
|
/// Instance name.
|
||||||
@ -623,7 +707,16 @@ namespace Esiur.Resource
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public IResource Resource
|
public IResource Resource
|
||||||
{
|
{
|
||||||
get { return resource; }
|
get
|
||||||
|
{
|
||||||
|
IResource res;
|
||||||
|
if (this.resource.TryGetTarget(out res))
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -658,11 +751,15 @@ namespace Esiur.Resource
|
|||||||
/// <returns>Ruling.</returns>
|
/// <returns>Ruling.</returns>
|
||||||
public Ruling Applicable(Session session, ActionType action, MemberTemplate member, object inquirer = null)
|
public Ruling Applicable(Session session, ActionType action, MemberTemplate member, object inquirer = null)
|
||||||
{
|
{
|
||||||
foreach (IPermissionsManager manager in managers)
|
IResource res;
|
||||||
|
if (this.resource.TryGetTarget(out res))
|
||||||
{
|
{
|
||||||
var r = manager.Applicable(this.resource, session, action, member, inquirer);
|
foreach (IPermissionsManager manager in managers)
|
||||||
if (r != Ruling.DontCare)
|
{
|
||||||
return r;
|
var r = manager.Applicable(res, session, action, member, inquirer);
|
||||||
|
if (r != Ruling.DontCare)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ruling.DontCare;
|
return Ruling.DontCare;
|
||||||
@ -684,19 +781,19 @@ namespace Esiur.Resource
|
|||||||
public Instance(uint id, string name, IResource resource, IStore store, ResourceTemplate customTemplate = null, ulong age = 0)
|
public Instance(uint id, string name, IResource resource, IStore store, ResourceTemplate customTemplate = null, ulong age = 0)
|
||||||
{
|
{
|
||||||
this.store = store;
|
this.store = store;
|
||||||
this.resource = resource;
|
this.resource = new WeakReference<IResource>(resource);
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.instanceAge = age;
|
this.instanceAge = age;
|
||||||
|
|
||||||
this.attributes = new KeyList<string, object>(this);
|
this.attributes = new KeyList<string, object>(this);
|
||||||
children = new AutoList<IResource, Instance>(this);
|
//children = new AutoList<IResource, Instance>(this);
|
||||||
parents = new AutoList<IResource, Instance>(this);
|
//parents = new AutoList<IResource, Instance>(this);
|
||||||
managers = new AutoList<IPermissionsManager, Instance>(this);
|
managers = new AutoList<IPermissionsManager, Instance>(this);
|
||||||
children.OnAdd += Children_OnAdd;
|
//children.OnAdd += Children_OnAdd;
|
||||||
children.OnRemoved += Children_OnRemoved;
|
//children.OnRemoved += Children_OnRemoved;
|
||||||
parents.OnAdd += Parents_OnAdd;
|
//parents.OnAdd += Parents_OnAdd;
|
||||||
parents.OnRemoved += Parents_OnRemoved;
|
//parents.OnRemoved += Parents_OnRemoved;
|
||||||
|
|
||||||
resource.OnDestroy += Resource_OnDestroy;
|
resource.OnDestroy += Resource_OnDestroy;
|
||||||
|
|
||||||
@ -715,7 +812,7 @@ namespace Esiur.Resource
|
|||||||
// connect events
|
// connect events
|
||||||
Type t = ResourceProxy.GetBaseType(resource);
|
Type t = ResourceProxy.GetBaseType(resource);
|
||||||
|
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
var events = t.GetTypeInfo().GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
|
var events = t.GetTypeInfo().GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -783,7 +880,12 @@ namespace Esiur.Resource
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Children_OnRemoved(Instance parent, IResource value)
|
|
||||||
|
//IQueryable<IResource> Children => store.GetChildren(this);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* private void Children_OnRemoved(Instance parent, IResource value)
|
||||||
{
|
{
|
||||||
value.Instance.parents.Remove(resource);
|
value.Instance.parents.Remove(resource);
|
||||||
}
|
}
|
||||||
@ -804,7 +906,7 @@ namespace Esiur.Resource
|
|||||||
if (!value.Instance.children.Contains(resource))
|
if (!value.Instance.children.Contains(resource))
|
||||||
value.Instance.children.Add(resource);
|
value.Instance.children.Add(resource);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
private void Resource_OnDestroy(object sender)
|
private void Resource_OnDestroy(object sender)
|
||||||
{
|
{
|
||||||
|
@ -36,7 +36,7 @@ namespace Esiur.Resource
|
|||||||
|
|
||||||
public virtual void Destroy()
|
public virtual void Destroy()
|
||||||
{
|
{
|
||||||
|
OnDestroy?.Invoke(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual AsyncReply<bool> Trigger(ResourceTrigger trigger)
|
public virtual AsyncReply<bool> Trigger(ResourceTrigger trigger)
|
||||||
@ -51,5 +51,10 @@ namespace Esiur.Resource
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~Resource()
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
28
Esiur/Resource/ResourceQuery.cs
Normal file
28
Esiur/Resource/ResourceQuery.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Esiur.Resource
|
||||||
|
{
|
||||||
|
public class ResourceQuery : IQueryable<IResource>
|
||||||
|
{
|
||||||
|
public Type ElementType => throw new NotImplementedException();
|
||||||
|
|
||||||
|
public Expression Expression => throw new NotImplementedException();
|
||||||
|
|
||||||
|
public IQueryProvider Provider => throw new NotImplementedException();
|
||||||
|
|
||||||
|
public IEnumerator<IResource> GetEnumerator()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -139,7 +139,7 @@ namespace Esiur.Resource.Template
|
|||||||
className = type.FullName;
|
className = type.FullName;
|
||||||
|
|
||||||
|
|
||||||
#if NETSTANDARD1_5
|
#if NETSTANDARD
|
||||||
PropertyInfo[] propsInfo = type.GetTypeInfo().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
|
PropertyInfo[] propsInfo = type.GetTypeInfo().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
|
||||||
EventInfo[] eventsInfo = type.GetTypeInfo().GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
|
EventInfo[] eventsInfo = type.GetTypeInfo().GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
|
||||||
MethodInfo[] methodsInfo = type.GetTypeInfo().GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
|
MethodInfo[] methodsInfo = type.GetTypeInfo().GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
|
||||||
|
@ -32,6 +32,8 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Esiur.Net.IIP;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace Esiur.Resource
|
namespace Esiur.Resource
|
||||||
{
|
{
|
||||||
@ -40,13 +42,13 @@ namespace Esiur.Resource
|
|||||||
{
|
{
|
||||||
//static byte prefixCounter;
|
//static byte prefixCounter;
|
||||||
|
|
||||||
static AutoList<IResource, Instance> stores = new AutoList<IResource, Instance>(null);
|
static AutoList<IStore, Instance> stores = new AutoList<IStore, Instance>(null);
|
||||||
static Dictionary<uint, IResource> resources = new Dictionary<uint, IResource>();
|
static Dictionary<uint, WeakReference<IResource>> resources = new Dictionary<uint, WeakReference<IResource>>();
|
||||||
static uint resourceCounter = 0;
|
static uint resourceCounter = 0;
|
||||||
|
|
||||||
static KeyList<Guid, ResourceTemplate> templates = new KeyList<Guid, ResourceTemplate>();
|
static KeyList<Guid, ResourceTemplate> templates = new KeyList<Guid, ResourceTemplate>();
|
||||||
|
|
||||||
static bool storeIsOpen = false;
|
static bool warehouseIsOpen = false;
|
||||||
|
|
||||||
public delegate void StoreConnectedEvent(IStore store, string name);
|
public delegate void StoreConnectedEvent(IStore store, string name);
|
||||||
public delegate void StoreDisconnectedEvent(IStore store);
|
public delegate void StoreDisconnectedEvent(IStore store);
|
||||||
@ -54,7 +56,15 @@ namespace Esiur.Resource
|
|||||||
public static event StoreConnectedEvent StoreConnected;
|
public static event StoreConnectedEvent StoreConnected;
|
||||||
public static event StoreDisconnectedEvent StoreDisconnected;
|
public static event StoreDisconnectedEvent StoreDisconnected;
|
||||||
|
|
||||||
public static KeyList<string, Func<IStore>> Protocols { get; } = new KeyList<string, Func<IStore>>();
|
public static KeyList<string, Func<IStore>> Protocols { get; } = getSupportedProtocols();
|
||||||
|
|
||||||
|
|
||||||
|
static KeyList<string, Func<IStore>> getSupportedProtocols()
|
||||||
|
{
|
||||||
|
var rt = new KeyList<string, Func<IStore>>();
|
||||||
|
rt.Add("iip", () => new DistributedConnection());
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a store by its name.
|
/// Get a store by its name.
|
||||||
@ -77,7 +87,13 @@ namespace Esiur.Resource
|
|||||||
public static AsyncReply<IResource> Get(uint id)
|
public static AsyncReply<IResource> Get(uint id)
|
||||||
{
|
{
|
||||||
if (resources.ContainsKey(id))
|
if (resources.ContainsKey(id))
|
||||||
return new AsyncReply<IResource>(resources[id]);
|
{
|
||||||
|
IResource r;
|
||||||
|
if (resources[id].TryGetTarget(out r))
|
||||||
|
return new AsyncReply<IResource>(r);
|
||||||
|
else
|
||||||
|
return new AsyncReply<IResource>(null);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return new AsyncReply<IResource>(null);
|
return new AsyncReply<IResource>(null);
|
||||||
}
|
}
|
||||||
@ -109,7 +125,11 @@ namespace Esiur.Resource
|
|||||||
|
|
||||||
var rBag = new AsyncBag<bool>();
|
var rBag = new AsyncBag<bool>();
|
||||||
foreach (var rk in resources)
|
foreach (var rk in resources)
|
||||||
rBag.Add(rk.Value.Trigger(ResourceTrigger.SystemInitialized));
|
{
|
||||||
|
IResource r;
|
||||||
|
if (rk.Value.TryGetTarget(out r))
|
||||||
|
rBag.Add(r.Trigger(ResourceTrigger.SystemInitialized));
|
||||||
|
}
|
||||||
|
|
||||||
rBag.Seal();
|
rBag.Seal();
|
||||||
|
|
||||||
@ -123,7 +143,7 @@ namespace Esiur.Resource
|
|||||||
}
|
}
|
||||||
|
|
||||||
rt.Trigger(true);
|
rt.Trigger(true);
|
||||||
storeIsOpen = true;
|
warehouseIsOpen = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
@ -142,15 +162,30 @@ namespace Esiur.Resource
|
|||||||
var bag = new AsyncBag<bool>();
|
var bag = new AsyncBag<bool>();
|
||||||
|
|
||||||
foreach (var resource in resources.Values)
|
foreach (var resource in resources.Values)
|
||||||
if (!(resource is IStore))
|
{
|
||||||
bag.Add(resource.Trigger(ResourceTrigger.Terminate));
|
IResource r;
|
||||||
|
if (resource.TryGetTarget(out r))
|
||||||
|
{
|
||||||
|
if (!(r is IStore))
|
||||||
|
bag.Add(r.Trigger(ResourceTrigger.Terminate));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var store in stores)
|
foreach (var store in stores)
|
||||||
bag.Add(store.Trigger(ResourceTrigger.Terminate));
|
bag.Add(store.Trigger(ResourceTrigger.Terminate));
|
||||||
|
|
||||||
|
|
||||||
foreach (var resource in resources.Values)
|
foreach (var resource in resources.Values)
|
||||||
if (!(resource is IStore))
|
{
|
||||||
bag.Add(resource.Trigger(ResourceTrigger.SystemTerminated));
|
IResource r;
|
||||||
|
if (resource.TryGetTarget(out r))
|
||||||
|
{
|
||||||
|
if (!(r is IStore))
|
||||||
|
bag.Add(r.Trigger(ResourceTrigger.SystemTerminated));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
foreach (var store in stores)
|
foreach (var store in stores)
|
||||||
bag.Add(store.Trigger(ResourceTrigger.SystemTerminated));
|
bag.Add(store.Trigger(ResourceTrigger.SystemTerminated));
|
||||||
@ -174,7 +209,8 @@ namespace Esiur.Resource
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static IResource[] QureyIn(string[] path, int index, AutoList<IResource, Instance> resources)
|
/*
|
||||||
|
private static IResource[] QureyIn(string[] path, int index, IEnumerable<IResource> resources)// AutoList<IResource, Instance> resources)
|
||||||
{
|
{
|
||||||
var rt = new List<IResource>();
|
var rt = new List<IResource>();
|
||||||
|
|
||||||
@ -191,18 +227,16 @@ namespace Esiur.Resource
|
|||||||
else
|
else
|
||||||
foreach (IResource child in resources)
|
foreach (IResource child in resources)
|
||||||
if (child.Instance.Name == path[index])
|
if (child.Instance.Name == path[index])
|
||||||
rt.AddRange(QureyIn(path, index+1, child.Instance.Children));
|
rt.AddRange(QureyIn(path, index+1, child.Instance.Children<IResource>()));
|
||||||
|
|
||||||
return rt.ToArray();
|
return rt.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AsyncReply<IResource[]> Query(string path)
|
public static AsyncReply<IResource[]> Query(string path)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
if (path == null || path == "")
|
if (path == null || path == "")
|
||||||
{
|
{
|
||||||
var roots = stores.Where(s => s.Instance.Parents.Count == 0).ToArray();
|
var roots = stores.Where(s => s.Instance.Parents<IResource>().Count() == 0).ToArray();
|
||||||
return new AsyncReply<IResource[]>(roots);
|
return new AsyncReply<IResource[]>(roots);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -229,6 +263,51 @@ namespace Esiur.Resource
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static async Task<IResource[]> Query(string path)
|
||||||
|
{
|
||||||
|
var rt = new AsyncReply<IResource[]>();
|
||||||
|
|
||||||
|
var p = path.Trim().Split('/');
|
||||||
|
IResource resource;
|
||||||
|
|
||||||
|
foreach (var store in stores)
|
||||||
|
if (p[0] == store.Instance.Name)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (p.Length == 1)
|
||||||
|
return new IResource[] { store };
|
||||||
|
|
||||||
|
var res = await store.Get(String.Join("/", p.Skip(1).ToArray()));
|
||||||
|
if (res != null)
|
||||||
|
return new IResource[] { res };
|
||||||
|
|
||||||
|
|
||||||
|
resource = store;
|
||||||
|
for (var i = 1; i < p.Length; i++)
|
||||||
|
{
|
||||||
|
var children = await resource.Instance.Children<IResource>(p[i]);
|
||||||
|
if (children.Length > 0)
|
||||||
|
{
|
||||||
|
if (i == p.Length - 1)
|
||||||
|
return children;
|
||||||
|
else
|
||||||
|
resource = children[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a resource by its path.
|
/// Get a resource by its path.
|
||||||
@ -236,38 +315,15 @@ namespace Esiur.Resource
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path"></param>
|
/// <param name="path"></param>
|
||||||
/// <returns>Resource instance.</returns>
|
/// <returns>Resource instance.</returns>
|
||||||
public static AsyncReply<IResource> Get(string path, Structure attributes = null, IResource parent = null, IPermissionsManager manager = null)
|
public static AsyncReply<IResource> Get(string path, object attributes = null, IResource parent = null, IPermissionsManager manager = null)
|
||||||
{
|
{
|
||||||
|
|
||||||
var p = path.Split('/');
|
|
||||||
IResource res;
|
|
||||||
|
|
||||||
foreach(IStore d in stores)
|
|
||||||
if (p[0] == d.Instance.Name)
|
|
||||||
{
|
|
||||||
var i = 1;
|
|
||||||
res = d;
|
|
||||||
while(p.Length > i)
|
|
||||||
{
|
|
||||||
var si = i;
|
|
||||||
|
|
||||||
foreach (IResource r in res.Instance.Children)
|
var rt = new AsyncReply<IResource>();
|
||||||
if (r.Instance.Name == p[i])
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
res = r;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (si == i)
|
|
||||||
// not found, ask the store
|
|
||||||
return d.Get(path.Substring(p[0].Length + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new AsyncReply<IResource>(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Should we create a new store ?
|
// Should we create a new store ?
|
||||||
|
|
||||||
if (path.Contains("://"))
|
if (path.Contains("://"))
|
||||||
{
|
{
|
||||||
var url = path.Split(new string[] { "://" }, 2, StringSplitOptions.None);
|
var url = path.Split(new string[] { "://" }, 2, StringSplitOptions.None);
|
||||||
@ -275,17 +331,18 @@ namespace Esiur.Resource
|
|||||||
var pathname = string.Join("/", url[1].Split(new char[] { '/' }).Skip(1));
|
var pathname = string.Join("/", url[1].Split(new char[] { '/' }).Skip(1));
|
||||||
|
|
||||||
|
|
||||||
var rt = new AsyncReply<IResource>();
|
|
||||||
|
|
||||||
if (Protocols.ContainsKey(url[0]))
|
if (Protocols.ContainsKey(url[0]))
|
||||||
{
|
{
|
||||||
var handler = Protocols[url[0]];
|
var handler = Protocols[url[0]];
|
||||||
|
|
||||||
var store = handler();// Activator.CreateInstance(handler.GetType()) as IStore;
|
var store = handler();
|
||||||
Put(store, url[0] + "://" + hostname, null, parent, null, 0, manager, attributes);
|
Put(store, hostname, null, parent, null, 0, manager, attributes);
|
||||||
|
|
||||||
|
|
||||||
store.Trigger(ResourceTrigger.Open).Then(x => {
|
store.Trigger(ResourceTrigger.Open).Then(x => {
|
||||||
|
|
||||||
|
warehouseIsOpen = true;
|
||||||
|
|
||||||
if (pathname.Length > 0 && pathname != "")
|
if (pathname.Length > 0 && pathname != "")
|
||||||
store.Get(pathname).Then(r => {
|
store.Get(pathname).Then(r => {
|
||||||
rt.Trigger(r);
|
rt.Trigger(r);
|
||||||
@ -296,13 +353,24 @@ namespace Esiur.Resource
|
|||||||
rt.TriggerError(e);
|
rt.TriggerError(e);
|
||||||
Warehouse.Remove(store);
|
Warehouse.Remove(store);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
return rt;
|
return rt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return new AsyncReply<IResource>(null);
|
Query(path).ContinueWith(rs =>
|
||||||
|
{
|
||||||
|
// rt.TriggerError(new Exception());
|
||||||
|
if (rs.Result != null && rs.Result.Length > 0)
|
||||||
|
rt.Trigger(rs.Result[0]);
|
||||||
|
else
|
||||||
|
rt.Trigger(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -312,12 +380,31 @@ namespace Esiur.Resource
|
|||||||
/// <param name="name">Resource name.</param>
|
/// <param name="name">Resource name.</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 void Put(IResource resource, string name, IStore store = null, IResource parent = null, ResourceTemplate customTemplate = null, ulong age = 0, IPermissionsManager manager = null, Structure attributes = null)
|
public static void Put(IResource resource, string name, IStore store = null, IResource parent = null, ResourceTemplate customTemplate = null, ulong age = 0, IPermissionsManager manager = null, object attributes = null)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (store == null)
|
||||||
|
{
|
||||||
|
// assign parent as a store
|
||||||
|
if (parent is IStore)
|
||||||
|
store = (IStore)parent;
|
||||||
|
// assign parent's store as a store
|
||||||
|
else if (parent != null)
|
||||||
|
store = parent.Instance.Store;
|
||||||
|
// assign self as a store (root store)
|
||||||
|
else if (resource is IStore)
|
||||||
|
{
|
||||||
|
store = (IStore)resource;
|
||||||
|
stores.Add(resource as IStore);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new Exception("Can't find a store for the resource.");
|
||||||
|
}
|
||||||
|
|
||||||
resource.Instance = new Instance(resourceCounter++, name, resource, store, customTemplate, age);
|
resource.Instance = new Instance(resourceCounter++, name, resource, store, customTemplate, age);
|
||||||
|
|
||||||
if (attributes != null)
|
if (attributes != null)
|
||||||
resource.Instance.SetAttributes(attributes);
|
resource.Instance.SetAttributes(Structure.FromObject(attributes));
|
||||||
|
|
||||||
if (manager != null)
|
if (manager != null)
|
||||||
resource.Instance.Managers.Add(manager);
|
resource.Instance.Managers.Add(manager);
|
||||||
@ -325,6 +412,8 @@ namespace Esiur.Resource
|
|||||||
if (store == parent)
|
if (store == parent)
|
||||||
parent = null;
|
parent = null;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
if (parent == null)
|
if (parent == null)
|
||||||
{
|
{
|
||||||
if (!(resource is IStore))
|
if (!(resource is IStore))
|
||||||
@ -332,20 +421,26 @@ namespace Esiur.Resource
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
parent.Instance.Children.Add(resource);
|
parent.Instance.Children.Add(resource);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
if (resource is IStore)
|
if (resource is IStore)
|
||||||
{
|
|
||||||
stores.Add(resource as IStore);
|
|
||||||
StoreConnected?.Invoke(resource as IStore, name);
|
StoreConnected?.Invoke(resource as IStore, name);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
store.Put(resource);
|
store.Put(resource);
|
||||||
|
|
||||||
resources.Add(resource.Instance.Id, resource);
|
|
||||||
|
|
||||||
if (storeIsOpen)
|
if (parent != null)
|
||||||
|
{
|
||||||
|
parent.Instance.Store.AddChild(parent, resource);
|
||||||
|
store.AddParent(resource, parent);
|
||||||
|
//store.AddChild(parent, resource);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
resources.Add(resource.Instance.Id, new WeakReference<IResource>(resource));
|
||||||
|
|
||||||
|
if (warehouseIsOpen)
|
||||||
resource.Trigger(ResourceTrigger.Initialize);
|
resource.Trigger(ResourceTrigger.Initialize);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -430,9 +525,17 @@ namespace Esiur.Resource
|
|||||||
stores.Remove(resource as IStore);
|
stores.Remove(resource as IStore);
|
||||||
|
|
||||||
// remove all objects associated with the store
|
// remove all objects associated with the store
|
||||||
var toBeRemoved = resources.Values.Where(x => x.Instance.Store == resource);
|
var toBeRemoved = resources.Values.Where(x => {
|
||||||
|
IResource r;
|
||||||
|
return x.TryGetTarget(out r) && r.Instance.Store == resource;
|
||||||
|
});
|
||||||
|
|
||||||
foreach (var o in toBeRemoved)
|
foreach (var o in toBeRemoved)
|
||||||
Remove(o);
|
{
|
||||||
|
IResource r;
|
||||||
|
if (o.TryGetTarget(out r))
|
||||||
|
Remove(r);
|
||||||
|
}
|
||||||
|
|
||||||
StoreDisconnected?.Invoke(resource as IStore);
|
StoreDisconnected?.Invoke(resource as IStore);
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ using Esiur.Security.Authority;
|
|||||||
|
|
||||||
namespace Esiur.Security.Permissions
|
namespace Esiur.Security.Permissions
|
||||||
{
|
{
|
||||||
public class ParentalPermissionsManager : IPermissionsManager
|
public class StorePermissionsManager : IPermissionsManager
|
||||||
{
|
{
|
||||||
Structure settings;
|
Structure settings;
|
||||||
|
|
||||||
@ -41,20 +41,12 @@ namespace Esiur.Security.Permissions
|
|||||||
|
|
||||||
public Ruling Applicable(IResource resource, Session session, ActionType action, MemberTemplate member, object inquirer = null)
|
public Ruling Applicable(IResource resource, Session session, ActionType action, MemberTemplate member, object inquirer = null)
|
||||||
{
|
{
|
||||||
|
return resource.Instance.Store.Instance.Applicable(session, action, member, inquirer);
|
||||||
foreach (IResource parent in resource.Instance.Parents)
|
|
||||||
{
|
|
||||||
var ruling = parent.Instance.Applicable(session, action, member, inquirer);
|
|
||||||
if (ruling != Ruling.DontCare)
|
|
||||||
return ruling;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ruling.DontCare;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Initialize(Structure settings, IResource resource)
|
public bool Initialize(Structure settings, IResource resource)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -33,19 +33,31 @@ namespace Esiur.Stores
|
|||||||
|
|
||||||
public AsyncReply<IResource> Get(string path)
|
public AsyncReply<IResource> Get(string path)
|
||||||
{
|
{
|
||||||
|
foreach (var r in resources)
|
||||||
|
if (r.Value.Instance.Name == path)
|
||||||
|
return new AsyncReply<IResource>(r.Value);
|
||||||
|
|
||||||
return new AsyncReply<IResource>(null);
|
return new AsyncReply<IResource>(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Put(IResource resource)
|
public bool Put(IResource resource)
|
||||||
{
|
{
|
||||||
resources.Add(resource.Instance.Id, resource);
|
resources.Add(resource.Instance.Id, resource);// new WeakReference<IResource>(resource));
|
||||||
|
resource.Instance.Attributes["children"] = new AutoList<IResource, Instance>(resource.Instance);
|
||||||
|
resource.Instance.Attributes["parents"] = new AutoList<IResource, Instance>(resource.Instance);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AsyncReply<IResource> Retrieve(uint iid)
|
public AsyncReply<IResource> Retrieve(uint iid)
|
||||||
{
|
{
|
||||||
if (resources.ContainsKey(iid))
|
if (resources.ContainsKey(iid))
|
||||||
return new AsyncReply<IResource>(resources[iid]);
|
{
|
||||||
|
if (resources.ContainsKey(iid))// .TryGetTarget(out r))
|
||||||
|
return new AsyncReply<IResource>(resources[iid]);
|
||||||
|
else
|
||||||
|
return new AsyncReply<IResource>(null);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return new AsyncReply<IResource>(null);
|
return new AsyncReply<IResource>(null);
|
||||||
}
|
}
|
||||||
@ -76,5 +88,58 @@ namespace Esiur.Stores
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AsyncReply<bool> AddChild(IResource parent, IResource child)
|
||||||
|
{
|
||||||
|
if (parent.Instance.Store == this)
|
||||||
|
{
|
||||||
|
(parent.Instance.Attributes["children"] as AutoList<IResource, Instance>).Add(child);
|
||||||
|
return new AsyncReply<bool>(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return new AsyncReply<bool>(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncReply<bool> RemoveChild(IResource parent, IResource child)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncReply<bool> AddParent(IResource resource, IResource parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (resource.Instance.Store == this)
|
||||||
|
{
|
||||||
|
(resource.Instance.Attributes["parents"] as AutoList<IResource, Instance>).Add(parent);
|
||||||
|
return new AsyncReply<bool>(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return new AsyncReply<bool>(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncReply<bool> RemoveParent(IResource child, IResource parent)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncBag<T> Children<T>(IResource resource, string name) where T : IResource
|
||||||
|
{
|
||||||
|
var children = (resource.Instance.Attributes["children"] as AutoList<IResource, Instance>);
|
||||||
|
|
||||||
|
if (name == null)
|
||||||
|
return new AsyncBag<T>(children.Where(x=>x is T).Select(x=>(T)x).ToArray());
|
||||||
|
else
|
||||||
|
return new AsyncBag<T>(children.Where(x => x is T && x.Instance.Name == name).Select(x => (T)x).ToArray());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncBag<T> Parents<T>(IResource resource, string name) where T : IResource
|
||||||
|
{
|
||||||
|
var parents = (resource.Instance.Attributes["parents"] as AutoList<IResource, Instance>);
|
||||||
|
|
||||||
|
if (name == null)
|
||||||
|
return new AsyncBag<T>(parents.Where(x => x is T).Select(x => (T)x).ToArray());
|
||||||
|
else
|
||||||
|
return new AsyncBag<T>(parents.Where(x => x is T && x.Instance.Name == name).Select(x => (T)x).ToArray());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
118
Esiur/Stores/TemporaryStore.cs
Normal file
118
Esiur/Stores/TemporaryStore.cs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
using Esiur.Resource;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Esiur.Core;
|
||||||
|
using Esiur.Data;
|
||||||
|
using Esiur.Resource.Template;
|
||||||
|
|
||||||
|
namespace Esiur.Stores
|
||||||
|
{
|
||||||
|
public class TemporaryStore : IStore
|
||||||
|
{
|
||||||
|
public Instance Instance { get; set; }
|
||||||
|
|
||||||
|
public event DestroyedEvent OnDestroy;
|
||||||
|
|
||||||
|
Dictionary<uint, WeakReference> resources = new Dictionary<uint, WeakReference>();
|
||||||
|
|
||||||
|
public void Destroy()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Link(IResource resource)
|
||||||
|
{
|
||||||
|
if (resource.Instance.Store == this)
|
||||||
|
return this.Instance.Name + "/" + resource.Instance.Id;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncReply<IResource> Get(string path)
|
||||||
|
{
|
||||||
|
foreach (var r in resources)
|
||||||
|
if (r.Value.IsAlive && (r.Value.Target as IResource).Instance.Name == path)
|
||||||
|
return new AsyncReply<IResource>(r.Value.Target as IResource);
|
||||||
|
|
||||||
|
return new AsyncReply<IResource>(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Put(IResource resource)
|
||||||
|
{
|
||||||
|
resources.Add(resource.Instance.Id, new WeakReference( resource));// new WeakReference<IResource>(resource));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncReply<IResource> Retrieve(uint iid)
|
||||||
|
{
|
||||||
|
if (resources.ContainsKey(iid))
|
||||||
|
{
|
||||||
|
if (resources.ContainsKey(iid) && resources[iid].IsAlive)// .TryGetTarget(out r))
|
||||||
|
return new AsyncReply<IResource>(resources[iid].Target as IResource);
|
||||||
|
else
|
||||||
|
return new AsyncReply<IResource>(null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return new AsyncReply<IResource>(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
|
||||||
|
{
|
||||||
|
return new AsyncReply<bool>(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Record(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> GetRecord(IResource resource, DateTime fromDate, DateTime toDate)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(IResource resource)
|
||||||
|
{
|
||||||
|
resources.Remove(resource.Instance.Id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Modify(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncReply<bool> AddChild(IResource parent, IResource child)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncReply<bool> RemoveChild(IResource parent, IResource child)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncBag<T> Parents<T>(IResource resource, string name) where T : IResource
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
BIN
Esiurd.sln
Normal file
BIN
Esiurd.sln
Normal file
Binary file not shown.
@ -9,7 +9,7 @@ using System.Threading;
|
|||||||
|
|
||||||
namespace Test
|
namespace Test
|
||||||
{
|
{
|
||||||
public class MyObject : Resource
|
public class MyObject : EntryPoint
|
||||||
{
|
{
|
||||||
|
|
||||||
[ResourceEvent]
|
[ResourceEvent]
|
||||||
@ -90,6 +90,16 @@ namespace Test
|
|||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override AsyncReply<IResource[]> Query(string path, DistributedConnection sender)
|
||||||
|
{
|
||||||
|
return new AsyncReply<IResource[]>(new IResource[] { this });
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Create()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
[ResourceProperty]
|
[ResourceProperty]
|
||||||
public Structure Info
|
public Structure Info
|
||||||
{
|
{
|
||||||
|
@ -51,8 +51,6 @@ namespace Test
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
Warehouse.Protocols.Add("iip", () => new DistributedConnection());
|
|
||||||
|
|
||||||
// Create stores to keep objects.
|
// Create stores to keep objects.
|
||||||
var system = Warehouse.New<MemoryStore>("system");
|
var system = Warehouse.New<MemoryStore>("system");
|
||||||
var remote = Warehouse.New<MemoryStore>("remote");
|
var remote = Warehouse.New<MemoryStore>("remote");
|
||||||
@ -64,12 +62,12 @@ namespace Test
|
|||||||
// Set membership which handles authentication.
|
// Set membership which handles authentication.
|
||||||
iip.Membership = Warehouse.New<MyMembership>("ms", system);
|
iip.Membership = Warehouse.New<MyMembership>("ms", system);
|
||||||
// Start the server on port 5000.
|
// Start the server on port 5000.
|
||||||
iip.Start(new TCPSocket(new System.Net.IPEndPoint(System.Net.IPAddress.Any, 5000)), 600000, 60000);
|
iip.Start(new TCPSocket(new System.Net.IPEndPoint(System.Net.IPAddress.Any, 500)), 600000, 60000);
|
||||||
|
|
||||||
|
|
||||||
// Create http server to handle IIP over Websockets
|
// Create http server to handle IIP over Websockets
|
||||||
var http = Warehouse.New<HTTPServer>("http", system);
|
var http = Warehouse.New<HTTPServer>("http", system);
|
||||||
http.Start(new TCPSocket(new System.Net.IPEndPoint(System.Net.IPAddress.Any, 5001)), 600000, 60000);
|
http.Start(new TCPSocket(new System.Net.IPEndPoint(System.Net.IPAddress.Any, 501)), 600000, 60000);
|
||||||
|
|
||||||
// Create IIP over Websocket HTTP module and give it to HTTP server.
|
// Create IIP over Websocket HTTP module and give it to HTTP server.
|
||||||
var wsOverHttp = Warehouse.New<IIPoWS>("IIPoWS", system, http);
|
var wsOverHttp = Warehouse.New<IIPoWS>("IIPoWS", system, http);
|
||||||
@ -106,13 +104,10 @@ namespace Test
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
else
|
else
|
||||||
localObject = (MyObject)(await Warehouse.Get("db/my"));//.Then((o) => { myObject = (MyObject)o; });
|
localObject = (MyObject)(await Warehouse.Get("db/my"));
|
||||||
|
|
||||||
|
|
||||||
//var obj = ProxyObject.<MyObject>();
|
iip.EntryPoint = localObject;
|
||||||
//Warehouse.Put(obj, "dd", system);
|
|
||||||
//obj.Level2= 33;
|
|
||||||
|
|
||||||
|
|
||||||
Warehouse.StoreConnected += (store, name) =>
|
Warehouse.StoreConnected += (store, name) =>
|
||||||
{
|
{
|
||||||
@ -160,7 +155,7 @@ namespace Test
|
|||||||
private static async void TestClient()
|
private static async void TestClient()
|
||||||
{
|
{
|
||||||
|
|
||||||
remoteObject = await Warehouse.Get("iip://localhost:5000/db/my", new Structure() { ["username"] = "demo", ["password"] = "1234" });
|
remoteObject = await Warehouse.Get("iip://localhost:500/db/my", new { username= "demo", password = 1234 });
|
||||||
|
|
||||||
dynamic x = remoteObject;
|
dynamic x = remoteObject;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user