summaryrefslogtreecommitdiff
path: root/nejdb
diff options
context:
space:
mode:
authoradam <adamansky@gmail.com>2013-06-18 18:09:18 +0700
committeradam <adamansky@gmail.com>2013-06-18 18:09:18 +0700
commit21e36ade59ccc66e07fef689d62b70db23b203a8 (patch)
treebe480fb8f43fdb798e70b15dd996675c255f8459 /nejdb
parent2a40dfcb1e9a1cff29c72bea186af630658c146c (diff)
downloadejdb-21e36ade59ccc66e07fef689d62b70db23b203a8.tar.gz
ejdb-21e36ade59ccc66e07fef689d62b70db23b203a8.tar.bz2
ejdb-21e36ade59ccc66e07fef689d62b70db23b203a8.zip
#24
Diffstat (limited to 'nejdb')
-rw-r--r--nejdb/Ejdb.BSON/BSONIterator.cs16
-rw-r--r--nejdb/Ejdb.BSON/BSONOid.cs8
-rw-r--r--nejdb/Ejdb.DB/EJDB.cs147
-rw-r--r--nejdb/Ejdb.DB/EJDBQuery.cs33
-rw-r--r--nejdb/Ejdb.Tests/TestEJDB.cs31
-rw-r--r--nejdb/nejdb.csproj1
-rw-r--r--nejdb/nejdb.sln1
-rw-r--r--nejdb/nejdb.userprefs32
8 files changed, 231 insertions, 38 deletions
diff --git a/nejdb/Ejdb.BSON/BSONIterator.cs b/nejdb/Ejdb.BSON/BSONIterator.cs
index 8afc052..d7c15c3 100644
--- a/nejdb/Ejdb.BSON/BSONIterator.cs
+++ b/nejdb/Ejdb.BSON/BSONIterator.cs
@@ -22,8 +22,7 @@ using System.Collections.Generic;
namespace Ejdb.BSON {
- public class BSONIterator : IDisposable, IEnumerable<BSONType> {
-
+ public sealed class BSONIterator : IDisposable, IEnumerable<BSONType> {
ExtBinaryReader _input;
bool _closeOnDispose = true;
bool _disposed;
@@ -40,6 +39,12 @@ namespace Ejdb.BSON {
}
}
+ public bool Empty {
+ get {
+ return (_ctype == BSONType.EOO);
+ }
+ }
+
public int DocumentLength {
get { return _doclen; }
private set { _doclen = value; }
@@ -49,6 +54,10 @@ namespace Ejdb.BSON {
get { return _entryKey; }
}
+ public BSONIterator() { //empty iterator
+ this._ctype = BSONType.EOO;
+ }
+
public BSONIterator(BSONDocument doc) : this(doc.ToByteArray()) {
}
@@ -114,7 +123,10 @@ namespace Ejdb.BSON {
while (Next() != BSONType.EOO) {
yield return FetchCurrentValue();
}
+ }
+ public BSONDocument ToBSONDocument() {
+ return new BSONDocument(this);
}
public BSONType Next() {
diff --git a/nejdb/Ejdb.BSON/BSONOid.cs b/nejdb/Ejdb.BSON/BSONOid.cs
index 0afe745..9c3a835 100644
--- a/nejdb/Ejdb.BSON/BSONOid.cs
+++ b/nejdb/Ejdb.BSON/BSONOid.cs
@@ -14,7 +14,6 @@
// Boston, MA 02111-1307 USA.
// ============================================================================================
using System;
-using System.Text;
using System.IO;
namespace Ejdb.BSON {
@@ -83,6 +82,12 @@ namespace Ejdb.BSON {
return 0;
}
+ public byte[] ToBytes() {
+ var b = new byte[12];
+ Array.Copy(_bytes, b, 12);
+ return b;
+ }
+
public override string ToString() {
if (_cachedString == null) {
_cachedString = BitConverter.ToString(_bytes).Replace("-", "").ToLower();
@@ -131,6 +136,5 @@ namespace Ejdb.BSON {
public static implicit operator BSONOid(string val) {
return new BSONOid(val);
}
-
}
}
diff --git a/nejdb/Ejdb.DB/EJDB.cs b/nejdb/Ejdb.DB/EJDB.cs
index 824b3a2..197d5f4 100644
--- a/nejdb/Ejdb.DB/EJDB.cs
+++ b/nejdb/Ejdb.DB/EJDB.cs
@@ -21,27 +21,51 @@ using Ejdb.BSON;
namespace Ejdb.DB {
+ /// <summary>
+ /// Corresponds to <c>EJCOLLOPTS</c> in ejdb.h
+ /// </summary>
+ public struct EJDBCollectionOptionsN {
+ [MarshalAs(UnmanagedType.U1)]
+ public bool large;
+
+ [MarshalAs(UnmanagedType.U1)]
+ public bool compressed;
+
+ public long records;
+
+ public int cachedrecords;
+ }
+
public class EJDB : IDisposable {
//Open modes
public const int JBOREADER = 1 << 0;
+
public const int JBOWRITER = 1 << 1;
+
public const int JBOCREAT = 1 << 2;
+
public const int JBOTRUNC = 1 << 3;
+
public const int JBONOLCK = 1 << 4;
+
public const int JBOLCKNB = 1 << 5;
+
public const int JBOTSYNC = 1 << 6;
+
public const int DEFAULT_OPEN_MODE = (JBOWRITER | JBOCREAT);
+
public const string EJDB_LIB_NAME = "tcejdb";
+
IntPtr _db = IntPtr.Zero;
#region Functions
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdbnew")]
static extern IntPtr _ejdbnew();
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdbdel")]
- static extern IntPtr _ejdbdel(IntPtr db);
+ static extern IntPtr _ejdbdel([In] IntPtr db);
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdbopen")]
- static extern bool _ejdbopen(IntPtr db, IntPtr path, int mode);
+ static extern bool _ejdbopen([In] IntPtr db, [In] IntPtr path, int mode);
static bool _ejdbopen(IntPtr db, string path, int mode) {
IntPtr pptr = UnixMarshal.StringToHeap(path, Encoding.UTF8);
@@ -53,19 +77,19 @@ namespace Ejdb.DB {
}
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdbclose")]
- static extern bool _ejdbclose(IntPtr db);
+ static extern bool _ejdbclose([In] IntPtr db);
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdbisopen")]
- static extern bool _ejdbisopen(IntPtr db);
+ static extern bool _ejdbisopen([In] IntPtr db);
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdbecode")]
- static extern int _ejdbecode(IntPtr db);
+ static extern int _ejdbecode([In] IntPtr db);
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdberrmsg")]
static extern IntPtr _ejdberrmsg(int ecode);
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdbgetcoll")]
- static extern IntPtr _ejdbgetcoll(IntPtr db, IntPtr cname);
+ static extern IntPtr _ejdbgetcoll([In] IntPtr db, [In] IntPtr cname);
static IntPtr _ejdbgetcoll(IntPtr db, string cname) {
IntPtr cptr = UnixMarshal.StringToHeap(cname, Encoding.UTF8);
@@ -75,9 +99,30 @@ namespace Ejdb.DB {
UnixMarshal.FreeHeap(cptr);
}
}
+
+ [DllImport(EJDB_LIB_NAME, EntryPoint="ejdbcreatecoll")]
+ static extern IntPtr _ejdbcreatecoll([In] IntPtr db, [In] IntPtr cname, ref EJDBCollectionOptionsN? opts);
+
+ static IntPtr _ejdbcreatecoll(IntPtr db, String cname, EJDBCollectionOptionsN? opts) {
+ IntPtr cptr = UnixMarshal.StringToHeap(cname, Encoding.UTF8);
+ try {
+ return _ejdbcreatecoll(db, cptr, ref opts);
+ } finally {
+ UnixMarshal.FreeHeap(cptr);
+ }
+ }
//EJDB_EXPORT bool ejdbsavebson3(EJCOLL *jcoll, void *bsdata, bson_oid_t *oid, bool merge);
[DllImport(EJDB_LIB_NAME, EntryPoint="ejdbsavebson3")]
- static extern IntPtr _ejdbsavebson(IntPtr coll, [In] byte[] bsdata, [Out] byte[] oid, bool merge);
+ static extern bool _ejdbsavebson([In] IntPtr coll, [In] byte[] bsdata, [Out] byte[] oid, [In] bool merge);
+ //EJDB_EXPORT bson* ejdbloadbson(EJCOLL *coll, const bson_oid_t *oid);
+ [DllImport(EJDB_LIB_NAME, EntryPoint="ejdbloadbson")]
+ static extern IntPtr _ejdbloadbson([In] IntPtr coll, [In] byte[] oid);
+ //EJDB_EXPORT const char* bson_data2(const bson *b, int *bsize);
+ [DllImport(EJDB_LIB_NAME, EntryPoint="bson_data2")]
+ static extern IntPtr _bson_data2([In] IntPtr bsptr, out int size);
+ //EJDB_EXPORT void bson_del(bson *b);
+ [DllImport(EJDB_LIB_NAME, EntryPoint="bson_del")]
+ static extern void _bson_del([In] IntPtr bsptr);
#endregion
/// <summary>
/// Gets the last DB error code or <c>null</c> if underlying native database object does not exist.
@@ -142,13 +187,29 @@ namespace Ejdb.DB {
if (_db != IntPtr.Zero) {
IntPtr db = _db;
_db = IntPtr.Zero;
- if (_db != IntPtr.Zero) {
+ if (db != IntPtr.Zero) {
_ejdbdel(db);
}
}
}
/// <summary>
+ /// Automatically creates new collection if it does't exists.
+ /// </summary>
+ /// <remarks>
+ /// Collection options <c>copts</c> are applied only for newly created collection.
+ /// For existing collections <c>copts</c> has no effect.
+ /// </remarks>
+ /// <returns><c>false</c> error ocurried.</returns>
+ /// <param name="cname">Name of collection.</param>
+ /// <param name="copts">Collection options.</param>
+ public bool EnsureCollection(string cname, EJDBCollectionOptionsN? copts = null) {
+ CheckDisposed();
+ IntPtr cptr = _ejdbcreatecoll(_db, cname, copts);
+ return (cptr != IntPtr.Zero);
+ }
+
+ /// <summary>
/// Save the BSON document doc into the collection cname.
/// </summary>
/// <param name="cname">Name of collection.</param>
@@ -157,18 +218,76 @@ namespace Ejdb.DB {
/// If true the merge will be performend with old and new objects.
/// Otherwise old object will be replaced.</param>
/// <returns>True on success.</returns>
- public bool Save(string cname, BSONDocument doc, bool merge) {
- bool rv = false;
- IntPtr cptr = _ejdbgetcoll(_db, cname);
+ public bool Save(string cname, BSONDocument doc, bool merge = false) {
+ CheckDisposed();
+ bool rv;
+ IntPtr cptr = _ejdbcreatecoll(_db, cname, null);
if (cptr == IntPtr.Zero) {
return false;
}
BSONValue bv = doc.GetBSONValue("_id");
- byte[] bdoc = doc.ToByteArray();
- //todo
-
+ byte[] bsdata = doc.ToByteArray();
+ byte[] oiddata = new byte[12];
+ //static extern bool _ejdbsavebson([In] IntPtr coll, [In] byte[] bsdata, [Out] byte[] oid, bool merge);
+ rv = _ejdbsavebson(cptr, bsdata, oiddata, merge);
+ if (rv && bv == null) {
+ doc.SetOID("_id", new BSONOid(oiddata));
+ }
return rv;
}
+
+ /// <summary>
+ /// Loads JSON object identified by OID from the collection.
+ /// </summary>
+ /// <remarks>
+ /// Returns <c>null</c> if object is not found.
+ /// </remarks>
+ /// <param name="cname">Cname.</param>
+ /// <param name="oid">Oid.</param>
+ public BSONIterator Load(string cname, BSONOid oid) {
+ CheckDisposed();
+ IntPtr cptr = _ejdbgetcoll(_db, cname);
+ if (cptr == IntPtr.Zero) {
+ return null;
+ }
+ //static extern IntPtr _ejdbloadbson([In] IntPtr coll, [In] byte[] oid);
+ byte[] bsdata = BsonPtrIntoByteArray(_ejdbloadbson(cptr, oid.ToBytes()));
+ if (bsdata.Length == 0) {
+ return null;
+ }
+ return new BSONIterator(bsdata);
+ }
+
+ /// <summary>
+ /// Creates the query.
+ /// </summary>
+ /// <returns>The query object.</returns>
+ /// <param name="qdoc">BSON query spec.</param>
+ public EJDBQuery CreateQuery(BSONDocument qdoc) {
+ return new EJDBQuery(qdoc);
+ }
+ //.//////////////////////////////////////////////////////////////////
+ // Private staff //
+ //.//////////////////////////////////////////////////////////////////
+ byte[] BsonPtrIntoByteArray(IntPtr bsptr, bool deletebsptr = true) {
+ if (bsptr == IntPtr.Zero) {
+ return new byte[0];
+ }
+ int size;
+ IntPtr bsdataptr = _bson_data2(bsptr, out size);
+ byte[] bsdata = new byte[size];
+ Marshal.Copy(bsdataptr, bsdata, 0, bsdata.Length);
+ if (deletebsptr) {
+ _bson_del(bsptr);
+ }
+ return bsdata;
+ }
+
+ void CheckDisposed() {
+ if (_db == IntPtr.Zero) {
+ throw new ObjectDisposedException("Database is disposed");
+ }
+ }
}
}
diff --git a/nejdb/Ejdb.DB/EJDBQuery.cs b/nejdb/Ejdb.DB/EJDBQuery.cs
new file mode 100644
index 0000000..1e69891
--- /dev/null
+++ b/nejdb/Ejdb.DB/EJDBQuery.cs
@@ -0,0 +1,33 @@
+// ============================================================================================
+// .NET API for EJDB database library http://ejdb.org
+// Copyright (C) 2012-2013 Softmotions Ltd <info@softmotions.com>
+//
+// This file is part of EJDB.
+// EJDB is free software; you can redistribute it and/or modify it under the terms of
+// the GNU Lesser General Public License as published by the Free Software Foundation; either
+// version 2.1 of the License or any later version. EJDB 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 Lesser General Public
+// License for more details.
+// You should have received a copy of the GNU Lesser General Public License along with EJDB;
+// if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+// Boston, MA 02111-1307 USA.
+// ============================================================================================
+using System;
+using Ejdb.BSON;
+
+namespace Ejdb.DB {
+
+ public class EJDBQuery : IDisposable {
+
+ IntPtr _qptr;
+
+ internal EJDBQuery(BSONDocument qdoc) {
+ }
+
+ public void Dispose() {
+ throw new NotImplementedException();
+ }
+ }
+}
+
diff --git a/nejdb/Ejdb.Tests/TestEJDB.cs b/nejdb/Ejdb.Tests/TestEJDB.cs
index 44ac7d5..bb43c86 100644
--- a/nejdb/Ejdb.Tests/TestEJDB.cs
+++ b/nejdb/Ejdb.Tests/TestEJDB.cs
@@ -16,11 +16,13 @@
using System;
using NUnit.Framework;
using Ejdb.DB;
+using Ejdb.BSON;
namespace Ejdb.Tests {
[TestFixture]
public class TestEJDB {
+
[Test]
public void TestOpenClose() {
@@ -33,9 +35,38 @@ namespace Ejdb.Tests {
jb.Dispose(); //double dispose
}
+ [Test]
+ public void TestEnsureCollection() {
+ EJDB jb = new EJDB("testdb1", EJDB.DEFAULT_OPEN_MODE | EJDB.JBOTRUNC);
+ EJDBCollectionOptionsN co = new EJDBCollectionOptionsN();
+ co.large = true;
+ co.compressed = false;
+ co.records = 50000;
+ Assert.IsTrue(jb.EnsureCollection("mycoll2", co));
+ jb.Dispose();
+ }
+ [Test]
+ public void TestSaveLoad() {
+ EJDB jb = new EJDB("testdb1", EJDB.DEFAULT_OPEN_MODE | EJDB.JBOTRUNC);
+ Assert.IsTrue(jb.IsOpen);
+ BSONDocument doc = new BSONDocument().SetNumber("age", 33);
+ Assert.IsNull(doc["_id"]);
+ bool rv = jb.Save("mycoll", doc);
+ Assert.IsTrue(rv);
+ Assert.IsNotNull(doc["_id"]);
+ Assert.IsInstanceOfType(typeof(BSONOid), doc["_id"]);
+ rv = jb.Save("mycoll", doc);
+ Assert.IsTrue(rv);
+ BSONIterator it = jb.Load("mycoll", doc["_id"] as BSONOid);
+ Assert.IsNotNull(it);
+ BSONDocument doc2 = it.ToBSONDocument();
+ Assert.AreEqual(doc.ToDebugDataString(), doc2.ToDebugDataString());
+ Assert.IsTrue(doc == doc2);
+ jb.Dispose();
+ }
}
}
diff --git a/nejdb/nejdb.csproj b/nejdb/nejdb.csproj
index eb07c23..aceb9c7 100644
--- a/nejdb/nejdb.csproj
+++ b/nejdb/nejdb.csproj
@@ -64,6 +64,7 @@
<Compile Include="Ejdb.JSON\JSONElement.cs" />
<Compile Include="Ejdb.DB\EJDBException.cs" />
<Compile Include="Ejdb.Tests\TestEJDB.cs" />
+ <Compile Include="Ejdb.DB\EJDBQuery.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
diff --git a/nejdb/nejdb.sln b/nejdb/nejdb.sln
index a7b1ce9..940045c 100644
--- a/nejdb/nejdb.sln
+++ b/nejdb/nejdb.sln
@@ -52,6 +52,7 @@ Global
$4.SpacesBeforeBrackets = False
$4.SpacesAfterTypecast = True
$4.BlankLinesBeforeFirstDeclaration = 1
+ $4.BlankLinesBetweenFields = 1
$4.BlankLinesBetweenEventFields = 1
$4.inheritsSet = Mono
$4.inheritsScope = text/x-csharp
diff --git a/nejdb/nejdb.userprefs b/nejdb/nejdb.userprefs
index 4b8db9d..78732cb 100644
--- a/nejdb/nejdb.userprefs
+++ b/nejdb/nejdb.userprefs
@@ -2,12 +2,15 @@
<MonoDevelop.Ide.Workspace ActiveConfiguration="Debug" />
<MonoDevelop.Ide.Workbench ActiveDocument="Ejdb.DB/EJDB.cs">
<Files>
- <File FileName="Ejdb.Tests/TestBSON.cs" Line="27" Column="21" />
- <File FileName="Ejdb.DB/EJDB.cs" Line="80" Column="74" />
+ <File FileName="Ejdb.DB/EJDB.cs" Line="266" Column="13" />
<File FileName="Ejdb.BSON/BSONType.cs" Line="1" Column="1" />
- <File FileName="Ejdb.Tests/TestEJDB.cs" Line="36" Column="3" />
- <File FileName="Ejdb.BSON/BSONDocument.cs" Line="191" Column="24" />
- <File FileName="Ejdb.BSON/BSONOid.cs" Line="133" Column="4" />
+ <File FileName="Ejdb.Tests/TestEJDB.cs" Line="53" Column="23" />
+ <File FileName="Ejdb.BSON/BSONDocument.cs" Line="1" Column="1" />
+ <File FileName="Ejdb.BSON/BSONOid.cs" Line="1" Column="1" />
+ <File FileName="Ejdb.BSON/BSONIterator.cs" Line="326" Column="3" />
+ <File FileName="Ejdb.Tests/TestBSON.cs" Line="15" Column="49" />
+ <File FileName="Ejdb.DB/EJDBQuery.cs" Line="31" Column="3" />
+ <File FileName="Ejdb.DB/EJDBException.cs" Line="1" Column="1" />
</Files>
<Pads>
<Pad Id="ProjectPad">
@@ -39,27 +42,16 @@
<Value>_input.BaseStream.Position</Value>
</State>
</Pad>
+ <Pad Id="MonoDevelop.NUnit.TestPad">
+ <State expanded="True" selected="True" />
+ </Pad>
<Pad Id="ConnectionManagerPad">
<State selected="True" />
</Pad>
- <Pad Id="MonoDevelop.NUnit.TestPad">
- <State expanded="True" selected="True">
- <Node name="nejdb" expanded="True">
- <Node name="Ejdb" expanded="True">
- <Node name="Tests" expanded="True">
- <Node name="TestBSON" expanded="True" />
- <Node name="TestEJDB" expanded="True" />
- </Node>
- </Node>
- </Node>
- </State>
- </Pad>
</Pads>
</MonoDevelop.Ide.Workbench>
<MonoDevelop.Ide.DebuggingService.Breakpoints>
- <BreakpointStore>
- <Breakpoint file="/home/adam/Projects/softmotions/ejdb/nejdb/Ejdb.SON/BSONIterator.cs" line="96" column="1" />
- </BreakpointStore>
+ <BreakpointStore />
</MonoDevelop.Ide.DebuggingService.Breakpoints>
<MonoDevelop.Ide.DebuggingService.PinnedWatches />
</Properties> \ No newline at end of file