diff --git a/WEGA/contrib/ingres/dbs/src/sys/dbserver.c b/WEGA/contrib/ingres/dbs/src/sys/dbserver.c new file mode 100644 index 0000000..885d7e2 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/sys/dbserver.c @@ -0,0 +1,628 @@ +/************************************************************************/ +/* */ +/* DBS LOCK DEVICE SERVER */ +/* ************************** */ +/* Release 6/3.3 20/03/89 */ +/* */ +/************************************************************************/ + +# include +# include +# include "../conf/gen.h" +# include "../h/dbs.h" +# include "../h/access.h" +# include "../h/lock.h" +# include "../h/bs.h" + +# ifndef major +# define major(x) ((short) (((unsigned) (x) >> 8))) +# define minor(x) ((short) ((x) & 0377)) +# endif + +# define OBJS (30 * LOCKS) +# define REQS (40 * LOCKS) +# define KSIZE 12 + +# define OK 0 +# define ERROR 1 +# define OBJ_OVFLO 2 +# define PROC_OVFLO 3 +# define REQ_OVFLO 4 +# define OPEN_ERROR 5 +# define RD_ERROR 6 +# define WR_ERROR 7 +# define FORK_ERROR 8 + +# define CANT_LOCK -1 +# define LOCK_NOT_SET -2 +# define ILL_REQUEST -3 +# define DRIVER_LOCKED -4 + +# define PROC_FREE 0 +# define REQ_FREE ((struct object *) 0) + +# define NO_PROC ((struct process *) 0) +# define NO_REQ ((struct request *) 0) +# define NO_OBJ ((struct object *) 0) + +struct object +{ + long o_db; /* | KEY | inode of data base */ + long o_rel; /* | FOR | relation tid */ + long o_page; /* | LOCK | page address */ + char o_reqs; /* request reference count */ + /* free space if zero */ + char o_locks; /* lock reference count */ + char o_tas; /* TA reference count */ + char o_mode; /* mode of lock */ +}; + +struct process +{ + struct request *p_lock; /* pointer to lock queue */ + struct request *p_req; /* pointer to request queue */ + struct process *p_wait; /* pointer to wait queue */ + short p_pid; /* requesting process id */ + /* free space if zero */ +}; + +struct request +{ + struct request *r_next; /* next request in queue */ + struct object *r_obj; /* pointer to requested object */ + /* free space if zero */ + short r_mode; /* mode of lock */ +}; + +LOCKREQ AALOCKREQ = { 0 } ; +int AAlockdes = -1 ; +struct object *Object = 0 ; +struct process *Process = 0 ; +struct process *Wait = 0 ; +struct object Obj[OBJS + 1] = { 0 } ; +struct request Req[REQS + 1] = { 0 } ; +struct process Proc[LOCKS] = { 0 } ; +char SERVER[] = "DB.SERVER: "; + + +catch_signal(sig) +register int sig; +{ + signal(sig, (int (*)()) 1); + fflush(stdout); + signal(sig, catch_signal); +} + +main(argc, argv) +int argc; +char *argv[]; +{ + register int i; + register LOCKREQ *lb; + register struct process *p; + char stdbuf[BUFSIZ]; + extern int errno; + extern int (*signal())(); + +# ifdef xSTR1 + AAtTrace(&argc, argv, 'X'); +# endif + + if (argc > 1) + pr_startup(); + + errno = 0; + if ((i = fork()) < 0) + { + printf("\n%sFORK ERROR(%d)", SERVER, errno); + term(FORK_ERROR); + } + else if (i) /* PARENT */ + term(OK); + + /*********************/ + /*** ***/ + /*** +---------+ ***/ + /*** | CHILD | ***/ + /*** +---------+ ***/ + /*** ***/ + /*** lock(1) ***/ + /*** ***/ + /*********************/ + +# ifdef SETBUF + setbuf(stdout, stdbuf); +# endif + + /* user signal catch */ + for (i = SIGHUP; i <= SIGTERM; i++) + signal(i, catch_signal); + + for (i = MAXFILES - 1; i; --i) + if (i != 1) + close(i); + + /* open AA_DBS_LOCK */ + errno = 0; + if ((AAlockdes = open(AA_DBS_LOCK, 2)) < 0) + { + printf("\n%sOPEN %s: ERROR(%d)\n", SERVER, AA_DBS_LOCK, errno); + term(OPEN_ERROR); + } + + lb = &AALOCKREQ; + for ( ; ; ) + { +# ifdef xSTR1 + if (AAtTf(10, 0)) + pr_locks(); + AAtTfp(12, 0, "\n%s", SERVER); +# endif + + if ((i = read(AAlockdes, lb, DBS_RSIZE)) != DBS_RSIZE) + { + if (i < 0 && errno == DRIVER_LOCKED) + term(OK); + printf("\n%sREAD ERROR(%d) got %d\n", SERVER, errno, i); + term(RD_ERROR); + } + + if ((i = lb->l_act) == A_INFO) + { + pr_locks(); + continue; + } + + find_process(); + +# ifdef xSTR1 + if (AAtTfp(11, 0, " A%d M%02o ", i, lb->l_mode)) + { + if (i >= A_RLSA) + putchar('\n'); + else + pr_object(&AALOCKREQ); + } +# endif + + if (i == A_RLSA) + { + lb->l_db = lb->l_rel = lb->l_page = 0L; + rm_all_locks(); + } + else if (i == A_RLS1) + response(rm_one_lock()); + else + enter_lock(); + if (!(p = Process)->p_lock && !p->p_req) + p->p_pid = PROC_FREE; + relock(); + } +} + + +find_process() +{ + register struct process *p; + register short pid; + + for (pid = AALOCKREQ.l_pid, p = &Proc[LOCKS - 1]; p >= Proc; --p) + if (p->p_pid == pid) + goto proc_found; + for (p = &Proc[LOCKS - 1]; p >= Proc; --p) + if (!p->p_pid) + { + p->p_lock = p->p_req = NO_REQ; + p->p_wait = NO_PROC; + p->p_pid = pid; +proc_found: + Process = p; +# ifdef xSTR1 + AAtTfp(23, 0, "PID %5u", p->p_pid); +# endif + return; + } + term(PROC_OVFLO); +} + + +rm_all_locks() +{ + register struct request *r; + register struct process *p; + + for (r = (p = Process)->p_lock; r; r = r->r_next) + { + if (!(--(r->r_obj->o_locks))) + r->r_obj->o_mode = 0; + --(r->r_obj->o_reqs); + r->r_obj = REQ_FREE; + } + for (r = p->p_req; r; r = r->r_next) + { + --(r->r_obj->o_reqs); + if (r->r_mode & M_TA) + --(r->r_obj->o_tas); + r->r_obj = REQ_FREE; + } + p->p_pid = PROC_FREE; +} + + +rm_one_lock() +{ + register struct request **rr; + register struct request *r; + register LOCKREQ *lb; + + lb = &AALOCKREQ; + for (rr = &(Process->p_lock); r = *rr; rr = &r->r_next) + if (AAbequal(lb, r->r_obj, KSIZE)) + { + if (!(--(r->r_obj->o_locks))) + r->r_obj->o_mode = 0; + --(r->r_obj->o_reqs); + r->r_obj = REQ_FREE; + *rr = r->r_next; + return (OK); + } + return (ERROR); +} + + +enter_lock() +{ + register struct process *p; + register LOCKREQ *lb; + register struct object *o; + extern struct object *find_object(); + extern struct request *enter_request(); + + if ((lb = &AALOCKREQ)->l_mode & M_TA) + enter_ta(1); + else if (check_lock(find_object(), lb->l_mode)) + { + p = Process; + p->p_lock = enter_request(p->p_lock); + if (!(((o = Object)->o_locks)++)) + o->o_mode = lb->l_mode & M_MODE; + response(OK); + } + else if (lb->l_act == A_RTN) + response(ERROR); + else + { + lb->l_mode |= M_TE; + enter_ta(0); + } +} + + +relock() +{ + register struct process *w; + register struct request *r; + register int i; + register struct process *lw; + register struct request *lr; + +restart: + for (lw = w = Wait; w; ) + { + i = 0; + for (r = w->p_req; r; r = r->r_next) + if (!(i = check_lock(r->r_obj, r->r_mode))) + break; + if (i) + { + lr = w->p_lock; + for (w->p_lock = r = w->p_req; ; r = r->r_next) + { + if (r->r_mode & M_TA) + { + r->r_mode &= ~M_TA; + --(r->r_obj->o_tas); + } + if (!((r->r_obj->o_locks)++)) + r->r_obj->o_mode = r->r_mode & M_MODE; + if (!r->r_next) + { + r->r_next = lr; + break; + } + } + w->p_req = NO_REQ; + AALOCKREQ.l_pid = w->p_pid; + response(OK); + if (w == lw) + { + Wait = w->p_wait; + w->p_wait = NO_PROC; + goto restart; + } + else + { + lw->p_wait = w->p_wait; + w->p_wait = NO_PROC; + w = lw->p_wait; + } + } + else + { + lw = w; + w = w->p_wait; + } + } +} + + +check_lock(o, s) +register struct object *o; +register int s; +{ + return (!o || !o->o_locks || ((o->o_mode & M_SHARE) && (s & M_SHARE))); +} + + +enter_ta(find) +int find; +{ + register struct request **rr; + register struct request *r; + register struct process *w; + long rel_tid; + extern struct object *find_object(); + extern struct request *enter_request(); + + if (find) + find_object(); + rel_tid = AALOCKREQ.l_rel; + rr = &Process->p_req; + while (r = *rr) + { + if (r->r_obj->o_rel > rel_tid) + break; + rr = &r->r_next; + } + *rr = enter_request(r); + if (AALOCKREQ.l_mode & M_TA) + (*rr)->r_obj->o_tas++; + if (AALOCKREQ.l_mode & M_TE) + { + if (!(w = Wait)) + Wait = Process; + else + { + while (w->p_wait) + w = w->p_wait; + w->p_wait = Process; + } + } + else + response(OK); +} + + +struct object *find_object() +{ + register struct object *o; + register LOCKREQ *lb; + + lb = &AALOCKREQ; + for (o = &Obj[OBJS]; o >= Obj; --o) + if (o->o_reqs && AAbequal(lb, o, KSIZE)) + return (Object = o); + return (Object = NO_OBJ); +} + + +enter_object() +{ + register struct object *o; + + if (o = Object) + { + (o->o_reqs)++; + goto entered; + } + for (o = &Obj[OBJS]; o >= Obj; --o) + if (!o->o_reqs) + { + AAbmove(&AALOCKREQ, o, KSIZE); + o->o_reqs = 1; + o->o_locks = o->o_tas = o->o_mode = 0; + Object = o; +entered: + return; + } + term(OBJ_OVFLO); +} + + +struct request *enter_request(next) +register struct request *next; +{ + register struct request *r; + + enter_object(); + for (r = &Req[REQS]; r >= Req; --r) + if (!r->r_obj) + { + r->r_next = next; + r->r_obj = Object; + r->r_mode = AALOCKREQ.l_mode; + return (r); + } + term(REQ_OVFLO); +} + + +response(error) +register int error; +{ + register int i; + register LOCKRES *lr; + LOCKRES res_buf; + extern int errno; + + if (error < 0) + return; + (lr = &res_buf)->s_pid = AALOCKREQ.l_pid; + lr->s_error = error; + +# ifdef xSTR1 + AAtTfp(9, 0, "%s%s %5u\n", SERVER, error? "ERR": "RUN", lr->s_pid); +# endif + + if ((i = write(AAlockdes, lr, DBS_SSIZE)) != DBS_SSIZE) + { + printf("\n%sWRITE ERROR(%d) got %d\n", SERVER, errno, i); + term(WR_ERROR); + } +} + + +term(code) +register int code; +{ + close(AAlockdes); + fflush(stdout); + exit(code); +} + +pr_locks() +{ + register struct object *o; + register LOCKREQ *lb; + + pr_process(); + lb = &AALOCKREQ; + for (o = &Obj[OBJS]; o >= Obj; --o) + if (o->o_reqs && (!lb->l_db || o->o_db == lb->l_db)) + { + printf("L%5u | %2dRQ %2dLK %2dTA ", + o - Obj, o->o_reqs, o->o_locks, o->o_tas); + pr_mode(o->o_mode); + pr_object(o); + } + fflush(stdout); +} + +pr_process() +{ + register struct process *p; + register struct request *r; + register LOCKREQ *lb; + + lb = &AALOCKREQ; + if (p = Wait) + { + printf("%sWAITQUEUE", SERVER); + for ( ; p; p = p->p_wait) + printf("-->%5u", p->p_pid); + putchar('\n'); + } + for (p = &Proc[LOCKS - 1]; p >= Proc; --p) + { + if (p->p_pid) + { + printf("P%5u:", p->p_pid); + for (r = p->p_lock; r; r = r->r_next) + { + if (lb->l_db && r->r_obj->o_db != lb->l_db) + continue; + printf("\tL%4u", r->r_obj - Obj); + } + for (r = p->p_req; r; r = r->r_next) + { + if (lb->l_db && r->r_obj->o_db != lb->l_db) + continue; + printf("\tR%4u", r->r_obj - Obj); + } + putchar('\n'); + } + } + fflush(stdout); +} + +pr_object(o) +register struct object *o; +{ + register struct stat *s; + + s = (struct stat *) &o->o_db; + printf(" |%5d", major(s->st_dev)); + printf(" |%5d", minor(s->st_dev)); + printf(" |%6d | ", s->st_ino); + pr_tid(&o->o_rel); + printf(" |"); + if (o->o_page == REL_LOCK) + printf(" REL"); + else if (o->o_page == USE_LOCK) + printf(" USE"); + else if (o->o_page == CS_LOCK) + printf(" CS"); + else + printf("%6ld", o->o_page); + putchar('\n'); + fflush(stdout); +} + +pr_tid(tid) +register struct tup_id *tid; +{ + register int lineid; + long pageid; + + AApluck_page(tid, &pageid); + if (pageid == 0xffffff) + pageid = -1L; + if ((lineid = ctou(tid->line_id)) == SCANTID) + lineid = -1; + printf("%3ld/%3d", pageid, lineid); +} + +AApluck_page(tid, var) +register struct tup_id *tid; +register struct lpage *var; +{ + var->lpg0 = tid->pg0; + var->lpg1 = tid->pg1; + var->lpg2 = tid->pg2; + var->lpgx = 0; +} + +pr_mode(mode) +register int mode; +{ + if (mode & M_REL) + putchar('R'); + else if (mode & M_TA) + putchar('A'); + else if (mode & M_TE) + putchar('E'); + else + putchar(' '); + + if (mode & M_EXCL) + putchar('E'); + else if (mode & M_SHARE) + putchar('S'); + else + putchar(' '); +} + +pr_startup() +{ + printf("\n%sWAITQUEUE-->pid-->pid...\n", SERVER); + printf("Ppid: {Llock} {Rlock}\n"); + printf("Llock | nRQ nLK nTA mode | major | minor | inode | rel_tid | page\n"); + printf("\npid\tProzessnummer\n"); + printf("mode\tR-relation A-TA E-TE E-exclusive S-shared\n"); + printf("Llock\tbelegter Lock\n"); + printf("Rlock\tangeforderter Lock\n"); + printf("nRQ\tAnzahl der Verweise auf diesen Lock\n"); + printf("nLK\tAnzahl der Prozesse, die diesen Lock belegen\n"); + printf("nTA\tAnzahl der Transaktionen, die diesen Lock anfordern\n\n"); + fflush(stdout); +}