|
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Security.Permissions;
using System.Threading;
using Pfz.Databasing.Managers;
using Pfz.Extensions.MonitorLockExtensions;
namespace Pfz.Databasing
{
internal sealed class SerializerDatabaseConnection:
IDatabaseConnection
{
private IFormatter fFormatter;
internal string fPath;
private static readonly object fTransactionLock = new object();
internal static Dictionary<string, IRecord> fChangedRecords;
internal SerializerDatabaseConnection(IFormatter formatter, string path)
{
fFormatter = formatter;
fPath = path;
}
public void Dispose()
{
var transactionDisposer = fTransactionDisposer;
if (fTransactionDisposer != null)
{
fTransactionDisposer = null;
transactionDisposer.Dispose();
}
}
private IDisposable fTransactionDisposer;
public bool HasActiveTransaction
{
get
{
return fTransactionDisposer != null;
}
}
public void BeginTransaction()
{
if (fTransactionDisposer != null)
throw new DatabaseException("A transaction has already been initialized.");
fTransactionDisposer = fTransactionLock.LockWithTimeout();
fChangedRecords = new Dictionary<string, IRecord>();
}
public void CommitTransaction()
{
var transactionDisposer = fTransactionDisposer;
if (transactionDisposer == null)
throw new DatabaseException("A transaction has not been initialized.");
var changedRecords = fChangedRecords;
foreach(var pair in changedRecords)
p_FinalApply(pair.Key, pair.Value);
transactionDisposer.Dispose();
Interlocked.CompareExchange(ref fTransactionDisposer, null, transactionDisposer);
Interlocked.CompareExchange(ref fChangedRecords, null, changedRecords);
}
private void p_FinalApply(string name, IRecord record)
{
var recordMode = record.GetRecordMode();
if (recordMode == RecordMode.ReadOnly)
{
try
{
File.Delete(name);
}
catch
{
}
}
else
{
p_ClearReferences(record);
RecordBase recordBase = (RecordBase)(object)record;
recordBase.SetUntypedOldRecord(null);
Directory.CreateDirectory(Path.GetDirectoryName(name));
using(var stream = File.Create(name))
fFormatter.Serialize(stream, record);
}
}
public void RollbackTransaction()
{
var transactionDisposer = fTransactionDisposer;
if (transactionDisposer == null)
throw new DatabaseException("A transaction has not been initialized.");
var changedRecords = fChangedRecords;
transactionDisposer.Dispose();
Interlocked.CompareExchange(ref fTransactionDisposer, null, transactionDisposer);
Interlocked.CompareExchange(ref fChangedRecords, null, changedRecords);
}
[ReflectionPermission(SecurityAction.Assert, RestrictedMemberAccess=true)]
private void p_ClearReferences(object record)
{
RecordBase recordBase = (RecordBase)record;
recordBase.SetUntypedOldRecord(null);
Type recordType = record.GetType();
foreach(var interfaceType in recordType.GetInterfaces())
{
if (!typeof(IRecord).IsAssignableFrom(interfaceType))
continue;
foreach(var property in interfaceType.GetProperties())
{
Type propertyType = property.PropertyType;
if (!typeof(IRecord).IsAssignableFrom(propertyType))
continue;
FieldInfo field = recordType.GetField("__keyOf_" + property.Name, BindingFlags.Instance | BindingFlags.NonPublic);
field.SetValue(record, null);
}
}
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I started to program computers when I was 11 years old, as a hobbyist, programming in AMOS Basic and Blitz Basic for Amiga.
At 12 I had my first try with assembler, but it was too difficult at the time. Then, in the same year, I learned C and, after learning C, I was finally able to learn assembler (for Motorola 680x0).
Not sure, but probably between 12 and 13, I started to learn C++. I always programmed "in an object oriented way", but using function pointers instead of virtual methods.
At 15 I started to learn Pascal at school and to use Delphi. At 16 I started my first internship (using Delphi). At 18 I started to work professionally using C++ and since then I've developed my programming skills as a professional developer in C++ and C#, generally creating libraries that help other developers do their work easier, faster and with less errors.
Want more info or simply want to contact me?
Take a look at:
http://paulozemek.azurewebsites.net/
Or e-mail me at: paulozemek@outlook.com
Codeproject MVP 2012, 2015 & 2016
Microsoft MVP 2013-2014 (in October 2014 I started working at Microsoft, so I can't be a Microsoft MVP anymore).