示例#1
0
        private void UpgradeDatabase(FileInfo path)
        {
            var oldFilename = path.FullName;
            var newFilename = Path.ChangeExtension(oldFilename, DatabaseSuffix);
            var newFile     = new FileInfo(newFilename);

            if (!oldFilename.Equals(newFilename) && newFile.Exists)
            {
                var msg = String.Format("Cannot rename {0} to {1}, {2} already exists", oldFilename, newFilename, newFilename);
                Log.W(Database.TAG, msg);
                return;
            }

            var name = Path.GetFileNameWithoutExtension(Path.Combine(path.Directory.FullName, newFilename));
            var db   = GetDatabaseWithoutOpening(name, false);

            if (db == null)
            {
                Log.W(TAG, "Upgrade failed for {0} (Creating new DB failed)", path.Name);
                return;
            }
            db.Dispose();

            var upgrader = DatabaseUpgraderFactory.CreateUpgrader(db, oldFilename);
            var status   = upgrader.Import();

            if (status.IsError)
            {
                Log.W(TAG, "Upgrade failed for {0} (Status {1})", path.Name, status);
                upgrader.Backout();
                return;
            }

            Log.D(TAG, "...Success!");
        }
        public void TestUpgradeOldDatabaseFiles()
        {
            var testDirName = "test-directory-" + Runtime.CurrentTimeMillis();
            var rootDirPath = RootDirectory.FullName;
            var testDirPath = Path.Combine(rootDirPath, testDirName);
            var testDirInfo = Directory.CreateDirectory(testDirPath);

            var dbStream   = GetAsset("withattachments.cblite");
            var destStream = File.OpenWrite(Path.Combine(testDirPath, "withattachments" + Manager.DatabaseSuffix));

            dbStream.CopyTo(destStream);
            dbStream.Dispose();
            destStream.Dispose();

            var attStream = GetAsset("attachment.blob");

            Directory.CreateDirectory(Path.Combine(testDirPath, "withattachments/attachments"));
            destStream = File.OpenWrite(Path.Combine(testDirPath, "withattachments/attachments/356a192b7913b04c54574d18c28d46e6395428ab.blob"));
            attStream.CopyTo(destStream);
            destStream.Dispose();
            attStream.Dispose();

            StopCBLite();
            manager = new Manager(testDirInfo, Manager.DefaultOptions);
            var db      = manager.GetDatabaseWithoutOpening("withattachments", true);
            int version = DatabaseUpgraderFactory.SchemaVersion(db.Path);

            Assert.IsTrue(version >= 101, "Upgrade failed");
            Assert.IsFalse(Directory.Exists(Path.Combine(testDirPath, "withattachments/attachments")), "Failed to remove old attachments dir");
            Assert.IsTrue(Directory.Exists(Path.Combine(testDirPath, "withattachments attachments")), "Failed to create new attachments dir");
        }
        private bool UpgradeDatabase(FileInfo path)
        {
            #if !NOSQLITE
            var previousStorageType = StorageType;
            try {
                StorageType = "SQLite";
                var oldFilename = path.FullName;
                var newFilename = Path.ChangeExtension(oldFilename, DatabaseSuffix);
                var newFile     = new DirectoryInfo(newFilename);

                if (!oldFilename.Equals(newFilename) && newFile.Exists)
                {
                    var msg = String.Format("Cannot move {0} to {1}, {2} already exists", oldFilename, newFilename, newFilename);
                    Log.W(Database.TAG, msg);
                    return(false);
                }

                var name = Path.GetFileNameWithoutExtension(Path.Combine(path.DirectoryName, newFilename));
                var db   = GetDatabaseWithoutOpening(name, false);
                if (db == null)
                {
                    Log.W(TAG, "Upgrade failed for {0} (Creating new DB failed)", path.Name);
                    return(false);
                }
                db.Dispose();

                var upgrader = DatabaseUpgraderFactory.CreateUpgrader(db, oldFilename);
                try {
                    upgrader.Import();
                } catch (CouchbaseLiteException e) {
                    Log.W(TAG, "Upgrade failed for {0} (Status {1})", path.Name, e.CBLStatus);
                    upgrader.Backout();
                    return(false);
                }

                Log.D(TAG, "...Success!");
                return(true);
            } finally {
                StorageType = previousStorageType;
            }
            #endif
        }
示例#4
0
            public void Import()
            {
                // Rename the old database file for migration:
                var destPath = Path.ChangeExtension(_path, Manager.DatabaseSuffixv1 + "-mgr");

                if (!MoveSqliteFiles(_path, destPath))
                {
                    MoveSqliteFiles(destPath, _path);
                    throw Misc.CreateExceptionAndLog(Log.To.Upgrade, StatusCode.InternalServerError, TAG,
                                                     "Upgrade failed: Cannot rename the old sqlite files");
                }

                int version = DatabaseUpgraderFactory.SchemaVersion(destPath);

                if (version < 0)
                {
                    throw Misc.CreateExceptionAndLog(Log.To.Upgrade, StatusCode.CorruptError, TAG,
                                                     "Cannot determine database schema version");
                }

                // Open source (SQLite) database:
                var err = raw.sqlite3_open_v2(destPath, out _sqlite, raw.SQLITE_OPEN_READWRITE, null);

                if (err > 0)
                {
                    throw Misc.CreateExceptionAndLog(Log.To.Upgrade, SqliteErrToStatus(err).Code, TAG,
                                                     "SQLite error while opening source database ({0})", err);
                }

                raw.sqlite3_create_collation(_sqlite, "JSON", raw.SQLITE_UTF8, CollateRevIDs);
                sqlite3_stmt stmt = null;

                PrepareSQL(ref stmt, "SELECT name FROM sqlite_master WHERE type='table' AND name='maps'");

                err = raw.sqlite3_step(stmt);
                if (err == raw.SQLITE_ROW)
                {
                    sqlite3_stmt stmt2 = null;
                    PrepareSQL(ref stmt2, "SELECT * FROM maps");
                    while ((err = raw.sqlite3_step(stmt2)) == raw.SQLITE_ROW)
                    {
                        int          viewId = raw.sqlite3_column_int(stmt2, 0);
                        sqlite3_stmt stmt3  = null;
                        PrepareSQL(ref stmt3, "CREATE TABLE IF NOT EXISTS maps_" + viewId +
                                   " (sequence INTEGER NOT NULL REFERENCES revs(sequence) ON DELETE CASCADE," +
                                   "key TEXT NOT NULL COLLATE JSON," +
                                   "value TEXT," +
                                   "fulltext_id INTEGER, " +
                                   "bbox_id INTEGER, " +
                                   "geokey BLOB)");
                        raw.sqlite3_step(stmt3);
                        raw.sqlite3_finalize(stmt3);
                        stmt3 = null;

                        var sequence = raw.sqlite3_column_int64(stmt2, 1);
                        var key      = raw.sqlite3_column_text(stmt2, 2);
                        var value    = raw.sqlite3_column_text(stmt2, 3);

                        var insertSql = String.Format("INSERT INTO maps_{0} (sequence, key, value) VALUES (?, ?, ?)",
                                                      viewId);

                        PrepareSQL(ref stmt3, insertSql);
                        raw.sqlite3_bind_int64(stmt3, 0, sequence);
                        raw.sqlite3_bind_text(stmt3, 1, key);
                        raw.sqlite3_bind_text(stmt3, 2, value);
                        raw.sqlite3_step(stmt3);
                        raw.sqlite3_finalize(stmt3);
                    }

                    raw.sqlite3_finalize(stmt2);
                    stmt2 = null;
                    PrepareSQL(ref stmt2, "DROP TABLE maps");
                    raw.sqlite3_step(stmt2);
                    raw.sqlite3_finalize(stmt2);
                }

                raw.sqlite3_finalize(stmt);
                raw.sqlite3_close(_sqlite);
                if (err != raw.SQLITE_DONE)
                {
                    throw Misc.CreateExceptionAndLog(Log.To.Upgrade, SqliteErrToStatus(err).Code, TAG,
                                                     "SQLite error during upgrade process ({0})", err);
                }

                if (version >= 101)
                {
                    _db.Delete();
                    MoveSqliteFiles(destPath, _path);
                    var secondaryUpgrade = new v11_upgrader(_db, _path);
                    secondaryUpgrade.Import();
                    var newPath = Path.Combine(Path.GetDirectoryName(_path), _db.Name + Manager.DatabaseSuffix);
                    if (newPath != _db.DbDirectory)
                    {
                        Directory.Move(Path.Combine(Path.GetDirectoryName(_path), _db.Name + Manager.DatabaseSuffix), _db.DbDirectory);
                    }
                    return;
                }

                Log.To.Upgrade.I(TAG, "Upgrading database v1.0 ({0}) to v1.1 at {1} ...", version, _path);

                err = raw.sqlite3_open_v2(destPath, out _sqlite, raw.SQLITE_OPEN_READONLY, null);
                if (err > 0)
                {
                    throw Misc.CreateExceptionAndLog(Log.To.Upgrade, SqliteErrToStatus(err).Code, TAG,
                                                     "Error opening destination SQLite file ({0})", err);
                }

                raw.sqlite3_create_collation(_sqlite, "REVID", raw.SQLITE_UTF8, CollateRevIDs);

                // Open destination database:
                try {
                    _db.Open();
                } catch (CouchbaseLiteException) {
                    Log.To.Upgrade.E(TAG, "Upgrade failed: Couldn't open new db, rethrowing...");
                    throw;
                } catch (Exception e) {
                    throw Misc.CreateExceptionAndLog(Log.To.Upgrade, e, TAG,
                                                     "Error during upgrade; couldn't open new db");
                }

                try {
                    MoveAttachmentsDir();
                } catch (CouchbaseLiteException) {
                    Log.To.Upgrade.E(TAG, "Failed to move attachments directory for database at '{0}', rethrowing...", _path);
                    throw;
                } catch (Exception e) {
                    throw Misc.CreateExceptionAndLog(Log.To.Upgrade, e, TAG,
                                                     "Error moving attachments directory for database at '{0}'", _path);
                }

                // Upgrade documents:
                // CREATE TABLE docs (doc_id INTEGER PRIMARY KEY, docid TEXT UNIQUE NOT NULL);
                sqlite3_stmt docQuery = null;

                PrepareSQL(ref docQuery, "SELECT doc_id, docid FROM docs");

                _db.RunInTransaction(() =>
                {
                    int transactionErr;
                    int count = 0;
                    while (raw.SQLITE_ROW == (transactionErr = raw.sqlite3_step(docQuery)))
                    {
                        long docNumericID = raw.sqlite3_column_int64(docQuery, 0);
                        string docID      = raw.sqlite3_column_text(docQuery, 1);
                        try {
                            ImportDoc(docID, docNumericID);
                        } catch (CouchbaseLiteException) {
                            Log.To.Upgrade.E(TAG, "Failed to import document #{0} ({1}), rethrowing", docNumericID,
                                             new SecureLogString(docID, LogMessageSensitivity.PotentiallyInsecure));
                            throw;
                        } catch (Exception e) {
                            throw Misc.CreateExceptionAndLog(Log.To.Upgrade, e, TAG,
                                                             "Error importing documents");
                        }

                        if ((++count % 1000) == 0)
                        {
                            Log.To.Upgrade.I(TAG, "Migrated {0} documents", count);
                        }
                    }

                    return(transactionErr == raw.SQLITE_DONE);
                });

                raw.sqlite3_finalize(docQuery);

                try {
                    ImportLocalDocs();
                } catch (CouchbaseLiteException) {
                    Log.To.Upgrade.E(TAG, "Failed to import local docs for database '{0}', rethrowing...", _path);
                    throw;
                } catch (Exception e) {
                    throw Misc.CreateExceptionAndLog(Log.To.Upgrade, e, TAG,
                                                     "Error importing local docs for database '{0}'", _path);
                }

                try {
                    ImportInfo();
                } catch (CouchbaseLiteException) {
                    Log.To.Upgrade.E(TAG, "Failed to import info for database '{0}', rethrowing...", _path);
                    throw;
                } catch (Exception e) {
                    throw Misc.CreateExceptionAndLog(Log.To.Upgrade, e, TAG,
                                                     "Error importing info for database '{0}'", _path);
                }

                raw.sqlite3_close(_sqlite);
                _sqlite = null;
                File.Delete(destPath);
                File.Delete(destPath + "-wal");
                File.Delete(destPath + "-shm");
            }