/Horizon/Database/SnapshotDatabase.cs |
@@ -46,6 +46,12 @@ |
private const string RemoveSnapshotFromHashSql = |
"DELETE FROM \"Snapshots\" WHERE Hash = @hash"; |
|
private const string GetTransferSnapshotFromHashSql = |
"SELECT \"Name\", \"Path\", \"Time\", \"Data\", \"Shot\", \"Color\", \"Hash\", \"Note\" FROM \"Snapshots\" WHERE Hash = @hash"; |
|
private const string SetTransferSnapshotSql = |
"INSERT INTO \"Snapshots\" ( \"Name\", \"Path\", \"Time\", \"Data\", \"Shot\", \"Color\", \"Hash\", \"Note\" ) VALUES ( @name, @path, @time, zeroblob(@dataLength), zeroblob(@shotLength), @color, @hash, @note )"; |
|
private const string RemoveScreenshotFromHashSql = |
"UPDATE \"Snapshots\" SET Shot = null WHERE Hash = @hash"; |
|
@@ -376,6 +382,282 @@ |
} |
} |
|
public async Task SetCompleteSnapshotAsync(TransferSnapshot transferSnapshot, CancellationToken cancellationToken) |
{ |
await _databaseLock.WaitAsync(cancellationToken); |
try |
{ |
using (var sqliteConnection = |
new SQLiteConnection(_sqliteConnectionStringBuilder.ConnectionString)) |
{ |
await sqliteConnection.OpenAsync(cancellationToken); |
|
using (var dbTransaction = sqliteConnection.BeginTransaction()) |
{ |
try |
{ |
using (var dataMemoryStream = new MemoryStream()) |
{ |
using (var dataZipStream = |
new GZipStream(dataMemoryStream, CompressionMode.Compress, true)) |
{ |
dataMemoryStream.Position = 0L; |
await dataZipStream.WriteAsync(transferSnapshot.Data, 0, |
transferSnapshot.Data.Length, cancellationToken); |
dataZipStream.Close(); |
|
using (var bitmapMemoryStream = new MemoryStream()) |
{ |
bitmapMemoryStream.Position = 0L; |
using (var bitmapZipStream = |
new GZipStream(bitmapMemoryStream, CompressionMode.Compress, |
true)) |
{ |
using (var transferImageStream = new MemoryStream(transferSnapshot.Shot)) |
{ |
transferImageStream.Position = 0L; |
await transferImageStream.CopyToAsync(bitmapZipStream); |
bitmapZipStream.Close(); |
bitmapMemoryStream.Position = 0L; |
|
var a = bitmapMemoryStream.ToArray(); |
|
// Insert the file change. |
using (var sqliteCommand = |
new SQLiteCommand(SetTransferSnapshotSql, sqliteConnection, |
dbTransaction)) |
{ |
sqliteCommand.Parameters.AddRange(new[] |
{ |
new SQLiteParameter("@name", transferSnapshot.Name), |
new SQLiteParameter("@path", transferSnapshot.Path), |
new SQLiteParameter("@time", transferSnapshot.Time), |
new SQLiteParameter("@dataLength", |
dataMemoryStream.Length), |
new SQLiteParameter("@shotLength", |
bitmapMemoryStream.Length), |
new SQLiteParameter("@hash", transferSnapshot.Hash), |
new SQLiteParameter("@note", transferSnapshot.Note) |
}); |
|
var numeric = transferSnapshot.Color; |
switch (numeric) |
{ |
case 0: |
sqliteCommand.Parameters.Add( |
new SQLiteParameter("@color", null)); |
break; |
default: |
sqliteCommand.Parameters.Add( |
new SQLiteParameter("@color", numeric)); |
break; |
} |
|
sqliteCommand.Prepare(); |
|
await sqliteCommand.ExecuteNonQueryAsync(cancellationToken); |
} |
|
// Insert the data blobs. |
using (var sqliteCommand = |
new SQLiteCommand(GetLastRowInsertSql, sqliteConnection, |
dbTransaction)) |
{ |
sqliteCommand.Prepare(); |
|
var rowId = |
(long)await sqliteCommand.ExecuteScalarAsync( |
cancellationToken); |
|
using (var sqliteBlob = |
SQLiteBlob.Create(sqliteConnection, "main", |
"Snapshots", |
"Data", |
rowId, |
false)) |
{ |
var fileMemoryStreamData = dataMemoryStream.ToArray(); |
|
sqliteBlob.Write(fileMemoryStreamData, |
fileMemoryStreamData.Length, |
0); |
} |
|
using (var sqliteBlob = |
SQLiteBlob.Create(sqliteConnection, "main", |
"Snapshots", |
"Shot", |
rowId, |
false)) |
{ |
var bitmapMemoryStreamData = |
bitmapMemoryStream.ToArray(); |
|
sqliteBlob.Write(bitmapMemoryStreamData, |
bitmapMemoryStreamData.Length, |
0); |
} |
} |
|
dbTransaction.Commit(); |
|
SnapshotCreate?.Invoke(this, |
new SnapshotCreateSuccessEventArgs(transferSnapshot.Name, |
transferSnapshot.Time, transferSnapshot.Path, |
Color.FromArgb(transferSnapshot.Color), |
transferSnapshot.Hash)); |
} |
} |
} |
} |
} |
} |
catch (SQLiteException exception) |
{ |
dbTransaction.Rollback(); |
|
if (exception.ResultCode != SQLiteErrorCode.Constraint) |
{ |
SnapshotCreate?.Invoke(this, |
new SnapshotCreateFailureEventArgs(transferSnapshot.Name, transferSnapshot.Path, |
Color.FromArgb(transferSnapshot.Color), exception)); |
} |
|
throw; |
} |
catch (Exception exception) |
{ |
dbTransaction.Rollback(); |
|
SnapshotCreate?.Invoke(this, |
new SnapshotCreateFailureEventArgs(transferSnapshot.Name, transferSnapshot.Path, |
Color.FromArgb(transferSnapshot.Color), exception)); |
|
throw; |
} |
} |
} |
} |
finally |
{ |
_databaseLock.Release(); |
} |
} |
|
|
public async Task<TransferSnapshot> GetCompleteSnapshot(string hash, CancellationToken cancellationToken) |
{ |
await _databaseLock.WaitAsync(cancellationToken); |
try |
{ |
using (var sqliteConnection = |
new SQLiteConnection(_sqliteConnectionStringBuilder.ConnectionString)) |
{ |
await sqliteConnection.OpenAsync(cancellationToken); |
|
// Insert the file change. |
using (var sqliteCommand = new SQLiteCommand(GetTransferSnapshotFromHashSql, sqliteConnection)) |
{ |
|
sqliteCommand.Parameters.AddRange(new[] |
{ |
new SQLiteParameter("@hash", hash) |
}); |
|
sqliteCommand.Prepare(); |
|
using (var sqlDataReader = await sqliteCommand.ExecuteReaderAsync(cancellationToken)) |
{ |
//var snapshots = new List<Snapshot>(); |
while (await sqlDataReader.ReadAsync(cancellationToken)) |
{ |
var name = (string)sqlDataReader["Name"]; |
var path = (string)sqlDataReader["Path"]; |
var time = (string)sqlDataReader["Time"]; |
|
var color = Color.Empty; |
|
if (!(sqlDataReader["Color"] is DBNull)) |
{ |
var dbColor = Convert.ToInt32(sqlDataReader["Color"]); |
|
switch (dbColor) |
{ |
case 0: |
color = Color.Empty; |
break; |
default: |
color = Color.FromArgb(dbColor); |
break; |
} |
} |
|
var note = string.Empty; |
|
if (!(sqlDataReader["Note"] is DBNull)) |
{ |
note = (string)sqlDataReader["Note"]; |
} |
|
Bitmap shot = null; |
|
if (!(sqlDataReader["Shot"] is DBNull)) |
{ |
var readStream = sqlDataReader.GetStream(4); |
|
readStream.Position = 0L; |
|
using (var zipStream = new GZipStream(readStream, CompressionMode.Decompress)) |
{ |
using (var image = Image.FromStream(zipStream)) |
{ |
shot = new Bitmap(image); |
} |
} |
} |
|
byte[] data = null; |
if (!(sqlDataReader["Data"] is DBNull)) |
{ |
using (var readStream = sqlDataReader.GetStream(3)) |
{ |
using (var memoryStream = new MemoryStream()) |
{ |
readStream.Position = 0L; |
|
await readStream.CopyToAsync(memoryStream); |
|
memoryStream.Position = 0L; |
|
using (var zipStream = new GZipStream(memoryStream, CompressionMode.Decompress)) |
{ |
// Do not dispose the returned stream and leave it up to callers to dispose. |
var outputStream = new MemoryStream(); |
|
await zipStream.CopyToAsync(outputStream); |
|
outputStream.Position = 0L; |
|
data = outputStream.ToArray(); |
} |
} |
} |
} |
|
return new TransferSnapshot(name, path, time, hash, color, shot, note, data); |
} |
} |
} |
} |
} |
finally |
{ |
_databaseLock.Release(); |
} |
|
return null; |
} |
|
public async Task CreateSnapshotAsync(string name, string path, Color color, CancellationToken cancellationToken) |
{ |
await _databaseLock.WaitAsync(cancellationToken); |
@@ -1095,13 +1377,21 @@ |
|
readStream.Position = 0L; |
|
using (var zipStream = new GZipStream(readStream, CompressionMode.Decompress)) |
try |
{ |
using (var image = Image.FromStream(zipStream)) |
using (var zipStream = new GZipStream(readStream, CompressionMode.Decompress)) |
{ |
shot = new Bitmap(image); |
using (var image = Image.FromStream(zipStream)) |
{ |
shot = new Bitmap(image); |
} |
} |
} |
catch (Exception exception) |
{ |
Log.Error(exception, $"Could not retrieve image preview for snapshot {hash}."); |
return null; |
} |
} |
|
return new SnapshotPreview(hash, shot, note); |
@@ -1501,5 +1791,7 @@ |
} |
|
#endregion |
|
|
} |
} |