# HG changeset patch # User David Scott # Date 1257263470 0 # Node ID 0baec4029c0a9f2b15c40dc912ce3f4b82a09740 # Parent 62ed86ba9fb24b1963c38f4b4a14c2119d66bb15 [database]: Simplify the database population code, in preparation for an upgrade simplification. We now unconditionally force-flush all database backends on populate, rather than only flushing ones which had a lower generation count. -- there should now only be one database backend anyway -- we nolonger worry about write limiting -- the cost of writing once per xapi start is low but the cost of screwing up and not writing when we should is high Move the call to populate() so that it's always done before the database upgrade. -- the database upgrade code now assumes the cache is loaded and ready for modification Signed-off-by: David Scott diff -r 62ed86ba9fb2 -r 0baec4029c0a ocaml/database/db_cache.ml --- a/ocaml/database/db_cache.ml Tue Nov 03 12:56:58 2009 +0000 +++ b/ocaml/database/db_cache.ml Tue Nov 03 15:51:10 2009 +0000 @@ -459,17 +459,8 @@ Db_backend.blow_away_non_persistent_fields() let sync_all_db_connections() = - (* if any of the connections have an on-disk generation count <> the gen count of the db we populated from - then we need to force_flush them to "pull them to tip" *) - List.iter - (fun (gen,db)-> - let current_gen = Generation.read_generation() in - if gen<>current_gen then - begin - debug "Database '%s' out of sync; syncing up now." db.Parse_db_conf.path; - Db_connections.force_flush_all db - end) - (Db_connections.get_dbs_and_gen_counts()) + (* Unconditionally force-flush all databases. *) + List.iter Db_connections.force_flush_all (List.map snd (Db_connections.get_dbs_and_gen_counts())) (* Executed on the master to post-process database after populating cache from db stored on disk *) let post_populate_hook () = @@ -477,6 +468,8 @@ * there's no need to keep it and it's preferable for it not to hang * around. *) Unixext.unlink_safe Xapi_globs.ha_metadata_db; + (* non-persistent fields will have been flushed to disk anyway [since non-persistent just means dont trigger a flush + if I change]. Hence we blank non-persistent fields with a suitable empty value, depending on their type *) Db_backend.blow_away_non_persistent_fields(); (* Flush the in-memory cache to the redo-log *) Backend_xml.flush_db_to_redo_log Db_backend.cache @@ -506,17 +499,6 @@ (* we know that the backup is XML format so, to get the manifest, we jump right in and use the xml backend directly here.. *) let manifest = Backend_xml.populate_and_read_manifest Parse_db_conf.backup_file_dbconn in Db_backend.post_restore_hook manifest; - (* non-persistent fields will have been flushed to disk anyway [since non-persistent just means dont trigger a flush - if I change]. Hence we blank non-persistent fields with a suitable empty value, depending on their type *); - post_populate_hook(); - debug "removed non-persistent fields after backup"; - (* since we just restored from backup then flush new cache to all db connections *) - List.iter - (fun (_,db)-> - debug "Database '%s' syncing up after restore from backup." db.Parse_db_conf.path; - Db_connections.force_flush_all db - ) - (Db_connections.get_dbs_and_gen_counts()); (* delete file that contained backup *) Db_backend.try_and_delete_db_file Xapi_globs.db_temporary_restore_path; end @@ -524,14 +506,15 @@ begin (* Check schema vsn is current; if not try and upgrade; if can't do that then fail startup.. *) let most_recent_db = Db_connections.pick_most_recent_db connections in + (* populate gets all field names from the existing (old) db file, not the (current) schema... which is nice: *) + Backend_xml.populate most_recent_db; + debug "Path that I'm looking at to consider whether to upgrade = %s" most_recent_db.Parse_db_conf.path; if Sys.file_exists most_recent_db.Parse_db_conf.path then Db_upgrade.maybe_upgrade most_recent_db; - (* populate from most recent database *) - Backend_xml.populate most_recent_db; - post_populate_hook () - end + end; + post_populate_hook () let spawn_db_flush_threads() = (* Spawn threads that flush cache to db connections at regular intervals *) diff -r 62ed86ba9fb2 -r 0baec4029c0a ocaml/database/db_connections.ml --- a/ocaml/database/db_connections.ml Tue Nov 03 12:56:58 2009 +0000 +++ b/ocaml/database/db_connections.ml Tue Nov 03 15:51:10 2009 +0000 @@ -124,6 +124,7 @@ end let force_flush_all dbconn = + debug "About to flush database: %s" dbconn.Parse_db_conf.path; Db_conn_store.with_db_conn_lock dbconn (fun () -> begin diff -r 62ed86ba9fb2 -r 0baec4029c0a ocaml/database/db_upgrade.ml --- a/ocaml/database/db_upgrade.ml Tue Nov 03 12:56:58 2009 +0000 +++ b/ocaml/database/db_upgrade.ml Tue Nov 03 15:51:10 2009 +0000 @@ -213,6 +213,7 @@ upgrade_bios_strings () (* GEORGE OEM -> BODIE/MNR *) let upgrade_from_last_release dbconn = + (* NB the database cache has been populated already *) debug "Database schema version is that of last release: attempting upgrade"; (* !!! UPDATE THIS WHEN MOVING TO NEW RELEASE !!! *) @@ -231,9 +232,6 @@ let table_names_new_in_this_release = List.filter (fun tblname -> not (List.mem tblname table_names_in_last_release)) table_names_in_this_release in - - (* populate gets all field names from the existing (old) db file, not the (current) schema... which is nice: *) - Backend_xml.populate dbconn; (* we also have to ensure that the in-memory cache contains the new tables added in this release that will not have been created by the proceeding populate (cos this is restricted to table names in last release). Unless the new tables are