ln.types/odb/ng/storage/session/SessionStorage.cs

157 lines
3.9 KiB
C#

using System;
using System.Collections.Generic;
using ln.types.odb.values;
using System.Linq;
using ln.types.odb.ng.storage.bases;
using ln.types.threads;
using ln.types.odb.ng.diff;
namespace ln.types.odb.ng.storage.session
{
public class SessionStorage : ChainedStorage
{
public SessionStorageContainer SessionContainer { get; }
Dictionary<Guid, CachedDocument> documentCache = new Dictionary<Guid, CachedDocument>();
public SessionStorage(SessionStorageContainer session, IStorage storage)
:base(storage)
{
SessionContainer = session;
}
public override Document Load(Guid documentID)
{
lock (this)
{
if (!Storage.Contains(documentID))
throw new KeyNotFoundException();
if (!documentCache.ContainsKey(documentID))
{
Document cacheDocument = Storage.Load(documentID);
documentCache.Add(documentID, new CachedDocument(cacheDocument));
}
else
{
DateTime storageTimeStamp = GetStorageTimestamp(documentID);
if (!storageTimeStamp.Equals(documentCache[documentID].CachedCopy.StorageTimeStamp))
{
Document storageDocument = Storage.Load(documentID);
CachedDocument cd = documentCache[documentID];
storageDocument.CloneTo(cd.CachedCopy);
storageDocument.CloneTo(cd.WorkingCopy);
}
}
return documentCache[documentID].WorkingCopy;
}
}
public override void Save(Document document)
{
lock (this)
{
if (GetDocumentLocked(document.ID))
throw new LockingException();
if (!documentCache.ContainsKey(document.ID))
{
Storage.Save(document);
documentCache.Add(document.ID, new CachedDocument(document.Clone() as Document, document));
}
else
{
if (Storage.LockDocument(document.ID))
{
DateTime storageTimestamp = Storage.GetStorageTimestamp(document.ID);
Document cacheDocument = documentCache[document.ID].CachedCopy;
if (cacheDocument.StorageTimeStamp.Equals(storageTimestamp))
{
Storage.SaveRelease(document);
documentCache[document.ID] = new CachedDocument(document.Clone() as Document, document);
}
else
{
throw new NotImplementedException();
}
}
else
{
throw new LockingException();
}
}
}
}
public override void Delete(Guid documentID)
{
lock (this)
{
if (GetDocumentLocked(documentID))
throw new LockingException();
if (documentCache.ContainsKey(documentID))
{
documentCache.Remove(documentID);
}
Storage.Delete(documentID);
}
}
public void Sync(Guid documentID)
{
lock (this)
{
if (documentCache.ContainsKey(documentID))
Sync(documentCache[documentID].WorkingCopy);
}
}
public void Sync(Document document)
{
lock (this)
{
if (!documentCache.TryGetValue(document.ID, out CachedDocument cachedDocument))
throw new KeyNotFoundException();
if (!GetStorageTimestamp(document.ID).Equals(document.StorageTimeStamp))
{
Document cacheDocument = cachedDocument.CachedCopy;
Document storageDocument = Storage.Load(document.ID);
DocumentDiff cacheDiff = new DocumentDiff(cacheDocument, document);
DocumentDiff storageDiff = new DocumentDiff(cacheDocument, storageDocument);
}
}
}
class CachedDocument
{
public Document CachedCopy;
public Document WorkingCopy;
public bool ConcurrentlyChanged;
public CachedDocument(Document cachedCopy)
{
CachedCopy = cachedCopy;
WorkingCopy = cachedCopy.Clone() as Document;
ConcurrentlyChanged = false;
}
public CachedDocument(Document cachedCopy, Document workingCopy)
{
CachedCopy = cachedCopy;
WorkingCopy = workingCopy;
ConcurrentlyChanged = false;
}
}
}
}