run migrations and schema update through new Realm apis

This commit is contained in:
Ari Lazier 2015-06-22 10:32:31 -07:00
parent 60700ba121
commit 2a0a5d234f
4 changed files with 54 additions and 15 deletions

View File

@ -351,7 +351,7 @@ bool ObjectStore::is_schema_at_version(Group *group, uint64_t version) {
if (old_version > version && old_version != NotVersioned) { if (old_version > version && old_version != NotVersioned) {
throw ObjectStoreException(old_version, version); throw ObjectStoreException(old_version, version);
} }
return old_version != version; return old_version == version;
} }
@ -362,7 +362,7 @@ bool ObjectStore::update_realm_with_schema(Group *group,
// Recheck the schema version after beginning the write transaction as // Recheck the schema version after beginning the write transaction as
// another process may have done the migration after we opened the read // another process may have done the migration after we opened the read
// transaction // transaction
bool migrating = is_schema_at_version(group, version); bool migrating = !is_schema_at_version(group, version);
// create tables // create tables
bool changed = create_metadata_tables(group); bool changed = create_metadata_tables(group);

View File

@ -59,10 +59,9 @@ ObjectStoreException::ObjectStoreException(uint64_t old_version, uint64_t new_ve
} }
ObjectStoreException::ObjectStoreException(vector<ObjectStoreException> validation_errors, const string &object_type) : ObjectStoreException::ObjectStoreException(vector<ObjectStoreException> validation_errors, const string &object_type) :
m_validation_errors(validation_errors), m_validation_errors(validation_errors), m_kind(Kind::ObjectStoreValidationFailure) {
m_kind(Kind::ObjectStoreValidationFailure), m_info[InfoKeyObjectType] = object_type;
m_info({{InfoKeyObjectType, object_type}}), m_what = generate_what();
m_what(generate_what()) {
} }
string ObjectStoreException::generate_what() const { string ObjectStoreException::generate_what() const {
@ -88,7 +87,7 @@ std::string ObjectStoreException::populate_format_string(const std::string & for
while(regex_search(current, sm, re)) { while(regex_search(current, sm, re)) {
out_string += sm.prefix(); out_string += sm.prefix();
const string &key = sm[1]; const string &key = sm[1];
if (key == "ValidationString") { if (key == "ValidationErrors") {
out_string += validation_errors_string(); out_string += validation_errors_string();
} }
else { else {

View File

@ -84,13 +84,14 @@ SharedRealm Realm::get_shared_realm(Config &config)
return realm; return realm;
} }
realm = make_shared<Realm>(config); realm = SharedRealm(new Realm(config));
// we want to ensure we are only initializing a single realm at a time // we want to ensure we are only initializing a single realm at a time
lock_guard<mutex> lock(s_init_mutex); lock_guard<mutex> lock(s_init_mutex);
if (!config.schema) { if (!config.schema) {
// get schema from group and skip validation // get schema from group and skip validation
realm->m_config.schema_version = ObjectStore::get_schema_version(realm->read_group());
realm->m_config.schema = make_unique<ObjectStore::Schema>(ObjectStore::schema_from_group(realm->read_group())); realm->m_config.schema = make_unique<ObjectStore::Schema>(ObjectStore::schema_from_group(realm->read_group()));
} }
else if (config.read_only) { else if (config.read_only) {
@ -107,21 +108,45 @@ SharedRealm Realm::get_shared_realm(Config &config)
realm->m_config.schema = make_unique<ObjectStore::Schema>(*existing->m_config.schema); realm->m_config.schema = make_unique<ObjectStore::Schema>(*existing->m_config.schema);
} }
else { else {
// its a new realm so update/migrate if needed // its a non-cached realm so update/migrate if needed
ObjectStore::update_realm_with_schema(realm->read_group(), config.schema_version, *realm->m_config.schema, realm->m_config.migration_function); realm->update_schema(*realm->m_config.schema, config.schema_version);
} }
s_global_cache.cache_realm(realm, realm->m_thread_id); s_global_cache.cache_realm(realm, realm->m_thread_id);
return realm; return realm;
} }
static void check_read_write(Realm *realm) { bool Realm::update_schema(ObjectStore::Schema &schema, uint64_t version)
{
bool changed = false;
try {
begin_transaction();
changed = ObjectStore::update_realm_with_schema(read_group(), version, schema, m_config.migration_function);
commit_transaction();
m_config.schema_version = version;
if (m_config.schema.get() != &schema) {
m_config.schema = make_unique<ObjectStore::Schema>(schema);
}
}
catch (...) {
if (is_in_transaction()) {
cancel_transaction();
}
throw;
}
return changed;
}
static void check_read_write(Realm *realm)
{
if (realm->config().read_only) { if (realm->config().read_only) {
throw RealmException(RealmException::Kind::InvalidTransaction, "Can't perform transactions on read-only Realms."); throw RealmException(RealmException::Kind::InvalidTransaction, "Can't perform transactions on read-only Realms.");
} }
} }
void Realm::verify_thread() { void Realm::verify_thread()
{
if (m_thread_id != this_thread::get_id()) { if (m_thread_id != this_thread::get_id()) {
throw RealmException(RealmException::Kind::IncorrectThread, "Realm accessed from incorrect thread."); throw RealmException(RealmException::Kind::IncorrectThread, "Realm accessed from incorrect thread.");
} }

View File

@ -52,11 +52,20 @@ namespace realm {
Config(const Config& c); Config(const Config& c);
}; };
Realm(Config &config); // Get a cached Realm or create a new one if no cached copies exists
Realm(const Realm& r) = delete; // Caching is done by path - mismatches for inMemory and readOnly Config properties
// will raise an exception
// If schema/schema_version is specified, update_schema is called automatically on the realm
// and a migration is performed. If not specified, the schema version and schema are dynamically
// read from the the existing Realm.
static SharedRealm get_shared_realm(Config &config); static SharedRealm get_shared_realm(Config &config);
// Updates a Realm to a given target schema/version creating tables and updating indexes as necessary
// Uses the existing migration function on the Config, and the resulting Schema and version with updated
// column mappings are set on the realms config upon success.
// returns if any changes were made
bool update_schema(ObjectStore::Schema &schema, uint64_t version);
const Config &config() const { return m_config; } const Config &config() const { return m_config; }
void begin_transaction(); void begin_transaction();
@ -83,6 +92,9 @@ namespace realm {
const std::string DidChangeNotification = "DidChangeNotification"; const std::string DidChangeNotification = "DidChangeNotification";
private: private:
Realm(Config &config);
//Realm(const Realm& r) = delete;
Config m_config; Config m_config;
std::thread::id m_thread_id; std::thread::id m_thread_id;
bool m_in_transaction; bool m_in_transaction;
@ -131,6 +143,9 @@ namespace realm {
IncompatibleLockFile, IncompatibleLockFile,
InvalidTransaction, InvalidTransaction,
IncorrectThread, IncorrectThread,
/** Thrown when trying to open an unitialized Realm without a target schema or with a mismatching
schema version **/
InvalidSchemaVersion
}; };
RealmException(Kind kind, std::string message) : m_kind(kind), m_what(message) {} RealmException(Kind kind, std::string message) : m_kind(kind), m_what(message) {}