mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2025-06-26 21:13:13 +00:00
WeakRef
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard1.5</TargetFramework>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<Authors>Ahmed Kh. Zamil</Authors>
|
||||
<Company>Esiur</Company>
|
||||
<Product>Esiur MongoDB Store</Product>
|
||||
@ -11,12 +11,12 @@
|
||||
<PackageProjectUrl>http://www.esiur.com</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/esiur/esiur-dotnet/</RepositoryUrl>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
<Version>1.2.5</Version>
|
||||
<Version>1.2.8</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MongoDB.Bson" Version="2.4.4" />
|
||||
<PackageReference Include="MongoDB.Driver" Version="2.4.4" />
|
||||
<PackageReference Include="MongoDB.Bson" Version="2.9.1" />
|
||||
<PackageReference Include="MongoDB.Driver" Version="2.9.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -23,15 +23,22 @@ namespace Esiur.Stores.MongoDB
|
||||
MongoClient client;
|
||||
IMongoDatabase database;
|
||||
IMongoCollection<BsonDocument> resourcesCollection;
|
||||
|
||||
//List<IResource> storeParents = new List<IResource>();
|
||||
//List<IResource> storeChildren = new List<IResource>();
|
||||
|
||||
//string collectionName;
|
||||
//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()
|
||||
@ -39,7 +46,7 @@ namespace Esiur.Stores.MongoDB
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public bool Record(IResource resource, string propertyName, object value, ulong age, DateTime date)
|
||||
{
|
||||
var objectId = resource.Instance.Attributes["objectId"].ToString();
|
||||
@ -77,21 +84,35 @@ namespace Esiur.Stores.MongoDB
|
||||
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 list = resourcesCollection.Find(filter).ToList();
|
||||
if (list.Count == 0)
|
||||
return new AsyncReply<IResource>(null);
|
||||
return new AsyncReply<T>(default(T));
|
||||
var document = list[0];
|
||||
|
||||
var type = Type.GetType(document["classname"].AsString);
|
||||
|
||||
if (type == null)
|
||||
return new AsyncReply<IResource>(null);
|
||||
return new AsyncReply<T>(default(T));
|
||||
|
||||
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);
|
||||
|
||||
@ -100,14 +121,16 @@ namespace Esiur.Stores.MongoDB
|
||||
var children = document["children"].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);
|
||||
});
|
||||
|
||||
var bag = new AsyncBag<object>();
|
||||
|
||||
/*
|
||||
foreach (var p in parents)
|
||||
{
|
||||
{
|
||||
var ap = Warehouse.Get(p.AsString);
|
||||
bag.Add(ap);
|
||||
ap.Then((x) =>
|
||||
@ -128,6 +151,10 @@ namespace Esiur.Stores.MongoDB
|
||||
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
|
||||
foreach (var m in this.Instance.Managers)
|
||||
@ -154,27 +181,34 @@ namespace Esiur.Stores.MongoDB
|
||||
|
||||
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);
|
||||
resource.Instance.LoadProperty(v.Name,
|
||||
(ulong)valueInfo["age"].AsInt64,
|
||||
valueInfo["modification"].ToUniversalTime(),
|
||||
x);
|
||||
});
|
||||
|
||||
bag.Add(av);
|
||||
}
|
||||
|
||||
bag.Seal();
|
||||
|
||||
var rt = new AsyncReply<IResource>();
|
||||
var rt = new AsyncReply<T>();
|
||||
|
||||
bag.Then((x) =>
|
||||
{
|
||||
rt.Trigger(resource);
|
||||
if (resource is T)
|
||||
rt.Trigger(resource);
|
||||
else
|
||||
rt.Trigger(null);
|
||||
});
|
||||
|
||||
bag.Seal();
|
||||
|
||||
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
@ -230,7 +264,7 @@ namespace Esiur.Stores.MongoDB
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
return new AsyncReply<object>(value.RawValue);
|
||||
}
|
||||
}
|
||||
@ -242,16 +276,22 @@ namespace Esiur.Stores.MongoDB
|
||||
if (p[0] == "id")
|
||||
{
|
||||
// load from Id
|
||||
return Fetch<IResource>(p[1]);
|
||||
|
||||
|
||||
/*
|
||||
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"];
|
||||
@ -259,11 +299,17 @@ namespace Esiur.Stores.MongoDB
|
||||
|
||||
public bool Put(IResource resource)
|
||||
{
|
||||
PutResource(resource).Wait();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<bool> PutResource(IResource resource)
|
||||
{
|
||||
var attrs = resource.Instance.GetAttributes();
|
||||
|
||||
foreach (var kv in resources)
|
||||
if (kv.Value == resource)
|
||||
if (kv.Value.Target == resource)
|
||||
{
|
||||
resource.Instance.Attributes.Add("objectId", kv.Key);
|
||||
return true;
|
||||
@ -290,34 +336,58 @@ namespace Esiur.Stores.MongoDB
|
||||
|
||||
var template = resource.Instance.Template;
|
||||
|
||||
foreach (IResource c in resource.Instance.Children)
|
||||
children.Add(c.Instance.Link);
|
||||
// setup attributes
|
||||
resource.Instance.Attributes["children"] = new string[0];
|
||||
resource.Instance.Attributes["parents"] = new string[] { this.Instance.Link };
|
||||
|
||||
// copy old children (in case we are moving a resource from a store to another.
|
||||
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);
|
||||
}
|
||||
|
||||
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 filter = Builders<BsonDocument>.Filter.Eq("_id", document["_id"]);
|
||||
// var update = Builders<BsonDocument>.Update
|
||||
// .Set("values", values);
|
||||
// col.UpdateOne(filter, update);
|
||||
|
||||
|
||||
/*
|
||||
@ -340,6 +410,7 @@ namespace Esiur.Stores.MongoDB
|
||||
|
||||
//resource.Instance.Attributes["objectId"] = document["_id"].ToString();
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -409,7 +480,7 @@ namespace Esiur.Stores.MongoDB
|
||||
|
||||
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"]));
|
||||
@ -454,8 +525,10 @@ namespace Esiur.Stores.MongoDB
|
||||
|
||||
resourcesCollection = this.database.GetCollection<BsonDocument>(collectionName);
|
||||
|
||||
// return new AsyncReply<bool>(true);
|
||||
// return new AsyncReply<bool>(true);
|
||||
|
||||
|
||||
/*
|
||||
var filter = new BsonDocument();
|
||||
|
||||
var list = resourcesCollection.Find(filter).ToList();
|
||||
@ -476,15 +549,24 @@ namespace Esiur.Stores.MongoDB
|
||||
|
||||
var rt = new AsyncReply<bool>();
|
||||
|
||||
bag.Then((x) => { rt.Trigger(true); });
|
||||
bag.Then((x) => {
|
||||
|
||||
// storeChildren.AddRange(x);
|
||||
rt.Trigger(true);
|
||||
|
||||
});
|
||||
|
||||
return rt;
|
||||
*/
|
||||
|
||||
return new AsyncReply<bool>(true);
|
||||
}
|
||||
else if (trigger == ResourceTrigger.Terminate)
|
||||
{
|
||||
// save all resources
|
||||
foreach (var resource in resources.Values)
|
||||
SaveResource(resource);
|
||||
if (resource.IsAlive)
|
||||
SaveResource(resource.Target as IResource);
|
||||
|
||||
return new AsyncReply<bool>(true);
|
||||
}
|
||||
@ -501,12 +583,14 @@ namespace Esiur.Stores.MongoDB
|
||||
var children = new BsonArray();
|
||||
var template = resource.Instance.Template;
|
||||
|
||||
foreach (IResource c in resource.Instance.Children)
|
||||
children.Add(c.Instance.Link);
|
||||
//foreach (IResource c in resource.Instance.Children)
|
||||
// children.Add(c.Instance.Link);
|
||||
|
||||
var plist = resource.Instance.Attributes["parents"] as string[];
|
||||
|
||||
foreach (var link in plist)// Parents)
|
||||
parents.Add(link);
|
||||
|
||||
foreach (IResource p in resource.Instance.Parents)
|
||||
parents.Add(p.Instance.Link);
|
||||
|
||||
|
||||
var values = new BsonDocument();
|
||||
|
||||
@ -536,7 +620,7 @@ namespace Esiur.Stores.MongoDB
|
||||
{
|
||||
{ "parents", parents },
|
||||
{ "children", children },
|
||||
{"attributes", attrsDoc },
|
||||
{ "attributes", attrsDoc },
|
||||
{ "classname", type.FullName + "," + type.GetTypeInfo().Assembly.GetName().Name },
|
||||
{ "name", resource.Instance.Name },
|
||||
{ "_id", new BsonObjectId(new ObjectId(resource.Instance.Attributes["objectId"].ToString())) },
|
||||
@ -576,15 +660,15 @@ namespace Esiur.Stores.MongoDB
|
||||
|
||||
var bag = new AsyncBag<object>();
|
||||
|
||||
foreach(var v in values)
|
||||
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++)
|
||||
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());
|
||||
@ -653,7 +737,7 @@ namespace Esiur.Stores.MongoDB
|
||||
|
||||
reply.Trigger(list);
|
||||
});
|
||||
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
@ -685,7 +769,7 @@ namespace Esiur.Stores.MongoDB
|
||||
|
||||
public bool Modify(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
|
||||
{
|
||||
|
||||
|
||||
|
||||
var objectId = resource.Instance.Attributes["objectId"].ToString();
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user