164 lines
3.8 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|