[smuxi/experiments/sqlite: 27/27] Engine(-Tests): initial SqliteMessageBuffer implementation (closes: #908) WIP
- From: Mirco M. M. Bauer <mmmbauer src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [smuxi/experiments/sqlite: 27/27] Engine(-Tests): initial SqliteMessageBuffer implementation (closes: #908) WIP
- Date: Sun, 23 Feb 2014 17:08:39 +0000 (UTC)
commit 3e9e5d3c569a3ee8adec8312bd402ff2f3e2e024
Author: Mirco Bauer <meebey meebey net>
Date: Sun Feb 23 17:49:21 2014 +0100
Engine(-Tests): initial SqliteMessageBuffer implementation (closes: #908) WIP
src/Engine-Tests/Engine-Tests.csproj | 1 +
src/Engine-Tests/SqliteMessageBufferTests.cs | 100 ++++++++++
src/Engine/Engine.csproj | 1 +
src/Engine/MessageBuffers/SqliteMessageBuffer.cs | 232 ++++++++++++++++++++++
4 files changed, 334 insertions(+), 0 deletions(-)
---
diff --git a/src/Engine-Tests/Engine-Tests.csproj b/src/Engine-Tests/Engine-Tests.csproj
index 040336f..1c30005 100644
--- a/src/Engine-Tests/Engine-Tests.csproj
+++ b/src/Engine-Tests/Engine-Tests.csproj
@@ -44,6 +44,7 @@
<Compile Include="GitMessageBufferTests.cs" />
<Compile Include="JsonMessageBufferTests.cs" />
<Compile Include="MessageDtoModelV1Tests.cs" />
+ <Compile Include="SqliteMessageBufferTests.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
diff --git a/src/Engine-Tests/SqliteMessageBufferTests.cs b/src/Engine-Tests/SqliteMessageBufferTests.cs
new file mode 100644
index 0000000..49be73e
--- /dev/null
+++ b/src/Engine-Tests/SqliteMessageBufferTests.cs
@@ -0,0 +1,100 @@
+// Smuxi - Smart MUltipleXed Irc
+//
+// Copyright (c) 2014 Mirco Bauer <meebey meebey net>
+//
+// Full GPL License: <http://www.gnu.org/licenses/gpl.txt>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+using System;
+using System.IO;
+using System.Collections.Generic;
+using NUnit.Framework;
+using Smuxi.Common;
+
+namespace Smuxi.Engine
+{
+ [TestFixture]
+ public class SqliteMessageBufferTests : MessageBufferTestsBase
+ {
+ protected override IMessageBuffer CreateBuffer()
+ {
+ var dbFile = Path.Combine(Platform.GetBuffersPath("testuser"),
+ "testprot");
+ dbFile = Path.Combine(dbFile, "testnet");
+ dbFile = Path.Combine(dbFile, "testchat.sqlite3");
+ if (File.Exists(dbFile)) {
+ File.Delete(dbFile);
+ }
+
+ return OpenBuffer();
+ }
+
+ protected override IMessageBuffer OpenBuffer()
+ {
+ return new SqliteMessageBuffer("testuser", "testprot", "testnet", "testchat");
+ }
+
+ [Test]
+ public void Reopen()
+ {
+ Buffer.Dispose();
+ OpenBuffer();
+ Enumerator();
+ }
+
+ [Test]
+ public void ImplicitFlush()
+ {
+ // generate 32 extra messsages to exceed the buffer size which
+ // forces a flush of the buffer to db4o
+ var bufferCount = Buffer.Count;
+ var msgs = new List<MessageModel>(Buffer);
+ for (int i = 1; i <= 32; i++) {
+ var builder = new MessageBuilder();
+ builder.AppendText("msg{0}", bufferCount + i);
+ var msg = builder.ToMessage();
+ msgs.Add(msg);
+ Buffer.Add(msg);
+ }
+
+ int j = 0;
+ foreach (var msg in Buffer) {
+ Assert.AreEqual(msgs[j++].ToString(), msg.ToString());
+ }
+ Assert.AreEqual(msgs.Count, j);
+ }
+
+ [Test]
+ public void ImplicitRemoveAt()
+ {
+ Buffer.MaxCapacity = 16;
+ // generate 32 extra messsages to exceed the max capacity which
+ // forces a RemoveAt() call of the oldest messages
+ var bufferCount = Buffer.Count;
+ var msgs = new List<MessageModel>(Buffer);
+ for (int i = 1; i <= 32; i++) {
+ var builder = new MessageBuilder();
+ builder.AppendText("msg{0}", bufferCount + i);
+ var msg = builder.ToMessage();
+ msgs.Add(msg);
+ Buffer.Add(msg);
+ }
+
+ Assert.AreEqual(Buffer.MaxCapacity, Buffer.Count);
+ Assert.AreEqual(msgs[19].ToString(), Buffer[0].ToString());
+ }
+ }
+}
diff --git a/src/Engine/Engine.csproj b/src/Engine/Engine.csproj
index 2c74ef3..ff441e0 100644
--- a/src/Engine/Engine.csproj
+++ b/src/Engine/Engine.csproj
@@ -112,6 +112,7 @@
<Compile Include="MessageBuffers\GitMessageBuffer.cs" />
<Compile Include="MessageBuffers\JsonMessageBuffer.cs" />
<Compile Include="Messages\Dto\MessageDtoModelV1.cs" />
+ <Compile Include="MessageBuffers\SqliteMessageBuffer.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Protocols\" />
diff --git a/src/Engine/MessageBuffers/SqliteMessageBuffer.cs
b/src/Engine/MessageBuffers/SqliteMessageBuffer.cs
new file mode 100644
index 0000000..fb00217
--- /dev/null
+++ b/src/Engine/MessageBuffers/SqliteMessageBuffer.cs
@@ -0,0 +1,232 @@
+// Smuxi - Smart MUltipleXed Irc
+//
+// Copyright (c) 2014 Mirco Bauer <meebey meebey net>
+//
+// Full GPL License: <http://www.gnu.org/licenses/gpl.txt>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+using System;
+using System.IO;
+using System.Text;
+using System.Linq;
+using System.Collections.Generic;
+using Mono.Data.Sqlite;
+using ServiceStack.Text;
+using Smuxi.Engine.Dto;
+
+namespace Smuxi.Engine
+{
+ public class SqliteMessageBuffer : MessageBufferBase
+ {
+#if LOG4NET
+ static readonly log4net.ILog f_Logger =
log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
+#endif
+ string DBPath { get; set; }
+ SqliteConnection Connection { get; set; }
+
+ public override int Count {
+ get {
+ var cmd = Connection.CreateCommand();
+ cmd.CommandText = "SELECT COUNT(*) FROM Messages";
+ return (int) Convert.ChangeType(cmd.ExecuteScalar(), typeof(int));
+ }
+ }
+
+ public override MessageModel this[int index] {
+ get {
+ return GetRange(index, 1).First();
+ }
+ set {
+ throw new NotImplementedException();
+ }
+ }
+
+ public SqliteMessageBuffer(string sessionUsername, string protocol,
+ string networkId, string chatId) :
+ base(sessionUsername, protocol, networkId, chatId)
+ {
+ DBPath = GetBufferPath() + ".sqlite3";
+ Connection = new SqliteConnection("URI=file:" + DBPath);
+ Connection.Open();
+
+ var sql = "CREATE TABLE IF NOT EXISTS Messages (" +
+ "ID INTEGER PRIMARY KEY," +
+ "JSON TEXT" +
+ ")";
+ var cmd = Connection.CreateCommand();
+ cmd.CommandText = sql;
+ cmd.ExecuteNonQuery();
+ }
+
+ /*
+ void SerializeChunk(List<MessageDtoModelV1> chunk, TextWriter writer)
+ {
+ DateTime start, stop;
+ start = DateTime.UtcNow;
+ JsonSerializer.SerializeToWriter(chunk, writer);
+ stop = DateTime.UtcNow;
+#if LOG4NET && MSGBUF_DEBUG
+ f_Logger.DebugFormat("SerializeChunk(): {0} items took: {1:0.00} ms",
+ chunk.Count,
+ (stop - start).TotalMilliseconds);
+#endif
+ }
+
+ List<MessageDtoModelV1> DeserializeChunk(TextReader reader)
+ {
+ DateTime start, stop;
+ start = DateTime.UtcNow;
+ var chunk = JsonSerializer.DeserializeFromReader<List<MessageDtoModelV1>>(reader);
+ stop = DateTime.UtcNow;
+#if LOG4NET && MSGBUF_DEBUG
+ f_Logger.DebugFormat("DeserializeChunk(): {0} items took: {1:0.00} ms",
+ chunk.Count,
+ (stop - start).TotalMilliseconds);
+#endif
+ return chunk;
+ }
+
+ List<MessageModel> LoadChunk(Int64 offset)
+ {
+ var chunk = new List<MessageModel>(MaxChunkSize);
+ var chunkFileName = GetChunkFileName(offset);
+ var chunkFilePath = Path.Combine(ChunkBasePath, chunkFileName);
+ if (!File.Exists(chunkFilePath)) {
+ return chunk;
+ }
+ using (var reader = File.OpenRead(chunkFilePath))
+ using (var textReader = new StreamReader(reader)) {
+ var dtoMsgs = DeserializeChunk(textReader);
+ foreach (var dtoMsg in dtoMsgs) {
+ chunk.Add(dtoMsg.ToMessage());
+ }
+ }
+ return chunk;
+ }
+
+ List<MessageDtoModelV1> LoadDtoChunk(Int64 offset)
+ {
+ var chunkFileName = GetChunkFileName(offset);
+ var chunkFilePath = Path.Combine(ChunkBasePath, chunkFileName);
+ if (!File.Exists(chunkFilePath)) {
+ return new List<MessageDtoModelV1>(0);
+ }
+ using (var reader = File.OpenRead(chunkFilePath))
+ using (var textReader = new StreamReader(reader)) {
+ return DeserializeChunk(textReader);
+ }
+ }
+*/
+
+ public override void Add(MessageModel msg)
+ {
+ if (msg == null) {
+ throw new ArgumentNullException("msg");
+ }
+
+ var dto = new MessageDtoModelV1(msg);
+ var json = JsonSerializer.SerializeToString(dto);
+
+ var cmd = Connection.CreateCommand();
+ cmd.CommandText = "INSERT INTO Messages (JSON)" +
+ " VALUES(@json)";
+ var param = cmd.CreateParameter();
+ param.ParameterName = "json";
+ param.Value = json;
+ cmd.Parameters.Add(param);
+
+ cmd.ExecuteNonQuery();
+ }
+
+ public override IList<MessageModel> GetRange(int offset, int limit)
+ {
+ using (var cmd = Connection.CreateCommand()) {
+ cmd.CommandText = "SELECT ID, JSON FROM Messages " +
+ " ORDER BY ID" +
+ " LIMIT @limit OFFSET @offset ";
+ var param = cmd.CreateParameter();
+ param.ParameterName = "offset";
+ param.Value = offset.ToString();
+ cmd.Parameters.Add(param);
+
+ param = cmd.CreateParameter();
+ param.ParameterName = "limit";
+ param.Value = limit.ToString();
+ cmd.Parameters.Add(param);
+
+ var reader = cmd.ExecuteReader();
+ var msgs = new List<MessageModel>(limit);
+ while (reader.Read()) {
+ var json = (string) reader["JSON"];
+ var dto = JsonSerializer.DeserializeFromString<MessageDtoModelV1>(json);
+ var msg = dto.ToMessage();
+ msgs.Add(msg);
+ }
+ return msgs;
+ }
+ }
+
+ public override void Clear()
+ {
+ var cmd = Connection.CreateCommand();
+ cmd.CommandText = "DELETE FROM Messages";
+ cmd.ExecuteNonQuery();
+ }
+
+ public override bool Contains(MessageModel item)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override void CopyTo(MessageModel[] array, int arrayIndex)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override bool Remove(MessageModel item)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override IEnumerator<MessageModel> GetEnumerator()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override int IndexOf(MessageModel item)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override void Insert(int index, MessageModel item)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override void RemoveAt(int index)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override void Dispose()
+ {
+ Flush();
+ }
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]