ln.objects/ng/storage/fs/FSStorageContainer.cs

146 lines
4.4 KiB
C#

// /**
// * File: FSStorage.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.Collections.Generic;
using System.IO;
using System.Diagnostics;
using ln.logging;
using ln.types.odb.ng.storage.cache;
namespace ln.types.odb.ng.storage.fs
{
public class FSStorageContainer : IStorageContainer,IDisposable
{
public string BasePath { get; }
public int DefaultCacheSize { get; set; }
FileStream lockFile;
Dictionary<string, IStorage> storages = new Dictionary<string, IStorage>();
public FSStorageContainer(string basePath)
{
BasePath = basePath;
}
public bool IsOpen => lockFile != null;
private void AssertOpen()
{
if (!IsOpen)
throw new IOException("FSStorage not open");
}
public void Close()
{
lock (this)
{
AssertOpen();
foreach (IStorage storage in storages.Values)
{
if (storage.IsOpen)
storage.Close();
storage.Dispose();
}
if (lockFile != null)
{
lockFile.Close();
lockFile.Dispose();
lockFile = null;
}
}
}
public IStorage GetStorage(string storageName)
{
lock (this)
{
AssertOpen();
if (!storages.ContainsKey(storageName))
{
IStorage storage = new SegmentedFileStorage(Path.Combine(BasePath, storageName));
if (DefaultCacheSize > 0)
storage = new CachingStorage(storage) { MaxCacheSize = DefaultCacheSize, };
storages.Add(storageName, storage);
}
if (!storages[storageName].IsOpen)
storages[storageName].Open();
return storages[storageName];
}
}
public IEnumerable<string> GetStorageNames()
{
lock (this)
{
AssertOpen();
return storages.Keys;
}
}
public IStorageContainer Open()
{
lock (this)
{
if (!IsOpen)
{
if (!Directory.Exists(BasePath))
Directory.CreateDirectory(BasePath);
try
{
lockFile = new FileStream(Path.Combine(BasePath, ".lock"), FileMode.CreateNew, FileAccess.ReadWrite, FileShare.Read, 1024, FileOptions.DeleteOnClose);
lockFile.WriteInteger(Process.GetCurrentProcess().Id);
lockFile.Flush();
} catch (IOException)
{
if (File.Exists(Path.Combine(BasePath, ".lock")))
{
lockFile = new FileStream(Path.Combine(BasePath, ".lock"), FileMode.Open, FileAccess.Read, FileShare.Read);
int lockPID = lockFile.ReadInteger();
lockFile.Close();
Process lockProcess = null;
try
{
lockProcess = Process.GetProcessById(lockPID);
} catch (Exception)
{
}
if ((lockProcess != null) && !lockProcess.HasExited)
throw;
Logging.Log(LogLevel.DEBUG, "FSStorageContainer: Ignoring stale lock file: PID:{0}@{1}", lockPID,Path.Combine(BasePath, ".lock"));
lockFile = new FileStream(Path.Combine(BasePath, ".lock"), FileMode.Truncate, FileAccess.ReadWrite, FileShare.Read, 1024, FileOptions.DeleteOnClose);
lockFile.WriteInteger(Process.GetCurrentProcess().Id);
lockFile.Flush();
}
}
}
}
return this;
}
public void Dispose()
{
if (IsOpen)
Close();
storages.Clear();
}
}
}