146 lines
4.4 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|