Overview
SHA1 Hash: | 00ac7945a9ead7200d6ad4404ca432c683b9c4c7 |
---|---|
Date: | 2009-08-13 14:27:24 |
User: | drh |
Comment: | Disconnect the global configuration database in ~/.fossil from the respository database in most cases. This allows multiple "sync" or "commit" operations to be running on different repositories at the same time. |
Timelines: | ancestors | descendants | both | trunk |
Other Links: | files | ZIP archive | manifest |
Tags And Properties
- branch=trunk inherited from [a28c83647d]
- sym-trunk inherited from [a28c83647d]
Changes
[hide diffs]Modified src/allrepo.c from [24723f7eda] to [d3d32a9331].
@@ -89,11 +89,11 @@ if( g.argc<3 ){ usage("list|ls|pull|push|rebuild|sync"); } n = strlen(g.argv[2]); - db_open_config(); + db_open_config(1); zCmd = g.argv[2]; if( strncmp(zCmd, "list", n)==0 ){ zCmd = "list"; }else if( strncmp(zCmd, "ls", n)==0 ){ /* alias for "list" above */ zCmd = "list";
Modified src/cgi.c from [1b01c427a4] to [8b6978d8ea].
@@ -678,11 +678,11 @@ if( z ){ z = mprintf("%s",z); add_param_list(z, '&'); } - z = P("REMOTE_ADDR"); + z = (char*)P("REMOTE_ADDR"); if( z ) g.zIpAddr = mprintf("%s", z); len = atoi(PD("CONTENT_LENGTH", "0")); g.zContentType = zType = P("CONTENT_TYPE"); if( len>0 && zType ){
Modified src/clone.c from [89ab820dce] to [f0402d199e].
@@ -41,20 +41,19 @@ char *zPassword; url_proxy_options(); if( g.argc!=4 ){ usage("FILE-OR-URL NEW-REPOSITORY"); } - db_open_config(); + db_open_config(0); if( file_size(g.argv[3])>0 ){ fossil_panic("file already exists: %s", g.argv[3]); } url_parse(g.argv[2]); if( g.urlIsFile ){ file_copy(g.urlName, g.argv[3]); db_close(); db_open_repository(g.argv[3]); - db_open_config(); db_record_repository_filename(g.argv[3]); db_multi_exec( "REPLACE INTO config(name,value)" " VALUES('server-code', lower(hex(randomblob(20))));" "REPLACE INTO config(name,value)"
Modified src/construct.c from [bf4879b005] to [763e35ebbe].
@@ -137,11 +137,11 @@ } /* Create the foundation */ db_create_repository(zRepository); db_open_repository(zRepository); - db_open_config(); + db_open_config(0); db_begin_transaction(); db_initial_setup(0, 1); printf("project-id: %s\n", db_get("project-code", 0));
Modified src/db.c from [503381e0ca] to [b0740e5748].
@@ -620,43 +620,62 @@ sqlite3_exec(db, "COMMIT", 0, 0, 0); sqlite3_close(db); } /* +** Open a database file. Return a pointer to the new database +** connection. An error results in process abort. +*/ +static sqlite3 *openDatabase(const char *zDbName){ + int rc; + const char *zVfs; + sqlite3 *db; + + zVfs = getenv("FOSSIL_VFS"); + rc = sqlite3_open_v2( + zDbName, &db, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, + zVfs + ); + if( rc!=SQLITE_OK ){ + db_err(sqlite3_errmsg(db)); + } + sqlite3_busy_timeout(db, 5000); + return db; +} + + +/* ** zDbName is the name of a database file. If no other database ** file is open, then open this one. If another database file is ** already open, then attach zDbName using the name zLabel. */ void db_open_or_attach(const char *zDbName, const char *zLabel){ #ifdef __MINGW32__ zDbName = mbcsToUtf8(zDbName); #endif if( !g.db ){ - int rc; - const char *zVfs; - - zVfs = getenv("FOSSIL_VFS"); - rc = sqlite3_open_v2( - zDbName, &g.db, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, - zVfs - ); - if( rc!=SQLITE_OK ){ - db_err(sqlite3_errmsg(g.db)); - } - sqlite3_busy_timeout(g.db, 5000); + g.db = openDatabase(zDbName); db_connection_init(); }else{ db_multi_exec("ATTACH DATABASE %Q AS %s", zDbName, zLabel); } } /* ** Open the user database in "~/.fossil". Create the database anew if ** it does not already exist. -*/ -void db_open_config(void){ +** +** If the useAttach flag is 0 (the usual case) then the user database is +** opened on a separate database connection g.dbConfig. This prevents +** the ~/.fossil database from becoming locked on long check-in or sync +** operations which hold an exclusive transaction. In a few cases, though, +** it is convenient for the ~/.fossil to be attached to the main database +** connection so that we can join between the various databases. In that +** case, invoke this routine with useAttach as 1. +*/ +void db_open_config(int useAttach){ char *zDbName; const char *zHome; if( g.configOpen ) return; #ifdef __MINGW32__ zHome = getenv("LOCALAPPDATA"); @@ -684,11 +703,17 @@ zDbName = mprintf("%s/.fossil", zHome); #endif if( file_size(zDbName)<1024*3 ){ db_init_database(zDbName, zConfigSchema, (char*)0); } - db_open_or_attach(zDbName, "configdb"); + g.useAttach = useAttach; + if( useAttach ){ + db_open_or_attach(zDbName, "configdb"); + g.dbConfig = 0; + }else{ + g.dbConfig = openDatabase(zDbName); + } g.configOpen = 1; } /* ** If zDbName is a valid local database file, open it and return @@ -702,11 +727,11 @@ if( access(zDbName, F_OK) ) return 0; lsize = file_size(zDbName); if( lsize%1024!=0 || lsize<4096 ) return 0; db_open_or_attach(zDbName, "localdb"); g.localOpen = 1; - db_open_config(); + db_open_config(0); db_open_repository(0); /* If the "mtime" column is missing from the vfile table, then ** add it now. This code added on 2008-12-06. After all users have ** upgraded, this code can be safely deleted. @@ -987,11 +1012,11 @@ if( g.argc!=3 ){ usage("REPOSITORY-NAME"); } db_create_repository(g.argv[2]); db_open_repository(g.argv[2]); - db_open_config(); + db_open_config(0); db_begin_transaction(); db_initial_setup(zDate, 1); db_end_transaction(0); printf("project-id: %s\n", db_get("project-code", 0)); printf("server-id: %s\n", db_get("server-code", 0)); @@ -1147,50 +1172,83 @@ } return 0; } /* +** Swap the g.db and g.dbConfig connections so that the various db_* routines +** work on the ~/.fossil database instead of on the repository database. +** Be sure to swap them back after doing the operation. +** +** If g.useAttach that means the ~/.fossil database was opened with +** the useAttach flag set to 1. In that case no connection swap is required +** so this routine is a no-op. +*/ +void db_swap_connections(void){ + if( !g.useAttach ){ + sqlite3 *dbTemp = g.db; + g.db = g.dbConfig; + g.dbConfig = dbTemp; + } +} + +/* ** Get and set values from the CONFIG, GLOBAL_CONFIG and VVAR table in the ** repository and local databases. */ char *db_get(const char *zName, char *zDefault){ char *z = 0; if( g.repositoryOpen ){ z = db_text(0, "SELECT value FROM config WHERE name=%Q", zName); } if( z==0 && g.configOpen ){ + db_swap_connections(); z = db_text(0, "SELECT value FROM global_config WHERE name=%Q", zName); + db_swap_connections(); } if( z==0 ){ z = zDefault; } return z; } void db_set(const char *zName, const char *zValue, int globalFlag){ db_begin_transaction(); - db_multi_exec("REPLACE INTO %sconfig(name,value) VALUES(%Q,%Q)", - globalFlag ? "global_" : "", zName, zValue); + if( globalFlag ){ + db_swap_connections(); + db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%Q)", + zName, zValue); + db_swap_connections(); + }else{ + db_multi_exec("REPLACE INTO config(name,value) VALUES(%Q,%Q)", + zName, zValue); + } if( globalFlag && g.repositoryOpen ){ db_multi_exec("DELETE FROM config WHERE name=%Q", zName); } db_end_transaction(0); } void db_unset(const char *zName, int globalFlag){ db_begin_transaction(); - db_multi_exec("DELETE FROM %sconfig WHERE name=%Q", - globalFlag ? "global_" : "", zName); + if( globalFlag ){ + db_swap_connections(); + db_multi_exec("DELETE INTO global_config WHERE name=%Q", zName); + db_swap_connections(); + }else{ + db_multi_exec("DELETE INTO config WHERE name=%Q", zName); + } if( globalFlag && g.repositoryOpen ){ db_multi_exec("DELETE FROM config WHERE name=%Q", zName); } db_end_transaction(0); } int db_is_global(const char *zName){ + int rc = 0; if( g.configOpen ){ - return db_exists("SELECT 1 FROM global_config WHERE name=%Q", zName); - }else{ - return 0; - } + db_swap_connections(); + rc = db_exists("SELECT 1 FROM global_config WHERE name=%Q", zName); + db_swap_connections(); + } + return rc; } int db_get_int(const char *zName, int dflt){ int v = dflt; int rc; if( g.repositoryOpen ){ @@ -1203,22 +1261,29 @@ db_finalize(&q); }else{ rc = SQLITE_DONE; } if( rc==SQLITE_DONE && g.configOpen ){ + db_swap_connections(); v = db_int(dflt, "SELECT value FROM global_config WHERE name=%Q", zName); + db_swap_connections(); } return v; } void db_set_int(const char *zName, int value, int globalFlag){ - db_begin_transaction(); - db_multi_exec("REPLACE INTO %sconfig(name,value) VALUES(%Q,%d)", - globalFlag ? "global_" : "", zName, value); + if( globalFlag ){ + db_swap_connections(); + db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%d)", + zName, value); + db_swap_connections(); + }else{ + db_multi_exec("REPLACE INTO config(name,value) VALUES(%Q,%d)", + zName, value); + } if( globalFlag && g.repositoryOpen ){ db_multi_exec("DELETE FROM config WHERE name=%Q", zName); } - db_end_transaction(0); } int db_get_boolean(const char *zName, int dflt){ char *zVal = db_get(zName, dflt ? "on" : "off"); if( is_truth(zVal) ) return 1; if( is_false(zVal) ) return 0; @@ -1252,15 +1317,17 @@ if( zName==0 ){ if( !g.localOpen ) return; zName = db_lget("repository", 0); } file_canonical_name(zName, &full); + db_swap_connections(); db_multi_exec( "INSERT OR IGNORE INTO global_config(name,value)" "VALUES('repo:%q',1)", blob_str(&full) ); + db_swap_connections(); blob_reset(&full); } /* ** COMMAND: open @@ -1412,15 +1479,15 @@ "web-browser", }; int i; int globalFlag = find_option("global","g",0)!=0; int unsetFlag = g.argv[1][0]=='u'; + db_open_config(1); db_find_and_open_repository(0); if( !g.repositoryOpen ){ globalFlag = 1; } - db_open_config(); if( unsetFlag && g.argc!=3 ){ usage("PROPERTY ?-global?"); } if( g.argc==2 ){ for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){
Modified src/info.c from [cb5129afc5] to [ce7fc1bbb9].
@@ -97,11 +97,11 @@ i64 fsize; if( g.argc!=2 && g.argc!=3 ){ usage("?FILENAME|ARTIFACT-ID?"); } if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){ - db_open_config(); + db_open_config(0); db_record_repository_filename(g.argv[2]); db_open_repository(g.argv[2]); printf("project-code: %s\n", db_get("project-code", "<none>")); printf("project-name: %s\n", db_get("project-name", "<unnamed>")); printf("server-code: %s\n", db_get("server-code", "<none>"));
Modified src/main.c from [9b1a2a10f7] to [0dbd180aa0].
@@ -52,10 +52,12 @@ */ struct Global { int argc; char **argv; /* Command-line arguments to the program */ int isConst; /* True if the output is unchanging */ sqlite3 *db; /* The connection to the databases */ + sqlite3 *dbConfig; /* Separate connection for global_config table */ + int useAttach; /* True if global_config is attached to repository */ int configOpen; /* True if the config database is open */ long long int now; /* Seconds since 1970 */ int repositoryOpen; /* True if the main repository database is open */ char *zRepositoryName; /* Name of the repository database */ int localOpen; /* True if the local database is open */