Skip to content

Commit

Permalink
Swapped out simple lock for ReaderWriterLockSlim
Browse files Browse the repository at this point in the history
This should make simulataneous reads faster.
  • Loading branch information
Redth committed Dec 20, 2017
1 parent e936edd commit 6a6c45d
Showing 1 changed file with 90 additions and 62 deletions.
152 changes: 90 additions & 62 deletions src/MonkeyCache.FileStore/Barrel.cs
Expand Up @@ -4,16 +4,21 @@
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using Newtonsoft.Json;

namespace MonkeyCache.FileStore
{
public class Barrel : IBarrel
{
ReaderWriterLockSlim indexLocker;

JsonSerializerSettings jsonSettings;

Barrel()
{
indexLocker = new ReaderWriterLockSlim();

jsonSettings = new JsonSerializerSettings {
ObjectCreationHandling = ObjectCreationHandling.Replace,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
Expand All @@ -39,17 +44,18 @@ public void Add(string key, string data, TimeSpan expireIn, string eTag = null)
if (data == null)
return;

lock (indexLock) {
indexLocker.EnterWriteLock();

var hash = Hash(key);
var path = Path.Combine(baseDirectory.Value, hash);
var hash = Hash(key);
var path = Path.Combine(baseDirectory.Value, hash);

File.WriteAllText(path, data);
File.WriteAllText(path, data);

index[key] = new Tuple<string, DateTime>(eTag ?? string.Empty, DateTime.UtcNow.Add(expireIn));
index[key] = new Tuple<string, DateTime>(eTag ?? string.Empty, DateTime.UtcNow.Add(expireIn));

WriteIndex();
}
WriteIndex();

indexLocker.ExitWriteLock();
}

public void Add<T>(string key, T data, TimeSpan expireIn, string eTag = null)
Expand All @@ -61,84 +67,103 @@ public void Add<T>(string key, T data, TimeSpan expireIn, string eTag = null)

public void Empty(params string[] key)
{
lock (indexLock) {

foreach (var k in key) {
File.Delete(Path.Combine(baseDirectory.Value, Hash(k)));
index.Remove(k);
}
indexLocker.EnterWriteLock();

WriteIndex();
foreach (var k in key) {
File.Delete(Path.Combine(baseDirectory.Value, Hash(k)));
index.Remove(k);
}

WriteIndex();

indexLocker.ExitWriteLock();
}

public void EmptyAll()
{
lock (indexLock) {
foreach (var item in index) {
var hash = Hash(item.Key);
File.Delete(Path.Combine(baseDirectory.Value, hash));
}

index.Clear();
indexLocker.EnterWriteLock();

WriteIndex();
foreach (var item in index) {
var hash = Hash(item.Key);
File.Delete(Path.Combine(baseDirectory.Value, hash));
}

index.Clear();

WriteIndex();

indexLocker.ExitWriteLock();
}

public void EmptyExpired()
{
lock (indexLock) {
var expired = index.Where(k => k.Value.Item2 < DateTime.UtcNow);

var toRem = new List<string>();
indexLocker.EnterWriteLock();

foreach (var item in expired) {
var hash = Hash(item.Key);
File.Delete(Path.Combine(baseDirectory.Value, hash));
toRem.Add(item.Key);
}
var expired = index.Where(k => k.Value.Item2 < DateTime.UtcNow);

foreach (var key in toRem)
index.Remove(key);
var toRem = new List<string>();

WriteIndex();
foreach (var item in expired) {
var hash = Hash(item.Key);
File.Delete(Path.Combine(baseDirectory.Value, hash));
toRem.Add(item.Key);
}

foreach (var key in toRem)
index.Remove(key);

WriteIndex();

indexLocker.ExitWriteLock();
}

public bool Exists(string key)
{
lock (indexLock) {
return index.ContainsKey(key);
}
var exists = false;

indexLocker.EnterReadLock();

exists = index.ContainsKey(key);

indexLocker.ExitReadLock();

return exists;
}

public string Get(string key)
{
lock (indexLock) {
var hash = Hash(key);
var path = Path.Combine(baseDirectory.Value, hash);
string result = null;

if (!index.ContainsKey(key) || !File.Exists(path))
return null;
indexLocker.EnterReadLock();

return File.ReadAllText(path);
}
var hash = Hash(key);
var path = Path.Combine(baseDirectory.Value, hash);

if (index.ContainsKey(key) && File.Exists(path))
result = File.ReadAllText(path);

indexLocker.ExitReadLock();

return result;
}

public T Get<T>(string key)
{
lock (indexLock) {
var hash = Hash(key);
var path = Path.Combine(baseDirectory.Value, hash);
T result = default(T);

if (!index.ContainsKey(key) || !File.Exists(path))
return default(T);
indexLocker.EnterReadLock();

var contents = File.ReadAllText(path);
var hash = Hash(key);
var path = Path.Combine(baseDirectory.Value, hash);

return JsonConvert.DeserializeObject<T>(contents, jsonSettings);
if (index.ContainsKey(key) && File.Exists(path)) {
var contents = File.ReadAllText(path);
result = JsonConvert.DeserializeObject<T>(contents, jsonSettings);
}

indexLocker.ExitReadLock();

return result;
}

public string GetETag(string key)
Expand All @@ -148,23 +173,28 @@ public string GetETag(string key)

string etag = null;

lock (indexLock) {
if (!index.ContainsKey(key))
return null;
indexLocker.EnterReadLock();

if (index.ContainsKey(key))
etag = index[key]?.Item1;
}

indexLocker.ExitReadLock();

return etag;
}

public bool IsExpired(string key)
{
lock (indexLock) {
if (!index.ContainsKey(key))
return false;
var expired = false;

return index[key].Item2 < DateTime.UtcNow;
}
indexLocker.EnterReadLock();

if (index.ContainsKey(key))
expired = index[key].Item2 < DateTime.UtcNow;

indexLocker.ExitReadLock();

return expired;
}

Lazy<string> baseDirectory = new Lazy<string>(() => {
Expand All @@ -173,8 +203,6 @@ public bool IsExpired(string key)

Dictionary<string, Tuple<string, DateTime>> index;

static readonly object indexLock = new object();

const string INDEX_FILENAME = "index.dat";

string indexFile;
Expand Down

0 comments on commit 6a6c45d

Please sign in to comment.