diff options
author | adam <adamansky@gmail.com> | 2013-06-18 18:09:18 +0700 |
---|---|---|
committer | adam <adamansky@gmail.com> | 2013-06-18 18:09:18 +0700 |
commit | 21e36ade59ccc66e07fef689d62b70db23b203a8 (patch) | |
tree | be480fb8f43fdb798e70b15dd996675c255f8459 /nejdb | |
parent | 2a40dfcb1e9a1cff29c72bea186af630658c146c (diff) | |
download | ejdb-21e36ade59ccc66e07fef689d62b70db23b203a8.tar.gz ejdb-21e36ade59ccc66e07fef689d62b70db23b203a8.tar.bz2 ejdb-21e36ade59ccc66e07fef689d62b70db23b203a8.zip |
#24
Diffstat (limited to 'nejdb')
-rw-r--r-- | nejdb/Ejdb.BSON/BSONIterator.cs | 16 | ||||
-rw-r--r-- | nejdb/Ejdb.BSON/BSONOid.cs | 8 | ||||
-rw-r--r-- | nejdb/Ejdb.DB/EJDB.cs | 147 | ||||
-rw-r--r-- | nejdb/Ejdb.DB/EJDBQuery.cs | 33 | ||||
-rw-r--r-- | nejdb/Ejdb.Tests/TestEJDB.cs | 31 | ||||
-rw-r--r-- | nejdb/nejdb.csproj | 1 | ||||
-rw-r--r-- | nejdb/nejdb.sln | 1 | ||||
-rw-r--r-- | nejdb/nejdb.userprefs | 32 |
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 |