CVS update: /ccvs/src/
[email protected] 30 Apr 2005 03:55:10 -0000
| Newsgroups | gmane.comp.version-control.cvs.cvs |
|---|---|
| Message-ID | <[email protected]> |
User: dprice Date: 05/04/29 20:55:10 Modified: /ccvs/src/ ChangeLog, cvs.h, history.c, lock.c, sanity.sh Log: Merge changes from 1.11.x. File Changes: Directory: /ccvs/src/ ===================== File [changed]: ChangeLog Url: https://ccvs.cvshome.org/source/browse/ccvs/src/ChangeLog?r1=1.3179&r2=1.3180 Delta lines: +21 -1 -------------------- --- ChangeLog 28 Apr 2005 18:06:05 -0000 1.3179 +++ ChangeLog 30 Apr 2005 03:55:07 -0000 1.3180 @@ -1,4 +1,24 @@ -2005-04-27 Derek Price <[email protected]> +2005-04-28 Derek Price <[email protected]> + + * cvs.h (history_lock, clear_history_lock): New protos. + * lock.c (struct lock): Add lockdirname. + (global_history_lock): New global. + (global_read_lock): Initialize. + (lock_name): Handle const args. + (lock_simple_remove): Factor out code in favor of clear_lock call. + (set_lock): Handle variable lockdirname. + (lock_filesdoneproc): Set new lockdirname. + (history_lock, clear_history_lock): New functions. + (clear_lock): Avoid segfault on missing lock. + (Lock_Cleanup): Clean up history locks when necessary. + * history.c (history_write): Use new lock. + * sanity.sh (lockfiles-20): Test new lock. + +2005-04-28 Derek Price <[email protected]> + + * sanity.sh (lockfiles): Port some locking tests over from 1.12.x. + +2005-04-28 Derek Price <[email protected]> * lock.c (clear_lock): Improve comment. File [changed]: cvs.h Url: https://ccvs.cvshome.org/source/browse/ccvs/src/cvs.h?r1=1.331&r2=1.332 Delta lines: +5 -0 ------------------- --- cvs.h 16 Mar 2005 15:52:14 -0000 1.331 +++ cvs.h 30 Apr 2005 03:55:07 -0000 1.332 @@ -193,6 +193,7 @@ #define CVSATTIC "Attic" #define CVSLCK "#cvs.lock" +#define CVSHISTLCK "#cvs.history.lock" #define CVSRFL "#cvs.rfl" #define CVSPFL "#cvs.pfl" #define CVSWFL "#cvs.wfl" @@ -556,6 +557,10 @@ /* See lock.c for description. */ void lock_dir_for_write (const char *); +/* Get a write lock for the history file. */ +int history_lock (const char *); +void clear_history_lock (void); + void Scratch_Entry (List * list, const char *fname); void ParseTag (char **tagp, char **datep, int *nonbranchp); void WriteTag (const char *dir, const char *tag, const char *date, File [changed]: history.c Url: https://ccvs.cvshome.org/source/browse/ccvs/src/history.c?r1=1.89&r2=1.90 Delta lines: +6 -0 ------------------- --- history.c 16 Mar 2005 22:00:49 -0000 1.89 +++ history.c 30 Apr 2005 03:55:07 -0000 1.90 @@ -735,6 +735,11 @@ if (noexec) goto out; + + if (!history_lock (current_parsed_root->directory)) + /* history_lock() will already have printed an error on failure. */ + goto out; + fd = CVS_OPEN (fname, O_WRONLY | O_APPEND | OPEN_BINARY, 0666); if (fd < 0) { @@ -875,6 +880,7 @@ error (1, errno, "cannot close history file: %s", fname); free (workdir); out: + clear_history_lock (); free (fname); } File [changed]: lock.c Url: https://ccvs.cvshome.org/source/browse/ccvs/src/lock.c?r1=1.112&r2=1.113 Delta lines: +83 -33 --------------------- --- lock.c 28 Apr 2005 18:06:05 -0000 1.112 +++ lock.c 30 Apr 2005 03:55:07 -0000 1.113 @@ -88,13 +88,20 @@ char *file2; #endif /* LOCK_COMPATIBILITY */ - /* The lock dir (usually CVSLCK), if we are currently holding it. */ + /* The name of the master lock dir. Usually CVSLCK. */ + const char *lockdirname; + + /* The full path to the lock dir, if we are currently holding it. + * + * This will be LOCKDIRNAME catted onto REPOSITORY. We waste a little + * space by storing it, but save a later malloc/free. + */ char *lockdir; /* Note there is no way of knowing whether the readlock and writelock exist. The code which sets the locks doesn't use SIG_beginCrSect to set a flag like we do for CVSLCK. */ - int free_repository; + bool free_repository; }; static void remove_locks (void); @@ -122,8 +129,11 @@ /* This is the (single) readlock which is set by Reader_Lock. The repository field is NULL if there is no such lock. */ -static struct lock global_readlock; -static struct lock global_writelock; +static struct lock global_readlock = {NULL, NULL, NULL, CVSLCK, NULL, false}; +static struct lock global_writelock = {NULL, NULL, NULL, CVSLCK, NULL, false}; + +static struct lock global_history_lock = {NULL, NULL, NULL, CVSHISTLCK, + NULL, false}; /* List of locks set by lock_tree_for_write. This is redundant with locklist, sort of. */ @@ -279,11 +289,11 @@ * * INPUTS * lock The lock to remove. - * free True if this lock directory will not5 be reused (free + * free True if this lock directory will not be reused (free * lock->repository if necessary). */ static void -remove_lock_files (struct lock *lock, int free_repository) +remove_lock_files (struct lock *lock, bool free_repository) { TRACE (TRACE_FLOW, "remove_lock_files (%s)", lock->repository); @@ -311,15 +321,7 @@ } #endif /* LOCK_COMPATIBILITY */ - if (lock->lockdir) - { - SIG_beginCrSect (); - if (CVS_RMDIR (lock->lockdir) < 0) - error (0, errno, "failed to remove lock dir %s", lock->lockdir); - free (lock->lockdir); - lock->lockdir = NULL; - SIG_endCrSect (); - } + clear_lock (lock); /* And free the repository string. We don't really have to set the * repository string to NULL first since there is no harm in running any of @@ -334,7 +336,7 @@ if (lock->free_repository) { free ((char *)lock->repository); - lock->free_repository = 0; + lock->free_repository = false; } lock->repository = NULL; SIG_endCrSect (); @@ -358,7 +360,7 @@ /* clean up simple read locks (if any) */ if (global_readlock.repository != NULL) - remove_lock_files (&global_readlock, 1); + remove_lock_files (&global_readlock, true); /* See note in Lock_Cleanup() below. */ SIG_endCrSect(); @@ -366,7 +368,15 @@ /* clean up simple write locks (if any) */ if (global_writelock.repository != NULL) - remove_lock_files (&global_writelock, 1); + remove_lock_files (&global_writelock, true); + /* See note in Lock_Cleanup() below. */ + SIG_endCrSect(); + + SIG_beginCrSect(); + + /* clean up simple write locks (if any) */ + if (global_history_lock.repository) + remove_lock_files (&global_history_lock, true); /* See note in Lock_Cleanup() below. */ SIG_endCrSect(); } @@ -423,7 +433,7 @@ static int unlock_proc (Node *p, void *closure) { - remove_lock_files (p->data, 0); + remove_lock_files (p->data, false); return 0; } @@ -500,7 +510,7 @@ /* remember what we're locking (for Lock_Cleanup) */ global_readlock.repository = xstrdup (xrepository); - global_readlock.free_repository = 1; + global_readlock.free_repository = true; /* get the lock dir for our own */ if (set_lock (&global_readlock, 1) != L_OK) @@ -768,7 +778,7 @@ /* Remove the promotable lock. */ lock->file2 = NULL; - remove_lock_files (lock, 0); + remove_lock_files (lock, false); /* return the error */ error (0, xerrno, @@ -994,7 +1004,7 @@ TRACE (TRACE_FLOW, "set_lock (%s, %d)", lock->repository ? lock->repository : "(null)", will_wait); - masterlock = lock_name (lock->repository, CVSLCK); + masterlock = lock_name (lock->repository, lock->lockdirname); /* * Note that it is up to the callers of set_lock() to arrange for signal @@ -1105,19 +1115,20 @@ * freeing the storage. * * ASSUMPTIONS - * We own the master lock directory. - * Its name is stored in LOCK->lockdir. + * If we own the master lock directory, its name is stored in LOCK->lockdir. * We may free LOCK->lockdir. - * */ static void clear_lock (struct lock *lock) { SIG_beginCrSect (); + if (lock->lockdir) + { if (CVS_RMDIR (lock->lockdir) < 0) error (0, errno, "failed to remove lock dir `%s'", lock->lockdir); free (lock->lockdir); lock->lockdir = NULL; + } SIG_endCrSect (); } @@ -1142,8 +1153,9 @@ #ifdef LOCK_COMPATIBILITY ((struct lock *)p->data)->file2 = NULL; #endif /* LOCK_COMPATIBILITY */ + ((struct lock *)p->data)->lockdirname = CVSLCK; ((struct lock *)p->data)->lockdir = NULL; - ((struct lock *)p->data)->free_repository = 0; + ((struct lock *)p->data)->free_repository = false; /* FIXME-KRP: this error condition should not simply be passed by. */ if (p->key == NULL || addnode (lock_tree_list, p) != 0) @@ -1206,10 +1218,10 @@ } if (global_writelock.repository != NULL) - remove_lock_files (&global_writelock, 1); + remove_lock_files (&global_writelock, true); global_writelock.repository = xstrdup (repository); - global_writelock.free_repository = 1; + global_writelock.free_repository = true; for (;;) { @@ -1262,7 +1274,7 @@ Node *p = findnode (locklist, repository); if (p) { - remove_lock_files (p->data, 1); + remove_lock_files (p->data, true); delnode (p); } } @@ -1271,3 +1283,41 @@ } } } + + + +/* Get a write lock for the history file. Return true on success and false on + * error. + */ +int +history_lock (xrepository) + const char *xrepository; +{ + /* remember what we're locking (for Lock_Cleanup) */ + assert (!global_history_lock.repository); + global_history_lock.repository = Xasprintf ("%s/%s", xrepository, + CVSROOTADM); + global_history_lock.free_repository = true; + + /* get the lock dir for our own */ + if (set_lock (&global_history_lock, 1) != L_OK) + { + if (!really_quiet) + error (0, 0, "failed to obtain history lock in repository `%s'", + xrepository); + + return 0; + } + + return 1; +} + + + +/* Remove the history lock, if it exists. + */ +void +clear_history_lock () +{ + remove_lock_files (&global_history_lock, true); +} File [changed]: sanity.sh Url: https://ccvs.cvshome.org/source/browse/ccvs/src/sanity.sh?r1=1.1058&r2=1.1059 Delta lines: +10 -0 -------------------- --- sanity.sh 22 Apr 2005 11:59:00 -0000 1.1058 +++ sanity.sh 30 Apr 2005 03:55:07 -0000 1.1059 @@ -22549,6 +22549,16 @@ $CVSROOT_DIRNAME/first-dir/sdir/ssdir/file1,v <-- first-dir/sdir/ssdir/file1 new revision: 1\.4; previous revision: 1\.3" + # 10. Don't write when history locks are present... + echo have you ever heard a poem quite so vile\? >>first-dir/sdir/ssdir/file1 + mkdir "$TESTDIR/locks/CVSROOT/#cvs.history.lock" + (sleep 5; rmdir "$TESTDIR/locks/CVSROOT/#cvs.history.lock")& + dotest lockfiles-20 "$testcvs -q ci -mnot-up-to-date first-dir" \ +"$CVSROOT_DIRNAME/first-dir/sdir/ssdir/file1,v <-- first-dir/sdir/ssdir/file1 +new revision: 1\.5; previous revision: 1\.4 +$SPROG commit: \[[0-9:]*\] waiting for $username's lock in $CVSROOT_DIRNAME/CVSROOT +$SPROG commit: \[[0-9:]*\] obtained lock in $CVSROOT_DIRNAME/CVSROOT" + cd CVSROOT dotest lockfiles-cleanup-1 "$testcvs -q up -pr1.1 config >config" "" dotest lockfiles-cleanup-2 "$testcvs -q ci -m config-it" \