Skip to content

Commit

Permalink
Merge pull request litedb-org#7 from mbdavid/dev
Browse files Browse the repository at this point in the history
Merge version 0.9
  • Loading branch information
mbdavid committed Feb 5, 2015
2 parents 1225719 + c585f7a commit a633d79
Show file tree
Hide file tree
Showing 36 changed files with 371 additions and 226 deletions.
2 changes: 1 addition & 1 deletion LiteDB/Document/BsonArray.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public BsonArray()
{
}

public BsonArray(List<object> array)
internal BsonArray(List<object> array)
: base(array)
{
}
Expand Down
2 changes: 1 addition & 1 deletion LiteDB/Document/BsonDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace LiteDB
/// </summary>
public class BsonDocument : BsonObject
{
public const int MAX_DOCUMENT_SIZE = 1 * 1024 * 1024; // limits in 1MB max document size to avoid large documents, memory usage and slow performance
public const int MAX_DOCUMENT_SIZE = 256 * BasePage.PAGE_AVAILABLE_BYTES; // limits in 1.044.224b max document size to avoid large documents, memory usage and slow performance

public BsonDocument()
: base()
Expand Down
2 changes: 1 addition & 1 deletion LiteDB/Document/BsonObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public BsonObject()
{
}

public BsonObject(Dictionary<string, object> obj)
internal BsonObject(Dictionary<string, object> obj)
: base(obj)
{
}
Expand Down
4 changes: 2 additions & 2 deletions LiteDB/Engine/Collections/Collection.Find.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public T FindById(object id)

var dataBlock = _engine.Data.Read(node.DataBlock, true);

var doc = BsonSerializer.Deserialize<T>(dataBlock.Key, dataBlock.Data);
var doc = BsonSerializer.Deserialize<T>(dataBlock.Key, dataBlock.Buffer);

foreach (var action in _includes)
{
Expand Down Expand Up @@ -69,7 +69,7 @@ public IEnumerable<T> Find(Query query)
{
var dataBlock = _engine.Data.Read(node.DataBlock, true);

var doc = BsonSerializer.Deserialize<T>(dataBlock.Key, dataBlock.Data);
var doc = BsonSerializer.Deserialize<T>(dataBlock.Key, dataBlock.Buffer);

foreach (var action in _includes)
{
Expand Down
2 changes: 1 addition & 1 deletion LiteDB/Engine/Collections/Collection.Index.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public virtual bool EnsureIndex(string field, bool unique = false)
var dataBlock = _engine.Data.Read(node.DataBlock, true);

// read object
var doc = BsonSerializer.Deserialize<T>(dataBlock.Key, dataBlock.Data);
var doc = BsonSerializer.Deserialize<T>(dataBlock.Key, dataBlock.Buffer);

// adding index
var key = BsonSerializer.GetFieldValue(doc, field);
Expand Down
2 changes: 1 addition & 1 deletion LiteDB/Engine/FileStorage/FileEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class FileEntry
/// <summary>
/// Number of bytes on each chunk document to store
/// </summary>
public const int CHUNK_SIZE = 50 * BasePage.PAGE_AVAILABLE_BYTES; // 50 extend page
public const int CHUNK_SIZE = BsonDocument.MAX_DOCUMENT_SIZE - BasePage.PAGE_AVAILABLE_BYTES; // Chunk size is a page less than a max document size

public string Id { get; private set; }
public string Filename { get; set; }
Expand Down
24 changes: 2 additions & 22 deletions LiteDB/Engine/LiteEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ public LiteEngine(string connectionString)
{
this.ConnectionString = new ConnectionString(connectionString);

if (!File.Exists(ConnectionString.Filename))
if (!File.Exists(this.ConnectionString.Filename))
{
CreateNewDatabase(ConnectionString);
DiskService.CreateNewDatafile(this.ConnectionString);
}

this.Recovery = new RecoveryService(this.ConnectionString);
Expand Down Expand Up @@ -148,26 +148,6 @@ public void Rollback()

#endregion

#region Statics methods

/// <summary>
/// Create a empty database ready to be used using connectionString as parameters
/// </summary>
private static void CreateNewDatabase(ConnectionString connectionString)
{
using (var stream = File.Create(connectionString.Filename))
{
using (var writer = new BinaryWriter(stream))
{
// creating header + master collection
DiskService.WritePage(writer, new HeaderPage { PageID = 0, LastPageID = 1 });
DiskService.WritePage(writer, new CollectionPage { PageID = 1, CollectionName = "_master" });
}
}
}

#endregion

public void Dispose()
{
this.Disk.Dispose();
Expand Down
2 changes: 2 additions & 0 deletions LiteDB/LiteDB.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\LiteDB.xml</DocumentationFile>
<NoWarn>1591</NoWarn>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
Expand All @@ -33,6 +34,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
Expand Down
4 changes: 2 additions & 2 deletions LiteDB/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
[assembly: ComVisible(false)]
[assembly: Guid("54989b5c-4bcf-4d58-b8ba-9b014a324f76")]

[assembly: AssemblyVersion("0.8.0.0")]
[assembly: AssemblyFileVersion("0.8.0.0")]
[assembly: AssemblyVersion("0.9.0.0")]
[assembly: AssemblyFileVersion("0.9.0.0")]

[assembly: InternalsVisibleTo("UnitTest")]
[assembly: InternalsVisibleTo("LiteDB.Shell")]
51 changes: 33 additions & 18 deletions LiteDB/Serializer/BsonSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,36 @@ internal class BsonSerializer
static BsonSerializer()
{
fastBinaryJSON.BJSON.Parameters.UseExtensions = false;
fastBinaryJSON.BJSON.Parameters.IgnoreAttributes.Clear();

// BsonId will can be excluded from byte[] data on convert - DataBlock as a special Key data
fastBinaryJSON.BJSON.Parameters.IgnoreAttributes.Add(typeof(BsonIdAttribute));
fastBinaryJSON.BJSON.Parameters.IgnoreAttributes.Add(typeof(BsonIgnoreAttribute));

fastBinaryJSON.BJSON.Parameters.UsingGlobalTypes = false;
}

public static byte[] Serialize(object obj)
{
if (obj == null) throw new ArgumentNullException("obj");
byte[] bytes;

if(obj is BsonDocument)
{
bytes = fastBinaryJSON.BJSON.ToBJSON(((BsonDocument)obj).RawValue);
}
else
{
// add parameters on serialization to ignore BsonIgnoreAttribute + Id attribute
var param = new fastBinaryJSON.BJSONParameters
{
UseExtensions = false,
UsingGlobalTypes = false,
IgnoreAttributes = new List<Type> { typeof(BsonIgnoreAttribute) },
IgnoreProperty = GetIdProperty(obj.GetType())
};

var bytes = obj is BsonDocument ?
fastBinaryJSON.BJSON.ToBJSON(((BsonDocument)obj).RawValue) :
fastBinaryJSON.BJSON.ToBJSON(obj);
bytes = fastBinaryJSON.BJSON.ToBJSON(obj, param);
}

if (bytes.Length > BsonDocument.MAX_DOCUMENT_SIZE)
{
throw new LiteException("Document size too long");
}

return bytes;
}
Expand All @@ -50,9 +61,9 @@ public static T Deserialize<T>(IndexKey key, byte[] data)

if (typeof(T) == typeof(BsonDocument))
{
var dict = fastBinaryJSON.BJSON.Parse(data);
var dict = (Dictionary<string, object>)fastBinaryJSON.BJSON.Parse(data);

doc = new BsonDocument((Dictionary<string, object>)dict);
doc = new BsonDocument(dict);
}
else
{
Expand All @@ -65,7 +76,7 @@ public static T Deserialize<T>(IndexKey key, byte[] data)
}

/// <summary>
/// Gets from a document object (plain C# object or BsonDocument) some field value
/// Gets from a document object (plain C# object or BsonDocument) some field value. Returns "null" when not found any value/path
/// </summary>
public static object GetFieldValue(object obj, string fieldName)
{
Expand Down Expand Up @@ -141,14 +152,18 @@ public static void SetIdValue(object obj, object id)
/// </summary>
public static PropertyInfo GetIdProperty(Type type)
{
if (_cacheId.ContainsKey(type))
return _cacheId[type];
PropertyInfo prop;

if(_cacheId.TryGetValue(type, out prop))
{
return prop;
}

// Get all properties and test in order: BsonIdAttribute, "Id" name, "<typeName>Id" name
var prop = SelectProperty(type.GetProperties(),
x => Attribute.IsDefined(x, typeof(BsonIdAttribute), true));
//x => x.Name.Equals("Id", StringComparison.InvariantCultureIgnoreCase),
//x => x.Name.Equals(type.Name + "Id", StringComparison.InvariantCultureIgnoreCase));
prop = SelectProperty(type.GetProperties(),
x => Attribute.IsDefined(x, typeof(BsonIdAttribute), true),
x => x.Name.Equals("Id", StringComparison.InvariantCultureIgnoreCase),
x => x.Name.Equals(type.Name + "Id", StringComparison.InvariantCultureIgnoreCase));

if (prop != null)
{
Expand Down
2 changes: 1 addition & 1 deletion LiteDB/Serializer/JsonEx/JsonWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ private void WriteArray(BsonArray arr)

this.WriteStartBlock("[", hasData);

for(var i = 0; i < arr.Length; i++)
for (var i = 0; i < arr.Length; i++)
{
var item = arr[i];

Expand Down
5 changes: 5 additions & 0 deletions LiteDB/Serializer/fastBinaryJSON/BJSON.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ public sealed class BJSONParameters
/// Ignore attributes to check for (default : XmlIgnoreAttribute)
/// </summary>
public List<Type> IgnoreAttributes = new List<Type> { typeof(System.Xml.Serialization.XmlIgnoreAttribute) };

/// <summary>
/// Ignore this property when serialize object (CHANGE TO ** LITEDB **)
/// </summary>
public PropertyInfo IgnoreProperty = null;
/// <summary>
/// If you have parametric and no default constructor for you classes (default = False)
///
Expand Down
2 changes: 2 additions & 0 deletions LiteDB/Serializer/fastBinaryJSON/Reflection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,8 @@ internal Getters[] GetGetters(Type type, BJSONParameters param)
List<Getters> getters = new List<Getters>();
foreach (PropertyInfo p in props)
{
// CHANGED FOR ** LITEDB ** IgnoreProperty
if (param.IgnoreProperty != null && p.MetadataToken == param.IgnoreProperty.MetadataToken && p.Module.Equals(param.IgnoreProperty.Module)) continue;
if (!p.CanWrite && param.ShowReadOnlyProperties == false) continue;
if (param.IgnoreAttributes != null)
{
Expand Down
2 changes: 1 addition & 1 deletion LiteDB/Shell/Commands/Collections/BaseCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ private Query ReadInlineQuery(StringScanner s)

private Query ReadOneQuery(StringScanner s)
{
var field = s.Scan(@"\w+(.\w+)*\s*").Trim();
var field = s.Scan(@"\w+(\.\w+)*\s*").Trim();
var oper = s.Scan(@"(=|!=|>=|<=|>|<|like|in|between)");
var value = new JsonReader().ReadValue(s);

Expand Down
4 changes: 4 additions & 0 deletions LiteDB/Shell/Commands/Files/Download.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ public void Execute(LiteEngine db, StringScanner s, Display display)
file.SaveAs(filename, true);
display.WriteBson(file.AsDocument);
}
else
{
display.WriteBson(false);
}
}
}
}
20 changes: 8 additions & 12 deletions LiteDB/Storage/Pages/BasePage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,14 @@ internal class BasePage
public const int PAGE_SIZE = 4096;

/// <summary>
/// This size is used bytes in header pages [17 bytes + 18 reserved]
/// This size is used bytes in header pages 17 bytes
/// </summary>
public const int PAGE_HEADER_SIZE = 35;
public const int PAGE_HEADER_SIZE = 17;

/// <summary>
/// Bytes avaiable to store data removing page header size - 4060 bytes
/// I really dont know why -1 in AVAILABLE_BYTES - but if I dont use, pages overflow on write to disk (see exception there)
/// Bytes avaiable to store data removing page header size - 4079 bytes
/// </summary>
public const int PAGE_AVAILABLE_BYTES = PAGE_SIZE - PAGE_HEADER_SIZE - 1;

/// <summary>
/// If a page has less that this number, it's considered full page for new items. Can be used only for update (DataPage) ~ 15% PAGE_SIZE
/// </summary>
public const int RESERVED_BYTES = 600;
public const int PAGE_AVAILABLE_BYTES = PAGE_SIZE - PAGE_HEADER_SIZE;

#endregion

Expand All @@ -57,11 +51,13 @@ internal class BasePage

/// <summary>
/// Used for all pages to count itens inside this page(bytes, nodes, blocks, ...)
/// Its Int32 but writes in UInt16
/// </summary>
public int ItemCount { get; set; }

/// <summary>
/// Must be overite for each page. Used to find a free page using only header search [used in FreeList]
/// Its Int32 but writes in UInt16
/// </summary>
public virtual int FreeBytes { get; set; }

Expand Down Expand Up @@ -124,7 +120,7 @@ public virtual void ReadHeader(BinaryReader reader)
this.NextPageID = reader.ReadUInt32();
this.PageType = (PageType)reader.ReadByte();
this.ItemCount = reader.ReadUInt16();
this.FreeBytes = reader.ReadInt32();
this.FreeBytes = reader.ReadUInt16();
}

public virtual void WriteHeader(BinaryWriter writer)
Expand All @@ -135,7 +131,7 @@ public virtual void WriteHeader(BinaryWriter writer)
writer.Write((byte)this.PageType);
UpdateItemCount(); // updating ItemCount before save on disk
writer.Write((UInt16)this.ItemCount);
writer.Write(this.FreeBytes);
writer.Write((UInt16)this.FreeBytes);
}

#endregion
Expand Down
5 changes: 5 additions & 0 deletions LiteDB/Storage/Pages/DataPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ namespace LiteDB
/// </summary>
internal class DataPage : BasePage
{
/// <summary>
/// If a Data Page has less that free space, it's considered full page for new items. Can be used only for update (DataPage) ~ 15% PAGE_SIZE
/// </summary>
public const int RESERVED_BYTES = 800;

/// <summary>
/// Returns all data blocks - Each block has one object
/// </summary>
Expand Down
10 changes: 5 additions & 5 deletions LiteDB/Storage/Pages/HeaderPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ internal class HeaderPage : BasePage
/// <summary>
/// Datafile specification version
/// </summary>
private const byte FILE_VERSION = 2;
private const byte FILE_VERSION = 3;

/// <summary>
/// Get/Set the changeID of data. When a client read pages, all pages are in the same version. But when OpenTransaction, we need validade that current changeID is the sabe that we have in cache
Expand Down Expand Up @@ -52,18 +52,18 @@ public HeaderPage()

public override void ReadHeader(BinaryReader reader)
{
reader.Seek(4); // skip byte 0 - it's loked in a transaction
reader.BaseStream.Seek(4, SeekOrigin.Current); // skip byte 0 - it's loked in a transaction
//this.PageID = reader.ReadUInt32();
this.PrevPageID = reader.ReadUInt32();
this.NextPageID = reader.ReadUInt32();
this.PageType = (PageType)reader.ReadByte();
this.ItemCount = reader.ReadUInt16();
this.FreeBytes = reader.ReadInt32();
this.FreeBytes = reader.ReadUInt16();
}

public override void ReadContent(BinaryReader reader)
{
var info = reader.ReadString(BasePage.PAGE_HEADER_SIZE);
var info = reader.ReadString(HEADER_INFO.Length);

if (info != HEADER_INFO)
throw new LiteException("This file is not a LiteDB datafile");
Expand All @@ -79,7 +79,7 @@ public override void ReadContent(BinaryReader reader)

public override void WriteContent(BinaryWriter writer)
{
writer.Write(HEADER_INFO, BasePage.PAGE_HEADER_SIZE);
writer.Write(HEADER_INFO, HEADER_INFO.Length);
writer.Write(FILE_VERSION);
writer.Write(this.ChangeID);
writer.Write(this.FreeEmptyPageID);
Expand Down
Loading

0 comments on commit a633d79

Please sign in to comment.