From df5e58e6e5eb2727a185bf9a98a462c18fa3a83d Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 8 Mar 2018 18:06:26 +0200 Subject: Setup project database infrastructure --- bdep/database.cxx | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 bdep/database.cxx (limited to 'bdep/database.cxx') diff --git a/bdep/database.cxx b/bdep/database.cxx new file mode 100644 index 0000000..c456961 --- /dev/null +++ b/bdep/database.cxx @@ -0,0 +1,88 @@ +// file : bdep/database.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include +#include + +#include + +using namespace std; + +namespace bdep +{ + using namespace odb::sqlite; + using odb::schema_catalog; + + database + open (const dir_path& d, tracer& tr, bool create) + { + tracer trace ("open"); + + path f (d / bdep_dir / "bdep.sqlite3"); + + if (!create && !exists (f)) + fail << d << " does not look like an initialized project directory" << + info << "run 'bdep init' to initialize"; + + try + { + // We don't need the thread pool. + // + unique_ptr cf (new single_connection_factory); + + database db (f.string (), + SQLITE_OPEN_READWRITE | (create ? SQLITE_OPEN_CREATE : 0), + true, // Enable FKs. + "", // Default VFS. + move (cf)); + + db.tracer (trace); + + // Lock the database for as long as the connection is active. First we + // set locking_mode to EXCLUSIVE which instructs SQLite not to release + // any locks until the connection is closed. Then we force SQLite to + // acquire the write lock by starting exclusive transaction. See the + // locking_mode pragma documentation for details. This will also fail if + // the database is inaccessible (e.g., file does not exist, already used + // by another process, etc). + // + try + { + db.connection ()->execute ("PRAGMA locking_mode = EXCLUSIVE"); + transaction t (db.begin_exclusive ()); + + if (create) + { + // Create the new schema. + // + if (db.schema_version () != 0) + fail << f << ": already has database schema"; + + schema_catalog::create_schema (db); + } + else + { + // Migrate the database if necessary. + // + schema_catalog::migrate (db); + } + + t.commit (); + } + catch (odb::timeout&) + { + fail << "project " << d << " is already used by another process"; + } + + db.tracer (tr); // Switch to the caller's tracer. + return db; + } + catch (const database_exception& e) + { + fail << f << ": " << e.message () << endf; + } + } +} -- cgit v1.1