ln.types/odb/ng/Session.cs

164 lines
3.8 KiB
C#

using System;
using System.Collections.Generic;
using ln.types.odb.values;
using ln.logging;
namespace ln.types.odb.ng
{
public class Session : IStorageContainer
{
public IStorageContainer StorageContainer { get; private set; }
public ODBMapper ODBMapper { get; private set; }
public bool IsOpen => StorageContainer.IsOpen;
public Session(IStorageContainer storageContainer)
{
StorageContainer = storageContainer;
ODBMapper = ODBMapper.Default;
}
private Dictionary<string, IStorage> storages = new Dictionary<string, IStorage>();
public IStorage GetStorage(string storageName)
{
if (storages.ContainsKey(storageName))
return storages[storageName];
IStorage storage = StorageContainer.GetStorage(storageName);
storages.Add(storageName, new SessionCache(storage));
if (!storage.IsOpen)
storage.Open();
return storages[storageName];
}
public void Open()
{
StorageContainer.Open();
}
public void Close()
{
StorageContainer.Close();
}
public IEnumerable<string> GetStorageNames()
{
return StorageContainer.GetStorageNames();
}
public void Dispose()
{
}
class SessionCache : IStorage
{
public IStorage Storage { get; }
public bool IsOpen => Storage.IsOpen;
Dictionary<Guid, CachedDocument> documentCache = new Dictionary<Guid, CachedDocument>();
public SessionCache(IStorage storage)
{
Storage = storage;
}
public bool Open()
{
return Storage.Open();
}
public void Close()
{
Storage.Close();
}
public Document Load(Guid documentID)
{
lock (this)
{
if (!documentCache.ContainsKey(documentID))
{
Document cacheDocument = Storage.Load(documentID);
documentCache.Add(documentID, new CachedDocument(cacheDocument));
}
return documentCache[documentID].WorkingCopy;
}
}
public void Save(Document document)
{
lock (this)
{
if (!documentCache.ContainsKey(document.ID))
{
Logging.Log(LogLevel.DEBUG, "SessionCache: Save(): saving new Document {0}",document.ID);
Storage.Save(document);
documentCache.Add(document.ID, new CachedDocument(document.Clone() as Document,document));
}
else
{
lock (Storage)
{
Document storageDocument = Storage.Load(document.ID);
Document cacheDocument = documentCache[document.ID].CachedCopy;
bool changedFlag = false;
foreach (ODBValue propertyName in document.Keys)
{
if (!document[propertyName].Equals(cacheDocument[propertyName]))
{
Logging.Log(LogLevel.DEBUG, "SessionCache: Save(): found changed field for Document {0}: {1}={2}", document.ID, propertyName, document[propertyName]);
storageDocument[propertyName] = document[propertyName];
changedFlag = true;
}
}
foreach (ODBValue propertyName in cacheDocument.Keys)
{
if (!document.Contains(propertyName))
{
storageDocument[propertyName] = ODBNull.Instance;
changedFlag = true;
}
}
if (changedFlag)
{
Storage.Save(storageDocument);
documentCache[document.ID] = new CachedDocument(document.Clone() as Document,document);
}
else
{
Logging.Log(LogLevel.DEBUG, "SessionCache: Save(): No changes to be saved for document {0}",document.ID);
}
}
}
}
}
public IEnumerable<Guid> GetDocumentIDs()
{
return Storage.GetDocumentIDs();
}
struct CachedDocument
{
public Document CachedCopy;
public Document WorkingCopy;
public CachedDocument(Document cachedCopy)
{
CachedCopy = cachedCopy;
WorkingCopy = cachedCopy.Clone() as Document;
}
public CachedDocument(Document cachedCopy,Document workingCopy)
{
CachedCopy = cachedCopy;
WorkingCopy = workingCopy;
}
}
}
}
}