From 7e31ca15bcaeb8d5ff4316b6d92d5ee5a68421f4 Mon Sep 17 00:00:00 2001 From: Nick Alexander Date: Thu, 26 Jul 2018 13:01:53 -0700 Subject: [PATCH] [sdks] Make `store_open{_encrypted}` return useful errors. Because this was formerly a constructor, the pattern needed to change to a factory function, but that's better than what we had. --- ffi/src/lib.rs | 10 ++- .../mozilla/mentat/FFIIntegrationTest.java | 64 +++++++++---------- .../src/main/java/org/mozilla/mentat/JNA.java | 2 +- .../main/java/org/mozilla/mentat/Mentat.java | 43 +++++++------ .../org/mozilla/samples/basic/MainActivity.kt | 5 +- sdks/swift/Mentat/Mentat/Mentat.swift | 4 +- sdks/swift/Mentat/Mentat/store.h | 2 +- 7 files changed, 68 insertions(+), 62 deletions(-) diff --git a/ffi/src/lib.rs b/ffi/src/lib.rs index 98c45d8d..5d2c532e 100644 --- a/ffi/src/lib.rs +++ b/ffi/src/lib.rs @@ -208,21 +208,19 @@ impl<'a, 'c> InProgressTransactResult<'a, 'c> { /// A destructor `store_destroy` is provided for releasing the memory for this /// pointer type. #[no_mangle] -pub extern "C" fn store_open(uri: *const c_char) -> *mut Store { +pub unsafe extern "C" fn store_open(uri: *const c_char, error: *mut ExternError) -> *mut Store { assert_not_null!(uri); let uri = c_char_to_string(uri); - let store = Store::open(&uri).expect("expected a store"); - Box::into_raw(Box::new(store)) + translate_result(Store::open(&uri), error) } /// Variant of store_open that opens an encrypted database. #[cfg(feature = "sqlcipher")] #[no_mangle] -pub extern "C" fn store_open_encrypted(uri: *const c_char, key: *const c_char) -> *mut Store { +pub unsafe extern "C" fn store_open_encrypted(uri: *const c_char, key: *const c_char, error: *mut ExternError) -> *mut Store { let uri = c_char_to_string(uri); let key = c_char_to_string(key); - let store = Store::open_with_key(&uri, &key).expect("expected a store"); - Box::into_raw(Box::new(store)) + translate_result(Store::open_with_key(&uri, &key), error) } // TODO: open empty diff --git a/sdks/android/Mentat/library/src/androidTest/java/org/mozilla/mentat/FFIIntegrationTest.java b/sdks/android/Mentat/library/src/androidTest/java/org/mozilla/mentat/FFIIntegrationTest.java index ac199eb6..0b5be28d 100644 --- a/sdks/android/Mentat/library/src/androidTest/java/org/mozilla/mentat/FFIIntegrationTest.java +++ b/sdks/android/Mentat/library/src/androidTest/java/org/mozilla/mentat/FFIIntegrationTest.java @@ -71,7 +71,7 @@ public class FFIIntegrationTest { @Test public void openInMemoryStoreSucceeds() throws Exception { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); assertNotNull(mentat); } @@ -79,7 +79,7 @@ public class FFIIntegrationTest { public void openStoreInLocationSucceeds() throws Exception { Context context = InstrumentationRegistry.getTargetContext(); String path = context.getDatabasePath("test.db").getAbsolutePath(); - Mentat mentat = new Mentat(path); + Mentat mentat = Mentat.open(path); assertNotNull(mentat); } @@ -114,7 +114,7 @@ public class FFIIntegrationTest { public Mentat openAndInitializeCitiesStore() { if (this.mentat == null) { - this.mentat = new Mentat(); + this.mentat = Mentat.open(); this.transactCitiesSchema(mentat); this.transactSeattleData(mentat); } @@ -177,7 +177,7 @@ public class FFIIntegrationTest { @Test public void transactingVocabularySucceeds() { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport schemaReport = this.transactCitiesSchema(mentat); assertNotNull(schemaReport); assertTrue(schemaReport.getTxId() > 0); @@ -185,7 +185,7 @@ public class FFIIntegrationTest { @Test public void transactingEntitiesSucceeds() { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); this.transactCitiesSchema(mentat); TxReport dataReport = this.transactSeattleData(mentat); assertNotNull(dataReport); @@ -363,7 +363,7 @@ public class FFIIntegrationTest { @Test public void bindingLongValueSucceeds() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport report = this.populateWithTypesSchema(mentat).dataReport; final Long aEntid = report.getEntidForTempId("a"); String query = "[:find ?e . :in ?long :where [?e :foo/long ?long]]"; @@ -384,7 +384,7 @@ public class FFIIntegrationTest { @Test public void bindingRefValueSucceeds() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport report = this.populateWithTypesSchema(mentat).dataReport; long stringEntid = mentat.entIdForAttribute(":foo/string"); final Long bEntid = report.getEntidForTempId("b"); @@ -406,7 +406,7 @@ public class FFIIntegrationTest { @Test public void bindingRefKwValueSucceeds() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport report = this.populateWithTypesSchema(mentat).dataReport; String refKeyword = ":foo/string"; final Long bEntid = report.getEntidForTempId("b"); @@ -428,7 +428,7 @@ public class FFIIntegrationTest { @Test public void bindingKwValueSucceeds() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport report = this.populateWithTypesSchema(mentat).dataReport; final Long aEntid = report.getEntidForTempId("a"); String query = "[:find ?e . :in ?kw :where [?e :foo/keyword ?kw]]"; @@ -449,7 +449,7 @@ public class FFIIntegrationTest { @Test public void bindingDateValueSucceeds() throws InterruptedException, ParseException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport report = this.populateWithTypesSchema(mentat).dataReport; final Long aEntid = report.getEntidForTempId("a"); @@ -493,7 +493,7 @@ public class FFIIntegrationTest { @Test public void bindingUuidValueSucceeds() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport report = this.populateWithTypesSchema(mentat).dataReport; final Long aEntid = report.getEntidForTempId("a"); String query = "[:find ?e . :in ?uuid :where [?e :foo/uuid ?uuid]]"; @@ -515,7 +515,7 @@ public class FFIIntegrationTest { @Test public void bindingBooleanValueSucceeds() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport report = this.populateWithTypesSchema(mentat).dataReport; final Long aEntid = report.getEntidForTempId("a"); String query = "[:find ?e . :in ?bool :where [?e :foo/boolean ?bool]]"; @@ -537,7 +537,7 @@ public class FFIIntegrationTest { @Test public void bindingDoubleValueSucceeds() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport report = this.populateWithTypesSchema(mentat).dataReport; final Long aEntid = report.getEntidForTempId("a"); String query = "[:find ?e . :in ?double :where [?e :foo/double ?double]]"; @@ -558,7 +558,7 @@ public class FFIIntegrationTest { @Test public void typedValueConvertsToLong() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport report = this.populateWithTypesSchema(mentat).dataReport; final Long aEntid = report.getEntidForTempId("a"); String query = "[:find ?v . :in ?e :where [?e :foo/long ?v]]"; @@ -580,7 +580,7 @@ public class FFIIntegrationTest { @Test public void typedValueConvertsToRef() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport report = this.populateWithTypesSchema(mentat).dataReport; final Long aEntid = report.getEntidForTempId("a"); String query = "[:find ?e . :where [?e :foo/long 25]]"; @@ -602,7 +602,7 @@ public class FFIIntegrationTest { @Test public void typedValueConvertsToKeyword() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport report = this.populateWithTypesSchema(mentat).dataReport; final Long aEntid = report.getEntidForTempId("a"); String query = "[:find ?v . :in ?e :where [?e :foo/keyword ?v]]"; @@ -624,7 +624,7 @@ public class FFIIntegrationTest { @Test public void typedValueConvertsToBoolean() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport report = this.populateWithTypesSchema(mentat).dataReport; final Long aEntid = report.getEntidForTempId("a"); String query = "[:find ?v . :in ?e :where [?e :foo/boolean ?v]]"; @@ -646,7 +646,7 @@ public class FFIIntegrationTest { @Test public void typedValueConvertsToDouble() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport report = this.populateWithTypesSchema(mentat).dataReport; final Long aEntid = report.getEntidForTempId("a"); String query = "[:find ?v . :in ?e :where [?e :foo/double ?v]]"; @@ -668,7 +668,7 @@ public class FFIIntegrationTest { @Test public void typedValueConvertsToDate() throws InterruptedException, ParseException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport report = this.populateWithTypesSchema(mentat).dataReport; final Long aEntid = report.getEntidForTempId("a"); String query = "[:find ?v . :in ?e :where [?e :foo/instant ?v]]"; @@ -693,7 +693,7 @@ public class FFIIntegrationTest { @Test public void typedValueConvertsToString() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport report = this.populateWithTypesSchema(mentat).dataReport; final Long aEntid = report.getEntidForTempId("a"); String query = "[:find ?v . :in ?e :where [?e :foo/string ?v]]"; @@ -715,7 +715,7 @@ public class FFIIntegrationTest { @Test public void typedValueConvertsToUUID() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport report = this.populateWithTypesSchema(mentat).dataReport; final Long aEntid = report.getEntidForTempId("a"); String query = "[:find ?v . :in ?e :where [?e :foo/uuid ?v]]"; @@ -738,7 +738,7 @@ public class FFIIntegrationTest { @Test public void valueForAttributeOfEntitySucceeds() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport report = this.populateWithTypesSchema(mentat).dataReport; final Long aEntid = report.getEntidForTempId("a"); TypedValue value = mentat.valueForAttributeOfEntity(":foo/long", aEntid); @@ -748,7 +748,7 @@ public class FFIIntegrationTest { @Test public void entidForAttributeSucceeds() { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); this.populateWithTypesSchema(mentat); long entid = mentat.entIdForAttribute(":foo/long"); assertEquals(65540, entid); @@ -756,7 +756,7 @@ public class FFIIntegrationTest { @Test public void testInProgressTransact() { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport report = this.populateWithTypesSchema(mentat).dataReport; assertNotNull(report); @@ -764,7 +764,7 @@ public class FFIIntegrationTest { @Test public void testInProgressRollback() { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); TxReport report = this.populateWithTypesSchema(mentat).dataReport; assertNotNull(report); long aEntid = report.getEntidForTempId("a"); @@ -782,7 +782,7 @@ public class FFIIntegrationTest { @Test public void testInProgressEntityBuilder() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); DBSetupResult reports = this.populateWithTypesSchema(mentat); long bEntid = reports.dataReport.getEntidForTempId("b"); final long longEntid = reports.schemaReport.getEntidForTempId("l"); @@ -862,7 +862,7 @@ public class FFIIntegrationTest { @Test public void testEntityBuilderForEntid() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); DBSetupResult reports = this.populateWithTypesSchema(mentat); long bEntid = reports.dataReport.getEntidForTempId("b"); final long longEntid = reports.schemaReport.getEntidForTempId("l"); @@ -942,7 +942,7 @@ public class FFIIntegrationTest { @Test public void testEntityBuilderForTempid() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); DBSetupResult reports = this.populateWithTypesSchema(mentat); final long longEntid = reports.schemaReport.getEntidForTempId("l"); @@ -998,7 +998,7 @@ public class FFIIntegrationTest { @Test public void testInProgressBuilderTransact() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); DBSetupResult reports = this.populateWithTypesSchema(mentat); long aEntid = reports.dataReport.getEntidForTempId("a"); long bEntid = reports.dataReport.getEntidForTempId("b"); @@ -1063,7 +1063,7 @@ public class FFIIntegrationTest { @Test public void testEntityBuilderTransact() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); DBSetupResult reports = this.populateWithTypesSchema(mentat); long aEntid = reports.dataReport.getEntidForTempId("a"); long bEntid = reports.dataReport.getEntidForTempId("b"); @@ -1129,7 +1129,7 @@ public class FFIIntegrationTest { @Test public void testEntityBuilderRetract() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); DBSetupResult reports = this.populateWithTypesSchema(mentat); long bEntid = reports.dataReport.getEntidForTempId("b"); final long longEntid = reports.schemaReport.getEntidForTempId("l"); @@ -1199,7 +1199,7 @@ public class FFIIntegrationTest { @Test public void testInProgressBuilderRetract() throws InterruptedException { - Mentat mentat = new Mentat(); + Mentat mentat = Mentat.open(); DBSetupResult reports = this.populateWithTypesSchema(mentat); long bEntid = reports.dataReport.getEntidForTempId("b"); final long longEntid = reports.schemaReport.getEntidForTempId("l"); diff --git a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/JNA.java b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/JNA.java index b8ba5d42..44ac12c2 100644 --- a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/JNA.java +++ b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/JNA.java @@ -42,7 +42,7 @@ public interface JNA extends Library { class InProgressBuilder extends PointerType {} class EntityBuilder extends PointerType {} - Store store_open(String dbPath); + Store store_open(String dbPath, RustError.ByReference err); void destroy(Pointer obj); void uuid_destroy(Pointer obj); diff --git a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/Mentat.java b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/Mentat.java index 94f4f285..f51ecc7f 100644 --- a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/Mentat.java +++ b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/Mentat.java @@ -21,32 +21,39 @@ import com.sun.jna.Pointer; * The raw pointer it holds is a pointer to a Store. */ public class Mentat extends RustObject { - static { System.loadLibrary("mentat_ffi"); } - /** - * Open a connection to a Store in a given location.
- * If the store does not already exist, one will be created. - * @param dbPath The URI as a String of the store to open. - */ - public Mentat(String dbPath) { - this(JNA.INSTANCE.store_open(dbPath)); - } - - /** - * Open a connection to an in-memory Store. - */ - public Mentat() { - this(JNA.INSTANCE.store_open("")); - } - /** * Create a new Mentat with the provided pointer to a Mentat Store * @param rawPointer A pointer to a Mentat Store. */ - public Mentat(JNA.Store rawPointer) { super(rawPointer); } + private Mentat(JNA.Store rawPointer) { super(rawPointer); } + + /** + * Open a connection to an in-memory Mentat Store. + */ + public static Mentat open() { + return open(""); + } + + /** + * Open a connection to a Store in a given location. + *
+ * If the store does not already exist, one will be created. + * @param dbPath The URI as a String of the store to open. + */ + public static Mentat open(String dbPath) { + RustError.ByReference err = new RustError.ByReference(); + JNA.Store store = JNA.INSTANCE.store_open(dbPath, err); + if (!err.isSuccess()) { + err.logAndConsumeError("Mentat"); + throw new RuntimeException("Failed to open store: " + dbPath); + } + + return new Mentat(store); + } /** * Add an attribute to the cache. The {@link CacheDirection} determines how that attribute can be diff --git a/sdks/android/Mentat/samples/basic/src/main/java/org/mozilla/samples/basic/MainActivity.kt b/sdks/android/Mentat/samples/basic/src/main/java/org/mozilla/samples/basic/MainActivity.kt index 81c75a42..e7627b4d 100644 --- a/sdks/android/Mentat/samples/basic/src/main/java/org/mozilla/samples/basic/MainActivity.kt +++ b/sdks/android/Mentat/samples/basic/src/main/java/org/mozilla/samples/basic/MainActivity.kt @@ -21,8 +21,9 @@ class MainActivity : AppCompatActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) - Mentat(this.getDatabasePath("test.db").absolutePath).use { + this.getDatabasePath("test.db").absoluteFile.parentFile.mkdirs(); + + Mentat.open(this.getDatabasePath("test.db").absolutePath).use { } } } - diff --git a/sdks/swift/Mentat/Mentat/Mentat.swift b/sdks/swift/Mentat/Mentat/Mentat.swift index 2bd569e6..712bcf4b 100644 --- a/sdks/swift/Mentat/Mentat/Mentat.swift +++ b/sdks/swift/Mentat/Mentat/Mentat.swift @@ -58,8 +58,8 @@ open class Mentat: RustObject { - Parameter storeURI: The URI as a String of the store to open. If no store URI is provided, an in-memory store will be opened. */ - public convenience init(storeURI: String = "") { - self.init(raw: store_open(storeURI)) + public class func open(storeURI: String = "") throws -> Mentat { + return Mentat(raw: try RustError.unwrap({err in store_open(storeURI, err) })) } /** diff --git a/sdks/swift/Mentat/Mentat/store.h b/sdks/swift/Mentat/Mentat/store.h index 4163358b..729875f6 100644 --- a/sdks/swift/Mentat/Mentat/store.h +++ b/sdks/swift/Mentat/Mentat/store.h @@ -102,7 +102,7 @@ typedef NS_ENUM(NSInteger, ValueType) { }; // Store -struct Store*_Nonnull store_open(const char*_Nonnull uri); +struct Store*_Nonnull store_open(const char*_Nonnull uri, struct RustError* _Nonnull error); // Destructors. void destroy(void* _Nullable obj);