ln.types/odb/ODB.cs

179 lines
5.2 KiB
C#
Raw Normal View History

2019-03-13 08:22:08 +01:00
// /**
// * File: ODB.cs
// * Author: haraldwolff
// *
// * This file and it's content is copyrighted by the Author and / or copyright holder.
// * Any use wihtout proper permission is illegal and may lead to legal actions.
// *
// *
// **/
using System;
using System.IO;
using System.Collections.Generic;
2019-03-20 14:28:56 +01:00
using Castle.DynamicProxy;
using ln.types.serialize;
using Castle.Components.DictionaryAdapter;
using System.Linq;
2019-03-13 08:22:08 +01:00
namespace ln.types.odb
{
2019-03-21 14:07:08 +01:00
public class ODB<T> : ODB where T: IPersistent
2019-03-20 14:28:56 +01:00
{
public T Root
{
get => (T)RootObject;
}
public ODB(String basePath)
:base(basePath, typeof(T))
{
}
}
2019-03-21 14:07:08 +01:00
public class ODB
2019-03-13 08:22:08 +01:00
{
2019-03-20 14:28:56 +01:00
public String BasePath { get; set; }
2019-03-13 08:22:08 +01:00
2019-03-21 14:07:08 +01:00
public IPersistent RootObject { get; protected set; }
2019-03-13 08:22:08 +01:00
2019-03-20 14:28:56 +01:00
private Type RootType;
2019-03-21 14:07:08 +01:00
private Storage Storage { get; set; }
private Dictionary<Guid, PreparedObject> objectCache = new Dictionary<Guid, PreparedObject>();
2019-03-13 08:22:08 +01:00
2019-03-20 14:28:56 +01:00
public ODB(string basePath)
2019-03-13 08:22:08 +01:00
{
2019-03-20 14:28:56 +01:00
BasePath = Path.GetFullPath(basePath);
2019-03-21 14:07:08 +01:00
Storage = new ODBFileStorage(basePath);
2019-03-13 08:22:08 +01:00
}
2019-03-20 14:28:56 +01:00
public ODB(String basePath, Type rootType)
: this(basePath)
{
RootType = rootType;
Initialize();
}
2019-03-21 14:07:08 +01:00
public ODB(String basePath,IPersistent rootObject)
2019-03-20 14:28:56 +01:00
: this(basePath)
{
RootType = rootObject.GetType();
RootObject = rootObject;
Initialize();
}
private void Initialize()
{
if (RootObject == null)
{
string rootHint = Path.Combine(BasePath, "root.hint");
if (File.Exists(rootHint))
{
2019-03-21 14:07:08 +01:00
string rootID = File.ReadAllText(rootHint);
Guid persistenceID = Guid.Parse(rootID);
RootObject = LoadPersistent(persistenceID);
2019-03-20 14:28:56 +01:00
}
else
{
2019-03-21 14:07:08 +01:00
RootObject = (IPersistent)Activator.CreateInstance(RootType);
string rootID = RootObject.GetPersistenceID().ToString();
SavePersistent(RootObject);
File.WriteAllText(rootHint, rootID);
2019-03-20 14:28:56 +01:00
}
}
}
2019-03-21 07:43:39 +01:00
public bool Contains(Guid persistenceID)
{
2019-03-21 14:07:08 +01:00
return Storage.Contains(persistenceID) || objectCache.ContainsKey(persistenceID);
2019-03-20 14:28:56 +01:00
}
2019-03-21 07:43:39 +01:00
public void SavePersistent(IPersistent o) => SavePersistent(o, true);
public void SavePersistent(IPersistent o,bool recurse)
{
2019-03-21 14:07:08 +01:00
lock (this)
2019-03-21 07:43:39 +01:00
{
2019-03-21 14:07:08 +01:00
SaveCollector saveCollector = new SaveCollector(this);
saveCollector.Add(o);
2019-03-21 07:43:39 +01:00
2019-03-21 14:07:08 +01:00
foreach (PreparedObject preparedObject in saveCollector.PreparedToSave)
{
Storage.Store(preparedObject);
objectCache[preparedObject.PersistenceID] = preparedObject;
}
}
2019-03-21 07:43:39 +01:00
}
2019-03-21 14:07:08 +01:00
public T LoadPersistent<T>(Guid persistenceID) => (T)LoadPersistent(persistenceID);
public IPersistent LoadPersistent(Guid persistenceID)
2019-03-20 14:28:56 +01:00
{
2019-03-21 14:07:08 +01:00
if (!Contains(persistenceID))
throw new KeyNotFoundException();
2019-03-20 14:28:56 +01:00
2019-03-21 14:07:08 +01:00
PreparedObject preparedObject = GetCachedPersistent(persistenceID);
if (preparedObject == null)
2019-03-21 07:43:39 +01:00
{
2019-03-21 14:07:08 +01:00
preparedObject = new PreparedObject(this, typeof(IPersistent), persistenceID);
if (!Storage.Load(preparedObject))
throw new IOException(String.Format("unable to load IPersistent({0})",persistenceID));
2019-03-21 07:43:39 +01:00
2019-03-21 14:07:08 +01:00
preparedObject.CreateInstance();
objectCache.Add(persistenceID,preparedObject);
2019-03-21 07:43:39 +01:00
}
2019-03-21 14:07:08 +01:00
return preparedObject.Instance;
2019-03-20 14:28:56 +01:00
}
2019-03-21 07:43:39 +01:00
2019-03-21 14:07:08 +01:00
private PreparedObject GetCachedPersistent(Guid persistenceID)
2019-03-20 14:28:56 +01:00
{
lock (this)
{
2019-03-21 14:07:08 +01:00
if (objectCache.ContainsKey(persistenceID))
2019-03-20 14:28:56 +01:00
{
2019-03-21 14:07:08 +01:00
return objectCache[persistenceID];
2019-03-20 14:28:56 +01:00
}
}
return null;
}
2019-03-21 07:43:39 +01:00
class SaveCollector
2019-03-20 14:28:56 +01:00
{
public ODB ODB { get; }
2019-03-21 14:07:08 +01:00
public IEnumerable<PreparedObject> PreparedToSave => preparedObjects.Values;
2019-03-20 14:28:56 +01:00
2019-03-21 14:07:08 +01:00
private Dictionary<Guid, PreparedObject> preparedObjects = new Dictionary<Guid, PreparedObject>();
2019-03-13 08:22:08 +01:00
2019-03-21 07:43:39 +01:00
public SaveCollector(ODB odb)
2019-03-20 14:28:56 +01:00
{
ODB = odb;
}
2019-03-13 08:22:08 +01:00
2019-03-21 14:07:08 +01:00
public void Add(IPersistent persistent)
2019-03-20 14:28:56 +01:00
{
2019-03-21 14:07:08 +01:00
PreparedObject preparedObject = new PreparedObject(ODB,persistent);
PreparedObject cachedObject = ODB.GetCachedPersistent(preparedObject.PersistenceID);
2019-03-21 07:43:39 +01:00
2019-03-21 14:07:08 +01:00
if (!preparedObject.InstanceEquals(cachedObject) && !preparedObjects.ContainsKey(preparedObject.PersistenceID))
2019-03-21 07:43:39 +01:00
{
2019-03-21 14:07:08 +01:00
preparedObjects.Add(preparedObject.PersistenceID, preparedObject);
foreach (IPersistent referencedPersistent in preparedObject.ReferencedPersistents)
2019-03-21 07:43:39 +01:00
{
2019-03-21 14:07:08 +01:00
Add(referencedPersistent);
2019-03-21 07:43:39 +01:00
}
2019-03-20 14:28:56 +01:00
}
}
2019-03-21 07:43:39 +01:00
2019-03-20 14:28:56 +01:00
}
2019-03-13 08:22:08 +01:00
}
}