# # patch "ChangeLog" # from [6d6babd353a051b7b5d6028319c3c98c8d81f7b2] # to [8828e452a0ac7dcf37a61eef52a908415cb90615] # # patch "automate.cc" # from [5416a4b51b9029e98cede29f658fb1120ee7bb65] # to [b303e2282502365cfd91af081afa85b6df03de8b] # # patch "commands.cc" # from [002c7e8b171019ed9c19cb1f15dcfebdec5c1257] # to [e91738f6920ce61beca85f8703a8efbab058a53e] # # patch "database.cc" # from [7fbf000b889c6a9e67179e405279c17c08f8b1ff] # to [d2b9a3f2fb7aae0006bd60e1266f0d9e7f882bfd] # # patch "database.hh" # from [5e52b0b84dd9cdcd155ee9af48481f8476ac2d8b] # to [a25c05b9b4ae523a61d846f7d21817cde40580bb] # ======================================================================== --- ChangeLog 6d6babd353a051b7b5d6028319c3c98c8d81f7b2 +++ ChangeLog 8828e452a0ac7dcf37a61eef52a908415cb90615 @@ -1,3 +1,15 @@ +2005-11-27 Grahame Bowland + + * automate.cc (automate_certs,automate_keys): use non-exclusive + transaction guard + * commands.cc (ls_certs,ls_keys,cat): use non-exclusive + transaction guard + * database.cc (begin_transaction): used BEGIN DEFERRED (only attempt + exclusive lock once a write is attempted on DB) when not exclusive + (transaction_guard::transaction_guard): new argument exclusive indicating + whether an immediate exclusive lock is requested, defaults to true + * database.hh: update prototype for transaction_guard + 2005-11-26 Nathaniel Smith * UPGRADE: Add note about serve changing syntax. @@ -33,7 +45,7 @@ * configure.ac, Makefile.am, po/Makevars: Avoid using xgettext's --flag option on versions that do not support it. -2005-11-26 Grahame Bowland +2005-11-26 Grahame Bowland * automate.cc (automate_stdio) add wrapper function to read() so that loops will not wind backwards possibly overrunning buffers ======================================================================== --- automate.cc 5416a4b51b9029e98cede29f658fb1120ee7bb65 +++ automate.cc b303e2282502365cfd91af081afa85b6df03de8b @@ -834,7 +834,7 @@ std::vector certs; - transaction_guard guard(app.db); + transaction_guard guard(app.db, false); revision_id rid(idx(args, 0)()); N(app.db.revision_exists(rid), F("No such revision %s") % rid); @@ -1331,7 +1331,7 @@ std::vector > > items; if (app.db.database_specified()) { - transaction_guard guard(app.db); + transaction_guard guard(app.db, false); app.db.get_key_ids("", dbkeys); guard.commit(); } ======================================================================== --- commands.cc 002c7e8b171019ed9c19cb1f15dcfebdec5c1257 +++ commands.cc e91738f6920ce61beca85f8703a8efbab058a53e @@ -523,7 +523,7 @@ vector certs; - transaction_guard guard(app.db); + transaction_guard guard(app.db, false); revision_id ident; complete(app, idx(args, 0)(), ident); @@ -626,7 +626,7 @@ if (app.db.database_specified()) { - transaction_guard guard(app.db); + transaction_guard guard(app.db, false); app.db.get_key_ids(pattern, pubs); guard.commit(); } @@ -1363,7 +1363,7 @@ if (app.revision_selectors.size() == 0) app.require_working_copy(); - transaction_guard guard(app.db); + transaction_guard guard(app.db, false); file_id ident; revision_id rid; ======================================================================== --- database.cc 7fbf000b889c6a9e67179e405279c17c08f8b1ff +++ database.cc d2b9a3f2fb7aae0006bd60e1266f0d9e7f882bfd @@ -675,10 +675,20 @@ } void -database::begin_transaction() +database::begin_transaction(bool exclusive) { if (transaction_level == 0) - execute("BEGIN EXCLUSIVE"); + { + if (exclusive) + execute("BEGIN EXCLUSIVE"); + else + execute("BEGIN DEFERRED"); + transaction_exclusive = exclusive; + } + else + { + E(!exclusive || transaction_exclusive, F("Attempt to start exclusive transaction within non-exclusive transaction.")); + } transaction_level++; } @@ -2549,10 +2559,11 @@ // transaction guards -transaction_guard::transaction_guard(database & d) : committed(false), db(d) +transaction_guard::transaction_guard(database & d, bool exclusive) : committed(false), db(d) { - db.begin_transaction(); + db.begin_transaction(exclusive); } + transaction_guard::~transaction_guard() { if (committed) @@ -2567,6 +2578,8 @@ committed = true; } + + // called to avoid foo.db-journal files hanging around if we exit cleanly // without unwinding the stack (happens with SIGINT & SIGTERM) void ======================================================================== --- database.hh 5e52b0b84dd9cdcd155ee9af48481f8476ac2d8b +++ database.hh a25c05b9b4ae523a61d846f7d21817cde40580bb @@ -88,6 +88,7 @@ struct sqlite3 * __sql; struct sqlite3 * sql(bool init = false); int transaction_level; + bool transaction_exclusive; void install_functions(app_state * app); void install_views(); @@ -188,7 +189,7 @@ std::vector & certs, std::string const & table); - void begin_transaction(); + void begin_transaction(bool exclusive); void commit_transaction(); void rollback_transaction(); friend class transaction_guard; @@ -451,12 +452,21 @@ // transaction-protected, and it'll make sure the db aborts a // txn if there's any exception before you call commit() +// by default, locks the database exclusively. +// if the transaction is intended to be read-only, call with exclusive=False +// in this case, if a database update is attempted and another process is accessing +// the database an exception will be thrown - uglier and more confusing for the user - +// however no data inconsistency should result. +// +// an exception is thrown if an exclusive transaction_guard is created while +// a non-exclusive transaction_guard exists. + class transaction_guard { bool committed; database & db; public: - transaction_guard(database & d); + transaction_guard(database & d, bool exclusive=true); ~transaction_guard(); void commit(); };