// Return 0 for lock got, 1 for lock not got, -1 for error. void lock_get(struct lock *lock) { #if defined(HAVE_WIN32) || !defined(HAVE_LOCKF) // Would somebody please tell me how to get a lock on Windows?! lock->status=GET_LOCK_GOT; return; #else char *cp=NULL; char *copy=NULL; // Try to make sure the lock directory exists. if(!(copy=strdup_w(lock->path, __func__))) { lock->status=GET_LOCK_ERROR; return; } if((cp=strrchr(copy, '/'))) { *cp='\0'; if(*copy) mkdir(copy, 0777); } free_w(©); lock_get_quick(lock); // Try to make sure the pid gets onto the disk. if(lock->status==GET_LOCK_GOT) fsync(lock->fd); return; #endif }
static void assert_can_get_lock(struct lock *lock) { fail_unless(!lock_test(lockfile)); lock_get_quick(lock); fail_unless(lock->status==GET_LOCK_GOT); fail_unless(!lock_release(lock)); fail_unless(lock->status==GET_LOCK_NOT_GOT); }
static int get_data_lock(struct lock *lock, struct dpth *dpth, const char *path) { int ret=-1; char *p=NULL; char *lockfile=NULL; // Use just the first three components, excluding sig number. if(!(p=prepend_slash(dpth->base_path, path, 14)) || !(lockfile=prepend(p, ".lock", strlen(".lock"), ""))) goto end; if(lock_init(lock, lockfile) || build_path_w(lock->path)) goto end; lock_get_quick(lock); ret=0; end: if(p) free(p); if(lockfile) free(lockfile); return ret; }
END_TEST static void do_test_cstat_reload_from_client_confs(enum protocol protocol) { struct cstat *c1; struct cstat *c2; struct cstat *clist=NULL; c1=setup_cstat("cli1", protocol); c2=setup_cstat("cli2", protocol); cstat_add_to_list(&clist, c1); cstat_add_to_list(&clist, c2); c1->permitted=1; // First time, nothing is reloaded. fail_unless(reload_from_clientdir(&clist)==0); fail_unless(c1->run_status==RUN_STATUS_IDLE); fail_unless(c2->run_status==RUN_STATUS_UNSET); fail_unless(c1->bu==NULL); fail_unless(c2->bu==NULL); // Add some storage dirs, and c1 is loaded. build_storage_dirs((struct sdirs *)c1->sdirs, sd123, ARR_LEN(sd123)); fail_unless(reload_from_clientdir(&clist)==1); fail_unless(c1->run_status==RUN_STATUS_IDLE); fail_unless(c2->run_status==RUN_STATUS_UNSET); fail_unless(c1->bu!=NULL); fail_unless(c2->bu==NULL); // Go again, nothing should be reloaded. fail_unless(reload_from_clientdir(&clist)==0); // Get a lock. lock_get_quick(((struct sdirs *)c1->sdirs)->lock); fail_unless(reload_from_clientdir(&clist)==1); sdirs_free((struct sdirs **)&c1->sdirs); sdirs_free((struct sdirs **)&c2->sdirs); cstat_list_free(&clist); clean(); alloc_check(); }
static void run_with_fork(int child_exit_early) { int stat; struct lock *lock=setup(); do_fork(child_exit_early); if(!child_exit_early) { sleep(1); fail_unless(lock_test(lockfile)==-1); lock_get_quick(lock); fail_unless(lock->status==GET_LOCK_NOT_GOT); wait(&stat); } // The child has exited, should now be able to get it. assert_can_get_lock(lock); tear_down(&lock, NULL); }
static void do_fork(int child_exit_early) { switch(fork()) { case -1: fail_unless(0==1); break; case 0: // Child. { struct lock *lock; lock=lock_alloc_and_init(lockfile); lock_get_quick(lock); if(!child_exit_early) { sleep(2); lock_release(lock); lock_free(&lock); } exit(0); } default: break; } // Parent. }
static void test_cstat_set_run_status_running(enum protocol protocol) { int waitstat; struct cstat *cstat; struct sdirs *sdirs; struct lock *lock; cstat=set_run_status_setup(protocol, 1 /*permitted*/); clean(); build_storage_dirs((struct sdirs *)cstat->sdirs, sd1w, ARR_LEN(sd1w)); sdirs=(struct sdirs *)cstat->sdirs; lock=sdirs->lock; switch(fork()) { case -1: fail_unless(0==1); break; case 0: // Child. { lock_get_quick(lock); sleep(2); lock_release(lock); exit(0); } default: break; } // Parent. sleep(1); lock_get(lock); fail_unless(lock->status==GET_LOCK_NOT_GOT); cstat_set_run_status(cstat); fail_unless(cstat->run_status==RUN_STATUS_RUNNING); wait(&waitstat); tear_down(&cstat); }