/* * ilwrite() : write driver * 1. copy Lock request info to lockbuf * 2. follow action in l_act * 3. Error return conditions * -1: lockrequest fails(only on act=1) * -2: attempt to release a lock not set * by calling program * -3: illegal action requested */ # include # include # include # include # include # include # include # include # include # include # define TRUE 1 # define FALSE 0 # ifdef DEBUG static int ildebug = TRUE; # endif DEBUG SCCSID(@(#)ildr.c 8.1 12/31/84) int From_server; /* read connection from socket server */ long Read_fmt; /* bit mask for select */ char *Prog_name; /* program name for abnormal errors */ extern int errno; /* error number */ /* ** main ** initilize the socket to the socket server, and then sit and on ** a select waiting for input. */ main(ac,av) int ac; char **av; { long read_fd, /* bit mask of useable descriptors*/ num_des; /* number of readable descriptors */ int abnormal(); /* error function */ register int i; /* index */ /* ** close all the files descriptors, so we can have more INGRES ** processes. We are lmited by file descriptors. */ # ifdef DEBUG setbuf(stdout,NULL); printf("DRIVER: starting up\n"); close(0); /* guarantee that 0 is what is attached to the socket server */ for ( i = 3 ; i < NOFILE ; i++ ) # else for ( i = 0 ; i < NOFILE ; i++ ) # endif DEBUG close(i); /* ** set up all the signals. Catching any signal ** is an error. We do a "warm start" in this condition */ for ( i = 0 ; i < NSIG ; i++ ) signal(i,abnormal); signal(SIGPIPE,SIG_IGN); /* ignore this one, in case a process simply dies in mid stride */ Prog_name = *av; /* ** if ac == 2, then we are restarted from the the lock driver ** itself, and we don't have to reattach ourselves to the magic ** ingres socket. */ if ( ac == 2 ) From_server = 0; else From_server = init_socket(); Read_fmt = (1< 0 ) { for ( i = 0 ; i < NOFILE ; i++ ) if ( (read_fd & (1< T_DB ) || (lockbuf.lr_mod < M_EXCL) || (lockbuf.lr_mod > M_SHARE ))) { # ifdef DEBUG printf("Illegal request\n"); # endif DEBUG send_info(read_desc,-5); return; } /* * follow action from lock request */ switch(lockbuf.lr_act) { case A_RTN: # ifdef DEBUG if ( ildebug ) printf("Driver: A_RTN\n"); # endif DEBUG /* ** attempt to set lock. ** error return if failure. */ for ( i = 0; i <= lockbuf.lr_type; i++) { if (Lockset[i] == 0) { # ifdef DEBUG if (ildebug) printf("ildr: lock %d not available\n", i); # endif DEBUG send_info(read_desc,-1); return; } } if (ilunique(&lockbuf) >= 0) { send_info(read_desc,-1); return; } # ifdef DEBUG if ( ildebug ) printf("Driver: lock assigned\n"); # endif DEBUG ilenter(&lockbuf,read_desc); break; case A_SLP: # ifdef DEBUG if ( ildebug ) printf("Driver: A_SLP\n"); # endif DEBUG if ( set_lock(read_desc,lockbuf) == -1 ) return; # ifdef DEBUG if ( ildebug ) printf("Driver: got lock\n"); # endif DEBUG break; case A_RLS1: /* remove 1 lock */ # ifdef DEBUG if ( ildebug ) printf("Driver: A_RLS1\n"); # endif DEBUG if ((i = ilfind(&lockbuf,read_desc)) >= 0) { ilrm(i,read_desc); } else { send_info(read_desc,-2); return; } # ifdef DEBUG if ( ildebug ) printf("Driver: released\n"); # endif DEBUG break; case A_RLSA: /* remove all locks for this process id*/ # ifdef DEBUG if ( ildebug ) printf("Driver: A_RLSA\n"); # endif DEBUG ilrma(read_desc,FALSE); break; case A_ABT: /* remove all locks */ # ifdef DEBUG if ( ildebug ) printf("Driver: A_ABT\n"); # endif DEBUG ilclose(); break; default : # ifdef DEBUG if ( ildebug ) printf("DRIVER: garbage\n"); # endif DEBUG send_info(read_desc,-3); } send_info(read_desc,0); } /* * ilunique- check for match on key * * return index of Locktab if match found * else return -1 */ static ilunique(ll) register struct Lockreq *ll; { register int k; register struct Lockform *p; register struct Lockreq *q; for (k = 0; k < NLOCKS; k++) { p = &Locktab[k]; if ((p->l_mod != M_EMTY) && (ilcomp(p->l_key,ll->lr_key) == 0) && (p->l_type == ll->lr_type) && ( (p->l_mod == M_EXCL) || (ll->lr_mod == M_EXCL)) ) { # ifdef DEBUG if (ildebug) { register int i; printf("ildr: lock "); for (i = 0; i < KEYSIZE; i++) printf("%c", ll->lr_key[i]); printf(" busy\n"); } # endif DEBUG return(k); } } return(-1); } static ilfind(ll,key) register struct Lockreq *ll; int key; { register int k; register struct Lockform *p; register struct Lockreq *q; for (k = 0; k < NLOCKS; k++) { p = &Locktab[k]; if ((p->l_mod != M_EMTY) && (ilcomp(p->l_key,ll->lr_key) == 0) && (p->l_type == ll->lr_type) && (p->l_pid == key)) return(k); } return(-1); }/* ilfind */ /* * remove the lth Lock * if the correct user is requesting the move. */ static ilrm(l,key,remove_all) int l; int key; int remove_all; { register struct Lockform *a; register k; a = &Locktab[l]; if (a->l_pid == key && a->l_mod != M_EMTY) { if ( !remove_all && a->l_type == T_DB ) return; a->l_mod = M_EMTY; a->l_pid = 0; if (a->l_wflag == W_ON) { a->l_wflag = W_OFF; wakeup(&Locktab[l]); } for (k = 0; k <= a->l_type; k++) { Lockset[k]++; if (Lockset[k] == 1) wakeup(&Lockset[k]); } } }/* ilrm */ /* * ilrma releases all locks for a given process id(pd) * -- called from sys1.c$exit() code. */ ilrma(key,remove_all) int key; int remove_all; { register int i; # ifdef DEBUG printf("DRVIER: Removing all, key = %d\n",key); # endif DEBUG for ( i = 0; i < NLOCKS; i++ ) ilrm(i,key,remove_all); } /* * enter Lockbuf in locktable * return position in Locktable * error return of -1 */ static ilenter(ll,key) register struct Lockreq *ll; int key; { int k,l; register char *f,*t; register struct Lockform *p; for (k = 0; k < NLOCKS; k++) { p = &Locktab[k]; if (p->l_mod == M_EMTY) { p->l_pid = key; p->l_type = ll->lr_type; Locktab[k].l_mod = p->l_mod = ll->lr_mod; f = ll->lr_key; t = p->l_key; for (l = 0; l < KEYSIZE; l++) *t++ = *f++; for (l = 0; l <= ll->lr_type; l++) Lockset[l]--; # ifdef DEBUG if ( ildebug ) printf("DRIVER: ilenter %d, mod %d, omod = %d\n",k,p->l_mod,Locktab[k].l_mod); # endif DEBUG return(k); } } # ifdef DEBUG if ( ildebug ) printf("DRIVER: ilenter -1\n"); # endif DEBUG return (-1); } /* * ilcomp- string compare * returns 0 if strings match * returns -1 otherwise */ static ilcomp(s1,s2) register char *s1,*s2; { register int k; for (k = 0; k < KEYSIZE; k++) if ( *s1++ != *s2++) # ifdef DEBUG { if ( ildebug ) printf("DRIVER: ilcomp returning -1\n"); return ( -1 ); } # else DEBUG return (-1); # endif DEBUG return (0); } /* * ilclose- releases all locks */ static ilclose() { register int k; register caddr_t c; # ifdef DEBUG printf("DRIVER: entered close\n"); # endif DEBUG for (k = 0; k < NLOCKS; k++) wakeup( &Locktab[k] ); for (k = 0; k < 4; k++) wakeup( &Lockset[k]); for (c = (caddr_t)&Locktab[0].l_pid; c < (caddr_t)&Locktab[NLOCKS];) *c++ = 0; Lockset[0] = NLOCKS; Lockset[1] = PLOCKS; Lockset[2] = RLOCKS; Lockset[3] = DLOCKS; }/* ilclose */ /* ** set_lock ** attempt to set a lock. If we can't, block the process and ** return -1, if we can than set the lock and return 0. */ set_lock(read_desc,lockbuf) register int read_desc; struct Lockreq lockbuf; { register int blockflag; register int i; /* ** attempt to set lock. ** sleep on blocking address if failure. */ do { do { blockflag = TRUE; for ( i = 0; i <= lockbuf.lr_type; i++) if (Lockset[i] == 0) { # ifdef DEBUG if (ildebug) printf("ildr: lock %d not available\n", i); # endif DEBUG wait_on(read_desc,&Lockset[i],lockbuf); return(-1); } } while (!blockflag); if (( i = ilunique(&lockbuf)) >= 0 ) { blockflag = FALSE; Locktab[i].l_wflag = W_ON; wait_on(read_desc,&Locktab[i],lockbuf); return(-1); } } while (!blockflag); ilenter(&lockbuf,read_desc); return ( 0 ); }/* set_lock */ /* ** send_info ** Send the data down the socket. Don't do it if it would cause the driver ** to block. */ send_info(fd,data) register int fd; int data; { auto int wdes = ( 1<wait_fd = fd; ptr->wait_lock = lock; ptr->wait_req = req; ptr->next = Wait_queue; Wait_queue = ptr; }/* wait_on */ /* ** wakeup ** See if there is anythng waiting on the newly freed lock. If there is, ** tell it it can have the lock now. */ wakeup(lock) register int lock; { register struct Wait *ptr,*back; for ( back = NULL, ptr = Wait_queue ; ptr != NULL ; back = ptr, ptr = ptr->next ) { if ( ptr->wait_lock == lock ) { if ( set_lock(ptr->wait_fd,ptr->wait_req) == 0 ) { send_info(ptr->wait_fd,0); if ( back != NULL ) back->next = ptr->next; else Wait_queue = Wait_queue->next; cfree(ptr); return; } } } }/* wakeup */ /* ** abnormal ** a signal has come down and hit us. We restart the entire ** program, and hope it goes away */ abnormal(sig) int sig; { extern int errno; # ifdef DEBUG printf("DRIVER: error %d, restarting\n",sig); # endif execl("/etc/lock_driver","lock_driver","restart",0); execl(Prog_name,Prog_name,"restart",0); execlp("lock_driver","lock_driver","restart",0); exit(4); }/* abnormal */ /* ** close_up ** try and find a closed up file descriptor. */ close_up(fmt) long fmt; { long rdesc; register int i; struct timeval time; errno = 0; time.tv_sec = 0; time.tv_usec = 0; for ( i = 0 ; i < NOFILE ; i++ ) { if ( (1<