Skip to content

Commit

Permalink
Fixes #637
Browse files Browse the repository at this point in the history
  • Loading branch information
borrrden committed May 7, 2016
1 parent 98a249e commit b223cec
Show file tree
Hide file tree
Showing 11 changed files with 41 additions and 408 deletions.
17 changes: 13 additions & 4 deletions Notes/StorageEngineOverview.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
*TL;DR (well...DWTR)*: This is how to enable the various storage modes of Couchbase Lite:

1. System SQLite - Do nothing
2. SQLite with encryption - Add the Couchbase.Lite.Storage.SQLCipher nuget package
3. ForestDB (with or without encryption is the same) - Add the Couchbase.Lite.Storage.ForestDB nuget package
1. System SQLite
a. iOS - Call Couchbase.Lite.Storage.SystemSQLite.Plugin.Register()
b. Others - Either do the above or do nothing
2. SQLite with encryption - Add the Couchbase.Lite.Storage.SQLCipher nuget package and call Couchbase.Lite.Storage.SQLCipher.Plugin.Register()
3. ForestDB (with or without encryption is the same) - Add the Couchbase.Lite.Storage.ForestDB nuget package and call Couchbase.Lite.Storage.ForestDB.Plugin.Register()

Changes in 1.2
==============
Expand All @@ -21,7 +23,14 @@ The third one uses ForestDB, which is a key value storage library that Couchbase

Note that to make the selection process as automatic as possible, I have implemented a sort of hierarchy. If you include the SQLCipher package it will override the SystemSQLite package. You can check the logs to figure out which plugin has been loaded if you are unsure. Make sure if you want to switch back to SystemSQLite from SQLCipher that you clean the project and ensure that the SQLCipher plugin DLL is not present.

Changes in 1.3
==============

The registration system for plugins is now manual since automatic registration caused too many headaches on AOT platforms which would strip the references to the plugins that it thought were not being used.

Details about this system
=========================

All of the managed functionality, and native image binding, has been refactored into separate pluggable assemblies. The system will attempt to use `Assembly.Load` to load the correct assemblies at runtime. There is no need to worry about binding to the wrong native library since the binding is not chosen via program logic directly, but rather by which managed code gets loaded.
1.2: All of the managed functionality, and native image binding, has been refactored into separate pluggable assemblies. The system will attempt to use `Assembly.Load` to load the correct assemblies at runtime. There is no need to worry about binding to the wrong native library since the binding is not chosen via program logic directly, but rather by which managed code gets loaded.

**NOTE** 1.3 Changes this to require a manual registration call to replace Assembly.Load.
2 changes: 2 additions & 0 deletions samples/CouchbaseSample.iOS/AppDelegate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
window = new UIWindow (UIScreen.MainScreen.Bounds);

Couchbase.Lite.Storage.SystemSQLite.Plugin.Register();

var controller = new RootViewController();
window.TintColor = UIColor.FromRGB(0.564f, 0.0f, 0.015f);
controller.EdgesForExtendedLayout = UIRectEdge.None;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<MtouchLink>None</MtouchLink>
<ConsolePause>false</ConsolePause>
<MtouchDebug>true</MtouchDebug>
<MtouchArch>i386, x86_64</MtouchArch>
Expand All @@ -39,19 +38,15 @@
<OutputPath>bin\iPhone\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<MtouchLink>None</MtouchLink>
<ConsolePause>false</ConsolePause>
<DebugSymbols>true</DebugSymbols>
<MtouchExtraArgs>--registrar=static</MtouchExtraArgs>
<MtouchArch>ARMv7</MtouchArch>
<MtouchArch>i386, x86_64</MtouchArch>
<Platform>iPhone</Platform>
<MtouchUseThumb>true</MtouchUseThumb>
<MtouchUseRefCounting>true</MtouchUseRefCounting>
<CodesignKey>iPhone Developer</CodesignKey>
<MtouchFloat32>true</MtouchFloat32>
<MtouchNoSymbolStrip>true</MtouchNoSymbolStrip>
<MtouchI18n>
</MtouchI18n>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
<DebugSymbols>true</DebugSymbols>
Expand All @@ -69,7 +64,6 @@
<MtouchArch>ARMv7, ARM64</MtouchArch>
<MtouchExtraArgs>--registrar=static</MtouchExtraArgs>
<MtouchNoSymbolStrip>true</MtouchNoSymbolStrip>
<MtouchLink>None</MtouchLink>
<DeviceSpecificBuild>true</DeviceSpecificBuild>
<MtouchFloat32>true</MtouchFloat32>
</PropertyGroup>
Expand All @@ -82,57 +76,16 @@
<CodesignKey>iPhone Developer</CodesignKey>
<ConsolePause>false</ConsolePause>
<MtouchExtraArgs>--registrar=static</MtouchExtraArgs>
<MtouchArch>ARMv7</MtouchArch>
<MtouchArch>ARMv7, ARM64</MtouchArch>
<Platform>iPhone</Platform>
<MtouchUseRefCounting>True</MtouchUseRefCounting>
<IpaPackageName>
</IpaPackageName>
<MtouchLink>SdkOnly</MtouchLink>
<MtouchFloat32>True</MtouchFloat32>
<MtouchI18n>
</MtouchI18n>
<MtouchSdkVersion>9.3</MtouchSdkVersion>
<MtouchDebug>False</MtouchDebug>
<MtouchProfiling>False</MtouchProfiling>
<MtouchFastDev>False</MtouchFastDev>
<MtouchUseLlvm>False</MtouchUseLlvm>
<MtouchUseThumb>False</MtouchUseThumb>
<MtouchUseSGen>False</MtouchUseSGen>
<OptimizePNGs>True</OptimizePNGs>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<WarningLevel>4</WarningLevel>
<MtouchNoSymbolStrip>true</MtouchNoSymbolStrip>
<MtouchLink>None</MtouchLink>
<MtouchArch>ARMv7, ARMv7s, ARM64</MtouchArch>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<Platform Condition=" '$(Platform)' == '' ">iPhone</Platform>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\iPhone\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodesignKey>iPhone Developer</CodesignKey>
<ConsolePause>false</ConsolePause>
<BuildIpa>false</BuildIpa>
<MtouchExtraArgs>--registrar=static</MtouchExtraArgs>
<MtouchI18n>
</MtouchI18n>
<MtouchArch>ARMv7</MtouchArch>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<MtouchArch>ARMv7, ARMv7s, ARM64</MtouchArch>
<MtouchLink>None</MtouchLink>
<MtouchUseLlvm>true</MtouchUseLlvm>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
<Reference Include="System.Json" />
<Reference Include="Xamarin.iOS" />
<Reference Include="ICSharpCode.SharpZipLib.Portable">
<HintPath>..\..\..\src\packages\SharpZipLib.Portable.0.86.0.0003\lib\portable-net45+netcore45+wp8+win8+wpa81+MonoTouch+MonoAndroid+Xamarin.iOS10\ICSharpCode.SharpZipLib.Portable.dll</HintPath>
Expand Down
55 changes: 23 additions & 32 deletions src/Couchbase.Lite.Shared/Database.cs
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,8 @@ public void ChangeEncryptionKey(SymmetricKey newKey)
internal static void RegisterStorageEngine(string identifier, Type type)
{
if(type.GetInterface("Couchbase.Lite.Store.ICouchStore") == null) {
Log.To.Database.E(TAG, "Storage engine type {0} is not ICouchStore, throwing Exception...",
type.FullName);
throw new ArgumentException("Storage engine type is not ICouchStore");
}

Expand All @@ -819,7 +821,7 @@ internal static void RegisterStorageEngine(string identifier, Type type)
internal static IDatabaseUpgrader CreateUpgrader(Database upgradeFrom, string upgradeTo)
{
// Right now only SQLite has upgrade logic
var sqliteType = GetSQLiteStorageClass();
var sqliteType = GetStorageClass(StorageEngineTypes.SQLite);
var sqliteStorage = (ICouchStore)Activator.CreateInstance(sqliteType);
return sqliteStorage.CreateUpgrader(upgradeFrom, upgradeTo);
}
Expand Down Expand Up @@ -1973,27 +1975,25 @@ internal void OpenWithOptions(DatabaseOptions options)

// Instantiate storage:
string storageType = options.StorageType ?? Manager.StorageType ?? StorageEngineTypes.SQLite;
var primaryStorage = default(Type);
if (storageType == "SQLite") {
primaryStorage = GetSQLiteStorageClass();
} else if (storageType == "ForestDB") {
primaryStorage = GetForestDBStorageClass();
} else {
throw Misc.CreateExceptionAndLog(Log.To.Database, StatusCode.InvalidStorageType, "Unknown store type {0}", storageType);
}
var primaryStorage = GetStorageClass(storageType);

if (primaryStorage == null) {
throw Misc.CreateExceptionAndLog(Log.To.Database, StatusCode.InvalidStorageType, TAG,
"Implementation for {0} storage engine not found. Be sure " +
"that the appropriate Nuget package is installed or if building from source that the appropriate " +
"project is referenced"
, storageType);
if (storageType == StorageEngineTypes.SQLite) {
throw Misc.CreateExceptionAndLog(Log.To.Database, StatusCode.InvalidStorageType, TAG,
"No implementation found for SQLite storage. For more information, see " +
"https://github.com/couchbase/couchbase-lite-net/wiki/Error-Dictionary#cblcs0001");
} else {
throw Misc.CreateExceptionAndLog(Log.To.Database, StatusCode.InvalidStorageType, TAG,
"No implementation found for ForestDB storage. For more information, see " +
"https://github.com/couchbase/couchbase-lite-net/wiki/Error-Dictionary#cblcs0002");
}
}


var upgrade = false;
var primarySQLite = storageType == StorageEngineTypes.SQLite;
var otherStorage = primarySQLite ? GetForestDBStorageClass() : GetSQLiteStorageClass();
var otherStorage = primarySQLite ? GetStorageClass(StorageEngineTypes.ForestDB) :
GetStorageClass(StorageEngineTypes.SQLite);


var primaryStorageInstance = (ICouchStore)Activator.CreateInstance(primaryStorage);
Expand All @@ -2006,7 +2006,8 @@ internal void OpenWithOptions(DatabaseOptions options)

if (upgrade && primarySQLite) {
throw Misc.CreateExceptionAndLog(Log.To.Upgrade, StatusCode.InvalidStorageType, TAG,
"Upgrades from ForestDB to SQLite are not supported");
"Upgrades from ForestDB to SQLite are not supported. For more information see " +
"https://github.com/couchbase/couchbase-lite-net/wiki/Error-Dictionary#cbldb0001");
}
} else {
// If options don't specify, use primary unless secondary db already exists in dir:
Expand All @@ -2033,8 +2034,6 @@ internal void OpenWithOptions(DatabaseOptions options)
Storage.Close();
Log.To.Database.E(TAG, "Failed to open storage for database, rethrowing...");
throw;
} catch(DllNotFoundException) {
throw Misc.CreateExceptionAndLog(Log.To.Database, TAG, "Native components not found, make sure to install the proper Nuget packages");
} catch(Exception e) {
Storage.Close();
throw Misc.CreateExceptionAndLog(Log.To.Database, e, TAG, "Got exception while opening storage for database");
Expand Down Expand Up @@ -2096,26 +2095,18 @@ internal void Open()

#region Private Methods

private static Type GetSQLiteStorageClass()
private static Type GetStorageClass(string identifier)
{
var retVal = _StorageEngineMap.Get(StorageEngineTypes.SQLite);
if(retVal != null) {
Log.To.Database.I(TAG, "Using {0} for SQLite implementation", retVal.FullName);
return retVal;
if (identifier != StorageEngineTypes.SQLite && identifier != StorageEngineTypes.ForestDB) {
throw Misc.CreateExceptionAndLog(Log.To.Database, StatusCode.InvalidStorageType, "Unknown store type {0}",
identifier);
}

Log.To.Database.E(TAG, "No SQLite implementation registered, returning null!");
return null;
}

private static Type GetForestDBStorageClass()
{
var retVal = _StorageEngineMap.Get(StorageEngineTypes.ForestDB);
var retVal = _StorageEngineMap.Get(identifier);
if(retVal != null) {
Log.To.Database.I(TAG, "Using {0} for {1} implementation", retVal.FullName, identifier);
return retVal;
}

Log.To.Database.I(TAG, "No ForestDB implementation registered.");
return null;
}

Expand Down

0 comments on commit b223cec

Please sign in to comment.