added ignore code coverage to experimental sqllitelog class that cannot be unit tested anyway really

This commit is contained in:
Tom Gardham-Pallister 2018-06-11 22:57:43 +01:00
parent 095406bd45
commit 14308ff5fb

View File

@ -1,321 +1,322 @@
namespace Ocelot.Raft namespace Ocelot.Raft
{ {
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Data.Sqlite; using Microsoft.Data.Sqlite;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using Rafty.Infrastructure; using Rafty.Infrastructure;
using Rafty.Log; using Rafty.Log;
public class SqlLiteLog : ILog [ExcludeFromCoverage]
{ public class SqlLiteLog : ILog
private readonly string _path; {
private readonly SemaphoreSlim _sempaphore = new SemaphoreSlim(1, 1); private readonly string _path;
private readonly ILogger _logger; private readonly SemaphoreSlim _sempaphore = new SemaphoreSlim(1, 1);
private readonly NodeId _nodeId; private readonly ILogger _logger;
private readonly NodeId _nodeId;
public SqlLiteLog(NodeId nodeId, ILoggerFactory loggerFactory)
{ public SqlLiteLog(NodeId nodeId, ILoggerFactory loggerFactory)
_logger = loggerFactory.CreateLogger<SqlLiteLog>(); {
_nodeId = nodeId; _logger = loggerFactory.CreateLogger<SqlLiteLog>();
_path = $"{nodeId.Id.Replace("/", "").Replace(":", "")}.db"; _nodeId = nodeId;
_sempaphore.Wait(); _path = $"{nodeId.Id.Replace("/", "").Replace(":", "")}.db";
_sempaphore.Wait();
if (!File.Exists(_path))
{ if (!File.Exists(_path))
var fs = File.Create(_path); {
var fs = File.Create(_path);
fs.Dispose(); fs.Dispose();
using (var connection = new SqliteConnection($"Data Source={_path};")) using (var connection = new SqliteConnection($"Data Source={_path};"))
{ {
connection.Open(); connection.Open();
const string sql = @"create table logs ( const string sql = @"create table logs (
id integer primary key, id integer primary key,
data text not null data text not null
)"; )";
using (var command = new SqliteCommand(sql, connection)) using (var command = new SqliteCommand(sql, connection))
{ {
var result = command.ExecuteNonQuery(); var result = command.ExecuteNonQuery();
_logger.LogInformation(result == 0 _logger.LogInformation(result == 0
? $"id: {_nodeId.Id} create database, result: {result}" ? $"id: {_nodeId.Id} create database, result: {result}"
: $"id: {_nodeId.Id} did not create database., result: {result}"); : $"id: {_nodeId.Id} did not create database., result: {result}");
} }
} }
} }
_sempaphore.Release(); _sempaphore.Release();
} }
public async Task<int> LastLogIndex() public async Task<int> LastLogIndex()
{ {
_sempaphore.Wait(); _sempaphore.Wait();
var result = 1; var result = 1;
using (var connection = new SqliteConnection($"Data Source={_path};")) using (var connection = new SqliteConnection($"Data Source={_path};"))
{ {
connection.Open(); connection.Open();
var sql = @"select id from logs order by id desc limit 1"; var sql = @"select id from logs order by id desc limit 1";
using (var command = new SqliteCommand(sql, connection)) using (var command = new SqliteCommand(sql, connection))
{ {
var index = Convert.ToInt32(await command.ExecuteScalarAsync()); var index = Convert.ToInt32(await command.ExecuteScalarAsync());
if (index > result) if (index > result)
{ {
result = index; result = index;
} }
} }
} }
_sempaphore.Release(); _sempaphore.Release();
return result; return result;
} }
public async Task<long> LastLogTerm() public async Task<long> LastLogTerm()
{ {
_sempaphore.Wait(); _sempaphore.Wait();
long result = 0; long result = 0;
using (var connection = new SqliteConnection($"Data Source={_path};")) using (var connection = new SqliteConnection($"Data Source={_path};"))
{ {
connection.Open(); connection.Open();
var sql = @"select data from logs order by id desc limit 1"; var sql = @"select data from logs order by id desc limit 1";
using (var command = new SqliteCommand(sql, connection)) using (var command = new SqliteCommand(sql, connection))
{ {
var data = Convert.ToString(await command.ExecuteScalarAsync()); var data = Convert.ToString(await command.ExecuteScalarAsync());
var jsonSerializerSettings = new JsonSerializerSettings() var jsonSerializerSettings = new JsonSerializerSettings()
{ {
TypeNameHandling = TypeNameHandling.All TypeNameHandling = TypeNameHandling.All
}; };
var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings); var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings);
if (log != null && log.Term > result) if (log != null && log.Term > result)
{ {
result = log.Term; result = log.Term;
} }
} }
} }
_sempaphore.Release(); _sempaphore.Release();
return result; return result;
} }
public async Task<int> Count() public async Task<int> Count()
{ {
_sempaphore.Wait(); _sempaphore.Wait();
var result = 0; var result = 0;
using (var connection = new SqliteConnection($"Data Source={_path};")) using (var connection = new SqliteConnection($"Data Source={_path};"))
{ {
connection.Open(); connection.Open();
var sql = @"select count(id) from logs"; var sql = @"select count(id) from logs";
using (var command = new SqliteCommand(sql, connection)) using (var command = new SqliteCommand(sql, connection))
{ {
var index = Convert.ToInt32(await command.ExecuteScalarAsync()); var index = Convert.ToInt32(await command.ExecuteScalarAsync());
if (index > result) if (index > result)
{ {
result = index; result = index;
} }
} }
} }
_sempaphore.Release(); _sempaphore.Release();
return result; return result;
} }
public async Task<int> Apply(LogEntry log) public async Task<int> Apply(LogEntry log)
{ {
_sempaphore.Wait(); _sempaphore.Wait();
using (var connection = new SqliteConnection($"Data Source={_path};")) using (var connection = new SqliteConnection($"Data Source={_path};"))
{ {
connection.Open(); connection.Open();
var jsonSerializerSettings = new JsonSerializerSettings() var jsonSerializerSettings = new JsonSerializerSettings()
{ {
TypeNameHandling = TypeNameHandling.All TypeNameHandling = TypeNameHandling.All
}; };
var data = JsonConvert.SerializeObject(log, jsonSerializerSettings); var data = JsonConvert.SerializeObject(log, jsonSerializerSettings);
//todo - sql injection dont copy this.. //todo - sql injection dont copy this..
var sql = $"insert into logs (data) values ('{data}')"; var sql = $"insert into logs (data) values ('{data}')";
_logger.LogInformation($"id: {_nodeId.Id}, sql: {sql}"); _logger.LogInformation($"id: {_nodeId.Id}, sql: {sql}");
using (var command = new SqliteCommand(sql, connection)) using (var command = new SqliteCommand(sql, connection))
{ {
var result = await command.ExecuteNonQueryAsync(); var result = await command.ExecuteNonQueryAsync();
_logger.LogInformation($"id: {_nodeId.Id}, insert log result: {result}"); _logger.LogInformation($"id: {_nodeId.Id}, insert log result: {result}");
}
sql = "select last_insert_rowid()";
using (var command = new SqliteCommand(sql, connection))
{
var result = await command.ExecuteScalarAsync();
_logger.LogInformation($"id: {_nodeId.Id}, about to release semaphore");
_sempaphore.Release();
_logger.LogInformation($"id: {_nodeId.Id}, saved log to sqlite");
return Convert.ToInt32(result);
} }
}
} sql = "select last_insert_rowid()";
using (var command = new SqliteCommand(sql, connection))
public async Task DeleteConflictsFromThisLog(int index, LogEntry logEntry) {
{ var result = await command.ExecuteScalarAsync();
_sempaphore.Wait(); _logger.LogInformation($"id: {_nodeId.Id}, about to release semaphore");
using (var connection = new SqliteConnection($"Data Source={_path};")) _sempaphore.Release();
{ _logger.LogInformation($"id: {_nodeId.Id}, saved log to sqlite");
connection.Open(); return Convert.ToInt32(result);
//todo - sql injection dont copy this.. }
var sql = $"select data from logs where id = {index};"; }
_logger.LogInformation($"id: {_nodeId.Id} sql: {sql}"); }
using (var command = new SqliteCommand(sql, connection))
{ public async Task DeleteConflictsFromThisLog(int index, LogEntry logEntry)
var data = Convert.ToString(await command.ExecuteScalarAsync()); {
_sempaphore.Wait();
using (var connection = new SqliteConnection($"Data Source={_path};"))
{
connection.Open();
//todo - sql injection dont copy this..
var sql = $"select data from logs where id = {index};";
_logger.LogInformation($"id: {_nodeId.Id} sql: {sql}");
using (var command = new SqliteCommand(sql, connection))
{
var data = Convert.ToString(await command.ExecuteScalarAsync());
var jsonSerializerSettings = new JsonSerializerSettings() var jsonSerializerSettings = new JsonSerializerSettings()
{ {
TypeNameHandling = TypeNameHandling.All TypeNameHandling = TypeNameHandling.All
}; };
_logger.LogInformation($"id {_nodeId.Id} got log for index: {index}, data is {data} and new log term is {logEntry.Term}"); _logger.LogInformation($"id {_nodeId.Id} got log for index: {index}, data is {data} and new log term is {logEntry.Term}");
var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings); var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings);
if (logEntry != null && log != null && logEntry.Term != log.Term) if (logEntry != null && log != null && logEntry.Term != log.Term)
{ {
//todo - sql injection dont copy this.. //todo - sql injection dont copy this..
var deleteSql = $"delete from logs where id >= {index};"; var deleteSql = $"delete from logs where id >= {index};";
_logger.LogInformation($"id: {_nodeId.Id} sql: {deleteSql}"); _logger.LogInformation($"id: {_nodeId.Id} sql: {deleteSql}");
using (var deleteCommand = new SqliteCommand(deleteSql, connection)) using (var deleteCommand = new SqliteCommand(deleteSql, connection))
{ {
var result = await deleteCommand.ExecuteNonQueryAsync(); var result = await deleteCommand.ExecuteNonQueryAsync();
} }
} }
} }
} }
_sempaphore.Release(); _sempaphore.Release();
} }
public async Task<bool> IsDuplicate(int index, LogEntry logEntry) public async Task<bool> IsDuplicate(int index, LogEntry logEntry)
{ {
_sempaphore.Wait(); _sempaphore.Wait();
using (var connection = new SqliteConnection($"Data Source={_path};")) using (var connection = new SqliteConnection($"Data Source={_path};"))
{ {
connection.Open(); connection.Open();
//todo - sql injection dont copy this.. //todo - sql injection dont copy this..
var sql = $"select data from logs where id = {index};"; var sql = $"select data from logs where id = {index};";
using (var command = new SqliteCommand(sql, connection)) using (var command = new SqliteCommand(sql, connection))
{ {
var data = Convert.ToString(await command.ExecuteScalarAsync()); var data = Convert.ToString(await command.ExecuteScalarAsync());
var jsonSerializerSettings = new JsonSerializerSettings() var jsonSerializerSettings = new JsonSerializerSettings()
{ {
TypeNameHandling = TypeNameHandling.All TypeNameHandling = TypeNameHandling.All
}; };
var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings); var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings);
if (logEntry != null && log != null && logEntry.Term == log.Term) if (logEntry != null && log != null && logEntry.Term == log.Term)
{ {
_sempaphore.Release(); _sempaphore.Release();
return true; return true;
} }
} }
} }
_sempaphore.Release(); _sempaphore.Release();
return false; return false;
} }
public async Task<LogEntry> Get(int index) public async Task<LogEntry> Get(int index)
{ {
_sempaphore.Wait(); _sempaphore.Wait();
using (var connection = new SqliteConnection($"Data Source={_path};")) using (var connection = new SqliteConnection($"Data Source={_path};"))
{ {
connection.Open(); connection.Open();
//todo - sql injection dont copy this.. //todo - sql injection dont copy this..
var sql = $"select data from logs where id = {index}"; var sql = $"select data from logs where id = {index}";
using (var command = new SqliteCommand(sql, connection)) using (var command = new SqliteCommand(sql, connection))
{ {
var data = Convert.ToString(await command.ExecuteScalarAsync()); var data = Convert.ToString(await command.ExecuteScalarAsync());
var jsonSerializerSettings = new JsonSerializerSettings() var jsonSerializerSettings = new JsonSerializerSettings()
{ {
TypeNameHandling = TypeNameHandling.All TypeNameHandling = TypeNameHandling.All
}; };
var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings); var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings);
_sempaphore.Release(); _sempaphore.Release();
return log; return log;
} }
} }
} }
public async Task<List<(int index, LogEntry logEntry)>> GetFrom(int index) public async Task<List<(int index, LogEntry logEntry)>> GetFrom(int index)
{ {
_sempaphore.Wait(); _sempaphore.Wait();
var logsToReturn = new List<(int, LogEntry)>(); var logsToReturn = new List<(int, LogEntry)>();
using (var connection = new SqliteConnection($"Data Source={_path};")) using (var connection = new SqliteConnection($"Data Source={_path};"))
{ {
connection.Open(); connection.Open();
//todo - sql injection dont copy this.. //todo - sql injection dont copy this..
var sql = $"select id, data from logs where id >= {index}"; var sql = $"select id, data from logs where id >= {index}";
using (var command = new SqliteCommand(sql, connection)) using (var command = new SqliteCommand(sql, connection))
{ {
using (var reader = await command.ExecuteReaderAsync()) using (var reader = await command.ExecuteReaderAsync())
{ {
while (reader.Read()) while (reader.Read())
{ {
var id = Convert.ToInt32(reader[0]); var id = Convert.ToInt32(reader[0]);
var data = (string)reader[1]; var data = (string)reader[1];
var jsonSerializerSettings = new JsonSerializerSettings() var jsonSerializerSettings = new JsonSerializerSettings()
{ {
TypeNameHandling = TypeNameHandling.All TypeNameHandling = TypeNameHandling.All
}; };
var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings); var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings);
logsToReturn.Add((id, log)); logsToReturn.Add((id, log));
} }
} }
} }
_sempaphore.Release(); _sempaphore.Release();
return logsToReturn; return logsToReturn;
} }
} }
public async Task<long> GetTermAtIndex(int index) public async Task<long> GetTermAtIndex(int index)
{ {
_sempaphore.Wait(); _sempaphore.Wait();
long result = 0; long result = 0;
using (var connection = new SqliteConnection($"Data Source={_path};")) using (var connection = new SqliteConnection($"Data Source={_path};"))
{ {
connection.Open(); connection.Open();
//todo - sql injection dont copy this.. //todo - sql injection dont copy this..
var sql = $"select data from logs where id = {index}"; var sql = $"select data from logs where id = {index}";
using (var command = new SqliteCommand(sql, connection)) using (var command = new SqliteCommand(sql, connection))
{ {
var data = Convert.ToString(await command.ExecuteScalarAsync()); var data = Convert.ToString(await command.ExecuteScalarAsync());
var jsonSerializerSettings = new JsonSerializerSettings() var jsonSerializerSettings = new JsonSerializerSettings()
{ {
TypeNameHandling = TypeNameHandling.All TypeNameHandling = TypeNameHandling.All
}; };
var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings); var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings);
if (log != null && log.Term > result) if (log != null && log.Term > result)
{ {
result = log.Term; result = log.Term;
} }
} }
} }
_sempaphore.Release(); _sempaphore.Release();
return result; return result;
} }
public async Task Remove(int indexOfCommand) public async Task Remove(int indexOfCommand)
{ {
_sempaphore.Wait(); _sempaphore.Wait();
using (var connection = new SqliteConnection($"Data Source={_path};")) using (var connection = new SqliteConnection($"Data Source={_path};"))
{ {
connection.Open(); connection.Open();
//todo - sql injection dont copy this.. //todo - sql injection dont copy this..
var deleteSql = $"delete from logs where id >= {indexOfCommand};"; var deleteSql = $"delete from logs where id >= {indexOfCommand};";
_logger.LogInformation($"id: {_nodeId.Id} Remove {deleteSql}"); _logger.LogInformation($"id: {_nodeId.Id} Remove {deleteSql}");
using (var deleteCommand = new SqliteCommand(deleteSql, connection)) using (var deleteCommand = new SqliteCommand(deleteSql, connection))
{ {
var result = await deleteCommand.ExecuteNonQueryAsync(); var result = await deleteCommand.ExecuteNonQueryAsync();
} }
} }
_sempaphore.Release(); _sempaphore.Release();
} }
} }
} }