1: /* 2: * ilwrite() : write driver 3: * 1. copy Lock request info to lockbuf 4: * 2. follow action in l_act 5: * 3. Error return conditions 6: * -1: lockrequest fails(only on act=1) 7: * -2: attempt to release a lock not set 8: * by calling program 9: * -3: illegal action requested 10: */ 11: 12: # include <stdio.h> 13: # include <sys/param.h> 14: # include <sys/socket.h> 15: # include <netinet/in.h> 16: # include <sys/ioctl.h> 17: # include <errno.h> 18: # include <ildr.h> 19: # include <sys/time.h> 20: # include <netdb.h> 21: # include <sccs.h> 22: 23: # define TRUE 1 24: # define FALSE 0 25: 26: # ifdef DEBUG 27: static int ildebug = TRUE; 28: # endif DEBUG 29: 30: SCCSID(@(#)ildr.c 8.1 12/31/84) 31: 32: int From_server; /* read connection from socket server */ 33: long Read_fmt; /* bit mask for select */ 34: char *Prog_name; /* program name for abnormal errors */ 35: extern int errno; /* error number */ 36: 37: /* 38: ** main 39: ** initilize the socket to the socket server, and then sit and on 40: ** a select waiting for input. 41: */ 42: main(ac,av) 43: int ac; 44: char **av; 45: { 46: long read_fd, /* bit mask of useable descriptors*/ 47: num_des; /* number of readable descriptors */ 48: int abnormal(); /* error function */ 49: register int i; /* index */ 50: 51: 52: /* 53: ** close all the files descriptors, so we can have more INGRES 54: ** processes. We are lmited by file descriptors. 55: */ 56: # ifdef DEBUG 57: setbuf(stdout,NULL); 58: printf("DRIVER: starting up\n"); 59: close(0); /* guarantee that 0 is what is attached to the socket server */ 60: for ( i = 3 ; i < NOFILE ; i++ ) 61: # else 62: for ( i = 0 ; i < NOFILE ; i++ ) 63: # endif DEBUG 64: close(i); 65: 66: /* 67: ** set up all the signals. Catching any signal 68: ** is an error. We do a "warm start" in this condition 69: */ 70: for ( i = 0 ; i < NSIG ; i++ ) 71: signal(i,abnormal); 72: signal(SIGPIPE,SIG_IGN); /* ignore this one, in case a process simply dies in mid stride */ 73: Prog_name = *av; 74: /* 75: ** if ac == 2, then we are restarted from the the lock driver 76: ** itself, and we don't have to reattach ourselves to the magic 77: ** ingres socket. 78: */ 79: if ( ac == 2 ) 80: From_server = 0; 81: else 82: From_server = init_socket(); 83: Read_fmt = (1<<From_server); 84: 85: /* 86: ** infinite loop waiting for something to happen 87: */ 88: for ( ;; ) 89: { 90: read_fd = Read_fmt; 91: 92: /* 93: ** wake up whenever something happens 94: */ 95: while ( (num_des = select(NOFILE,&read_fd,0,0,0)) == 0 ) 96: { 97: # ifdef DEBUG 98: printf("select returns 0 (%o)\n",read_fd); 99: # endif DEBUG 100: read_fd = Read_fmt; 101: } 102: # ifdef DEBUG 103: printf("select returns %d (%o)\n",num_des,read_fd); 104: # endif DEBUG 105: if ( num_des == -1 ) 106: { 107: # ifdef DEBUG 108: perror("DRIVER:num_des = -1"); 109: # endif DEBUG 110: /* 111: ** a bit of defensive programming. 112: ** If there is an EBADF (bad file descriptor) error 113: ** then we assume that a file descriptor has shut down, 114: ** with out tellng us. We go to a function to figure 115: ** out what has died. 116: */ 117: if ( errno == EBADF ) 118: close_up(Read_fmt); 119: sleep(1); 120: continue; 121: } 122: if ( (read_fd & (1<<From_server)) ) 123: { 124: num_des--; 125: new_proc(); 126: read_fd &= ~(1<<From_server); 127: } 128: if ( num_des > 0 ) 129: { 130: for ( i = 0 ; i < NOFILE ; i++ ) 131: if ( (read_fd & (1<<i)) ) 132: ilwrite(i); 133: } 134: } 135: }/* main */ 136: 137: /* 138: ** new_proc 139: ** start up a new connection to an Ingres process 140: */ 141: new_proc() 142: { 143: register int fd; 144: auto int to_ioctl = 1; 145: struct sockaddr_in addr; 146: auto int len; 147: 148: len = sizeof (addr); 149: if ( (fd = accept(From_server,&addr,&len)) != -1 ) 150: { 151: Read_fmt |= (1<<fd); 152: ioctl(fd,FIONBIO,&to_ioctl); 153: } 154: # ifdef DEBUG 155: else 156: { 157: perror("accept"); 158: sleep(1); 159: } 160: printf("DRIVER: new file %d (%o)\n",fd,(1<<fd)); 161: # endif DEBUG 162: }/* new_proc */ 163: 164: 165: 166: ilwrite(read_desc) 167: register int read_desc; 168: { 169: struct Lockreq lockbuf; 170: register int i; 171: register int blockflag; 172: extern int errno; 173: 174: errno = 0; 175: # ifdef DEBUG 176: printf("DRIVER: entering ilwrite, read_desc = %d\n",read_desc); 177: # endif DEBUG 178: if ( read(read_desc,&lockbuf, sizeof ( lockbuf)) != sizeof ( lockbuf ) ) 179: { 180: # ifdef DEBUG 181: printf("Read error, errno = %d\n",errno); 182: # endif DEBUG 183: if ( errno == EWOULDBLOCK ) 184: return; 185: if ( errno == ECONNRESET ) 186: { 187: ilrma(read_desc,TRUE); 188: close(read_desc); 189: Read_fmt &= ~(1<<read_desc); 190: return; 191: } 192: send_info(read_desc,-5); 193: return; 194: } 195: 196: # ifdef DEBUG 197: if (ildebug) 198: printf("ildr: act %d, type %d, mode %d, read_desc %d\n", 199: lockbuf.lr_act, lockbuf.lr_type, lockbuf.lr_mod, read_desc); 200: # endif DEBUG 201: if (( lockbuf.lr_act < A_RLS1) 202: && ((lockbuf.lr_type < T_CS) || (lockbuf.lr_type > T_DB ) 203: || (lockbuf.lr_mod < M_EXCL) || (lockbuf.lr_mod > M_SHARE ))) 204: { 205: # ifdef DEBUG 206: printf("Illegal request\n"); 207: # endif DEBUG 208: send_info(read_desc,-5); 209: return; 210: } 211: /* 212: * follow action from lock request 213: */ 214: switch(lockbuf.lr_act) 215: { 216: case A_RTN: 217: # ifdef DEBUG 218: if ( ildebug ) 219: printf("Driver: A_RTN\n"); 220: # endif DEBUG 221: 222: /* 223: ** attempt to set lock. 224: ** error return if failure. 225: */ 226: for ( i = 0; i <= lockbuf.lr_type; i++) 227: { 228: if (Lockset[i] == 0) 229: { 230: # ifdef DEBUG 231: if (ildebug) 232: printf("ildr: lock %d not available\n", i); 233: # endif DEBUG 234: send_info(read_desc,-1); 235: return; 236: } 237: } 238: if (ilunique(&lockbuf) >= 0) 239: { 240: send_info(read_desc,-1); 241: return; 242: } 243: # ifdef DEBUG 244: if ( ildebug ) 245: printf("Driver: lock assigned\n"); 246: # endif DEBUG 247: ilenter(&lockbuf,read_desc); 248: break; 249: 250: case A_SLP: 251: # ifdef DEBUG 252: if ( ildebug ) 253: printf("Driver: A_SLP\n"); 254: # endif DEBUG 255: if ( set_lock(read_desc,lockbuf) == -1 ) 256: return; 257: # ifdef DEBUG 258: if ( ildebug ) 259: printf("Driver: got lock\n"); 260: # endif DEBUG 261: break; 262: case A_RLS1: 263: /* remove 1 lock */ 264: # ifdef DEBUG 265: if ( ildebug ) 266: printf("Driver: A_RLS1\n"); 267: # endif DEBUG 268: if ((i = ilfind(&lockbuf,read_desc)) >= 0) 269: { 270: ilrm(i,read_desc); 271: } 272: else 273: { 274: send_info(read_desc,-2); 275: return; 276: } 277: # ifdef DEBUG 278: if ( ildebug ) 279: printf("Driver: released\n"); 280: # endif DEBUG 281: break; 282: 283: case A_RLSA: 284: /* remove all locks for this process id*/ 285: # ifdef DEBUG 286: if ( ildebug ) 287: printf("Driver: A_RLSA\n"); 288: # endif DEBUG 289: ilrma(read_desc,FALSE); 290: break; 291: 292: case A_ABT: /* remove all locks */ 293: # ifdef DEBUG 294: if ( ildebug ) 295: printf("Driver: A_ABT\n"); 296: # endif DEBUG 297: ilclose(); 298: break; 299: 300: default : 301: # ifdef DEBUG 302: if ( ildebug ) 303: printf("DRIVER: garbage\n"); 304: # endif DEBUG 305: send_info(read_desc,-3); 306: } 307: send_info(read_desc,0); 308: } 309: /* 310: * ilunique- check for match on key 311: * 312: * return index of Locktab if match found 313: * else return -1 314: */ 315: static 316: ilunique(ll) 317: register struct Lockreq *ll; 318: { 319: register int k; 320: register struct Lockform *p; 321: register struct Lockreq *q; 322: 323: for (k = 0; k < NLOCKS; k++) 324: { 325: p = &Locktab[k]; 326: if ((p->l_mod != M_EMTY) 327: && (ilcomp(p->l_key,ll->lr_key) == 0) 328: && (p->l_type == ll->lr_type) 329: && ( (p->l_mod == M_EXCL) || (ll->lr_mod == M_EXCL)) ) { 330: # ifdef DEBUG 331: if (ildebug) { 332: register int i; 333: 334: printf("ildr: lock "); 335: for (i = 0; i < KEYSIZE; i++) 336: printf("%c", ll->lr_key[i]); 337: printf(" busy\n"); 338: } 339: # endif DEBUG 340: return(k); 341: } 342: } 343: return(-1); 344: } 345: 346: static 347: ilfind(ll,key) 348: register struct Lockreq *ll; 349: int key; 350: { 351: register int k; 352: register struct Lockform *p; 353: register struct Lockreq *q; 354: 355: for (k = 0; k < NLOCKS; k++) 356: { 357: p = &Locktab[k]; 358: if ((p->l_mod != M_EMTY) 359: && (ilcomp(p->l_key,ll->lr_key) == 0) 360: && (p->l_type == ll->lr_type) 361: && (p->l_pid == key)) 362: return(k); 363: } 364: return(-1); 365: }/* ilfind */ 366: 367: /* 368: * remove the lth Lock 369: * if the correct user is requesting the move. 370: */ 371: static 372: ilrm(l,key,remove_all) 373: int l; 374: int key; 375: int remove_all; 376: { 377: register struct Lockform *a; 378: register k; 379: 380: 381: a = &Locktab[l]; 382: if (a->l_pid == key && a->l_mod != M_EMTY) 383: { 384: if ( !remove_all && a->l_type == T_DB ) 385: return; 386: a->l_mod = M_EMTY; 387: a->l_pid = 0; 388: if (a->l_wflag == W_ON) 389: { 390: a->l_wflag = W_OFF; 391: wakeup(&Locktab[l]); 392: } 393: for (k = 0; k <= a->l_type; k++) 394: { 395: Lockset[k]++; 396: if (Lockset[k] == 1) 397: wakeup(&Lockset[k]); 398: } 399: } 400: }/* ilrm */ 401: 402: /* 403: * ilrma releases all locks for a given process id(pd) 404: * -- called from sys1.c$exit() code. 405: */ 406: ilrma(key,remove_all) 407: int key; 408: int remove_all; 409: { 410: register int i; 411: 412: # ifdef DEBUG 413: printf("DRVIER: Removing all, key = %d\n",key); 414: # endif DEBUG 415: for ( i = 0; i < NLOCKS; i++ ) 416: ilrm(i,key,remove_all); 417: } 418: 419: /* 420: * enter Lockbuf in locktable 421: * return position in Locktable 422: * error return of -1 423: */ 424: static 425: ilenter(ll,key) 426: register struct Lockreq *ll; 427: int key; 428: { 429: int k,l; 430: register char *f,*t; 431: register struct Lockform *p; 432: 433: for (k = 0; k < NLOCKS; k++) 434: { 435: p = &Locktab[k]; 436: if (p->l_mod == M_EMTY) 437: { 438: p->l_pid = key; 439: p->l_type = ll->lr_type; 440: Locktab[k].l_mod = p->l_mod = ll->lr_mod; 441: f = ll->lr_key; 442: t = p->l_key; 443: for (l = 0; l < KEYSIZE; l++) 444: *t++ = *f++; 445: for (l = 0; l <= ll->lr_type; l++) 446: Lockset[l]--; 447: # ifdef DEBUG 448: if ( ildebug ) 449: printf("DRIVER: ilenter %d, mod %d, omod = %d\n",k,p->l_mod,Locktab[k].l_mod); 450: # endif DEBUG 451: return(k); 452: } 453: } 454: # ifdef DEBUG 455: if ( ildebug ) 456: printf("DRIVER: ilenter -1\n"); 457: # endif DEBUG 458: return (-1); 459: } 460: 461: /* 462: * ilcomp- string compare 463: * returns 0 if strings match 464: * returns -1 otherwise 465: */ 466: static 467: ilcomp(s1,s2) 468: register char *s1,*s2; 469: { 470: register int k; 471: 472: for (k = 0; k < KEYSIZE; k++) 473: if ( *s1++ != *s2++) 474: # ifdef DEBUG 475: { 476: if ( ildebug ) 477: printf("DRIVER: ilcomp returning -1\n"); 478: return ( -1 ); 479: } 480: # else DEBUG 481: return (-1); 482: # endif DEBUG 483: return (0); 484: } 485: 486: /* 487: * ilclose- releases all locks 488: */ 489: static 490: ilclose() 491: { 492: register int k; 493: register caddr_t c; 494: # ifdef DEBUG 495: printf("DRIVER: entered close\n"); 496: # endif DEBUG 497: 498: for (k = 0; k < NLOCKS; k++) 499: wakeup( &Locktab[k] ); 500: for (k = 0; k < 4; k++) 501: wakeup( &Lockset[k]); 502: for (c = (caddr_t)&Locktab[0].l_pid; c < (caddr_t)&Locktab[NLOCKS];) 503: *c++ = 0; 504: Lockset[0] = NLOCKS; 505: Lockset[1] = PLOCKS; 506: Lockset[2] = RLOCKS; 507: Lockset[3] = DLOCKS; 508: }/* ilclose */ 509: 510: /* 511: ** set_lock 512: ** attempt to set a lock. If we can't, block the process and 513: ** return -1, if we can than set the lock and return 0. 514: */ 515: set_lock(read_desc,lockbuf) 516: register int read_desc; 517: struct Lockreq lockbuf; 518: { 519: register int blockflag; 520: register int i; 521: 522: /* 523: ** attempt to set lock. 524: ** sleep on blocking address if failure. 525: */ 526: 527: do 528: { 529: do 530: { 531: blockflag = TRUE; 532: for ( i = 0; i <= lockbuf.lr_type; i++) 533: if (Lockset[i] == 0) 534: { 535: # ifdef DEBUG 536: if (ildebug) 537: printf("ildr: lock %d not available\n", i); 538: # endif DEBUG 539: wait_on(read_desc,&Lockset[i],lockbuf); 540: return(-1); 541: } 542: } while (!blockflag); 543: 544: if (( i = ilunique(&lockbuf)) >= 0 ) 545: { 546: blockflag = FALSE; 547: Locktab[i].l_wflag = W_ON; 548: wait_on(read_desc,&Locktab[i],lockbuf); 549: return(-1); 550: } 551: } while (!blockflag); 552: ilenter(&lockbuf,read_desc); 553: return ( 0 ); 554: }/* set_lock */ 555: 556: /* 557: ** send_info 558: ** Send the data down the socket. Don't do it if it would cause the driver 559: ** to block. 560: */ 561: send_info(fd,data) 562: register int fd; 563: int data; 564: { 565: auto int wdes = ( 1<<fd ); 566: struct timeval time; 567: 568: errno = 0; 569: time.tv_sec = 10; 570: time.tv_usec = 0; 571: 572: if ( select(NOFILE,0,&wdes,0,&time) != 1 ) 573: { 574: Read_fmt &= ~(1<<fd); 575: ilrma(fd,TRUE); 576: close(fd); 577: } 578: else 579: if ( write(fd,&data,sizeof (int)) != sizeof (int) ) 580: { 581: if ( errno == 0 ) 582: return; 583: Read_fmt &= ~(1<<fd); 584: ilrma(fd,TRUE); 585: close(fd); 586: } 587: }/* send_info */ 588: 589: struct Wait { 590: int wait_fd; /* file descriptor to send lock info to off of */ 591: int wait_lock; /* what lock we are waiting for */ 592: struct Lockreq wait_req; /* the lock request */ 593: struct Wait *next; 594: }; 595: struct Wait *Wait_queue = NULL; 596: 597: /* 598: ** wait_on 599: ** Set up to wait for a free lock. 600: */ 601: wait_on(fd,lock,req) 602: register int fd, lock; 603: struct Lockreq req; 604: { 605: register struct Wait *ptr; 606: char *calloc(); 607: 608: ptr = (struct Wait *)calloc(1,sizeof (struct Wait)); 609: ptr->wait_fd = fd; 610: ptr->wait_lock = lock; 611: ptr->wait_req = req; 612: ptr->next = Wait_queue; 613: Wait_queue = ptr; 614: }/* wait_on */ 615: 616: /* 617: ** wakeup 618: ** See if there is anythng waiting on the newly freed lock. If there is, 619: ** tell it it can have the lock now. 620: */ 621: wakeup(lock) 622: register int lock; 623: { 624: register struct Wait *ptr,*back; 625: 626: for ( back = NULL, ptr = Wait_queue ; ptr != NULL ; back = ptr, ptr = ptr->next ) 627: { 628: if ( ptr->wait_lock == lock ) 629: { 630: if ( set_lock(ptr->wait_fd,ptr->wait_req) == 0 ) 631: { 632: send_info(ptr->wait_fd,0); 633: if ( back != NULL ) 634: back->next = ptr->next; 635: else 636: Wait_queue = Wait_queue->next; 637: cfree(ptr); 638: return; 639: } 640: } 641: } 642: }/* wakeup */ 643: 644: /* 645: ** abnormal 646: ** a signal has come down and hit us. We restart the entire 647: ** program, and hope it goes away 648: */ 649: abnormal(sig) 650: int sig; 651: { 652: extern int errno; 653: 654: # ifdef DEBUG 655: printf("DRIVER: error %d, restarting\n",sig); 656: # endif 657: 658: execl("/etc/lock_driver","lock_driver","restart",0); 659: execl(Prog_name,Prog_name,"restart",0); 660: execlp("lock_driver","lock_driver","restart",0); 661: exit(4); 662: }/* abnormal */ 663: 664: /* 665: ** close_up 666: ** try and find a closed up file descriptor. 667: */ 668: close_up(fmt) 669: long fmt; 670: { 671: long rdesc; 672: register int i; 673: struct timeval time; 674: 675: errno = 0; 676: time.tv_sec = 0; 677: time.tv_usec = 0; 678: 679: for ( i = 0 ; i < NOFILE ; i++ ) 680: { 681: if ( (1<<i) & fmt ) 682: { 683: rdesc = (1<<i); 684: if ( select(NOFILE,&rdesc,0,0,&time) == -1 ) 685: { 686: /* 687: ** the server socket has closed down. 688: ** BOY ARE WE IN TROUBLE 689: */ 690: if ( i == From_server ) 691: { 692: sleep(1); 693: # ifdef DEBUG 694: printf("Restarting socket\n"); 695: # endif DEBUG 696: init_socket(); 697: } 698: if ( errno == EBADF ) 699: { 700: shutdown(i,2); 701: close(i); 702: Read_fmt &= ~(1<<i); 703: ilrma(i,TRUE); 704: } 705: } 706: } 707: } 708: }/* close_up */