#!/bin/sh # # This is a shell archive. To extract its contents, # execute this file with /bin/sh to create the file(s): # # uque.README uque.ec # # This shell archive created: Tue Sep 17 10:16:05 EDT 2002 # echo "Extracting file uque.README" sed -e 's/^X//' <<\SHAR_EOF > uque.README Xugue.README X X Xuque.ec Identifies who's locked on what and what it is that is locked. X X XN.B. --- this is 'as is' only X X-- X--------------------------------------- XMadison Pruet XEnterprise Replication Product Development XIBM Informix Dynamic Server XDallas, Texas SHAR_EOF if [ `wc -c < uque.README` -ne 265 ] then echo "Lengths do not match -- Bad Copy of uque.README" fi echo "Extracting file uque.ec" sed -e 's/^X//' <<\SHAR_EOF > uque.ec X#include X#include X#include X#include X$include sqlca; X X X/* X** X** structures defined X** X*/ Xtypedef struct user_node *U_PNT; Xtypedef struct lock_node *L_PNT; Xtypedef struct wait_node *W_PNT; Xtypedef struct tbl_node *T_PNT; Xtypedef unsigned long ADDRESS; X Xstruct user_node { X U_PNT next; X U_PNT prior; X unsigned short pass_number; X ADDRESS address; /* address this user */ X char flags[14]; X unsigned long pid; /* pid of this user */ X char *user_id; /* userid of user */ X char *xqt; /* execution of current user */ X ADDRESS wait; /* facility user waiting upon */ X short tout; /* timeout value */ X unsigned int locks; /* number of held locks */ X unsigned int nreads; /* number of reads this user */ X unsigned int nwrites; /* number of writes this user */ X short wait_cnt; /* number of users waiting on me */ X L_PNT locks_first; /* head of lock chain */ X }; X Xstruct lock_node { X L_PNT next; X L_PNT prior; X L_PNT o_next; /* link to next with same owner */ X L_PNT o_prior; X unsigned short pass_number; X ADDRESS address; /* address this lock */ X ADDRESS lklist; /* address of next in link */ X U_PNT wtlist; /* nxt user waiting on lock */ X U_PNT owner; /* owner of this resource */ X W_PNT wlst; /* list of users waiting on this lock */ X W_PNT wlst_end; X char type[20]; /* type of lock on this resource */ X char lock_type; /* 'a' - lock 'b' = latch */ X ADDRESS tblsnum; /* tablespace num this lock */ X ADDRESS rowid; /* rowid this lock */ X }; X Xstruct wait_node { X W_PNT next; /* link to next node */ X U_PNT user_waiting; /* user currently waiting on resource */ X }; X Xstruct tbl_node { X T_PNT next; X ADDRESS tblsnum; /* table space number */ X char tbl_name[19]; /* table name */ X }; X X X/*-------------------------------------------------------------------- X** X** Global variables follow X** X**-------------------------------------------------------------------*/ X XL_PNT g_first_lock = NULL; /* head of lock chain */ XL_PNT g_last_lock = NULL; /* tail of lock chain */ XU_PNT g_first_user = NULL; /* head of user chain */ XU_PNT g_last_user = NULL; /* tail of user chain */ XT_PNT g_first_table = NULL; /* head of table names */ XT_PNT g_last_table = NULL; Xunsigned short g_pass_number = 0; /* this pass number */ Xchar *tbstat_u_filename = ""; /* tbstat -u file */ Xchar *tbstat_k_filename = ""; Xchar *tbstat_s_filename = ""; Xchar *INFORMIXDIR="/usr/informix"; X X X/*--------------------------------------------------------------------- X** X** Local procedures declared below X** X*/ X XU_PNT allocate_user(); /* allocate user node */ XL_PNT allocate_lock(); /* allocate lock node */ Xvoid free_allocations(); /* free user, lock, wait nodes */ Xvoid clear_memory(); /* clear memory routine */ Xint load_tbstat_u(); /* process tbstat -u output */ Xint load_tbstat_k(); /* process tbstat -k output */ Xint load_tbstat_s(); /* process tbstat -s output */ XU_PNT find_user_node(); /* return pointer to user node */ XL_PNT find_lock_node(); /* return pointer to lock node */ Xchar* find_table(); /* return pointer to table */ Xvoid build_table_list(); /* build table space list */ Xvoid print_users(); /* print the user table */ Xvoid link_locks(); /* link lock table items */ Xvoid link_users_to_locks(); /* complete locks to users */ Xint find_table_name(); /* get the table name via tbcheck -pt */ X X Xint main(nparms, vparm) Xint nparms; Xchar *vparm[]; X{ int tnum; X char tchar; X char *chpnt; X X chpnt = getenv("INFORMIXDIR"); X if (chpnt != NULL) X { INFORMIXDIR=chpnt; X } X X X for (tnum = 1; tnum < nparms; tnum++) X { if (!(strcmp(vparm[tnum],"-u"))) X { tnum++; X tbstat_u_filename = (char *) malloc(strlen(vparm[tnum]) + 1); X if (tbstat_u_filename == NULL) X { perror("Can not allocate space for file name"); X exit(1); X } X strcpy(tbstat_u_filename,vparm[tnum]); X } X else X if (!(strcmp(vparm[tnum],"-k"))) X { tnum++; X tbstat_k_filename = (char *) malloc(strlen(vparm[tnum]) + 1); X if (tbstat_k_filename == NULL) X { perror("Can not allocate space for lock file name"); X exit(1); X } X strcpy(tbstat_k_filename,vparm[tnum]); X } X else X if (!strcmp(vparm[tnum],"-s")) X { tnum++; X tbstat_s_filename = (char*) malloc(strlen(vparm[tnum]) + 1); X if (tbstat_s_filename == NULL) X { perror("Can not allocate space for latch file name"); X exit(1); X } X strcpy(tbstat_s_filename,vparm[tnum]); X } X } X /*memorymap();*/ X while (!feof(stdin)) X { /* build_table_list(); */ X load_tbstat_u(); X load_tbstat_k(); X /* load_tbstat_s(); */ X link_locks(); X link_users_to_locks(); X print_users(); X tchar = getchar(); X free_allocations(); X } X exit(0); X X} X Xvoid free_allocations() X{ U_PNT user_pnt, next_user_pnt; X L_PNT lock_pnt, next_lock_pnt; X W_PNT wait_pnt, next_wait_pnt; X X for (lock_pnt = g_first_lock; X lock_pnt != NULL; X lock_pnt = next_lock_pnt) X { if (lock_pnt->wlst != NULL) X { for (wait_pnt = lock_pnt->wlst; X wait_pnt != NULL; X wait_pnt = next_wait_pnt) X { next_wait_pnt = wait_pnt->next; X free(wait_pnt); X } X } X next_lock_pnt = lock_pnt->next; X free(lock_pnt); X } X g_first_lock = g_last_lock = NULL; X X for (user_pnt = g_first_user; X user_pnt != NULL; X user_pnt = next_user_pnt) X { next_user_pnt = user_pnt->next; X free(user_pnt); X } X g_first_user = g_last_user = NULL; X X return; X X} X Xvoid clear_memory(chpnt, size) Xchar *chpnt; Xint size; X{ char *epnt; X epnt = chpnt + size; X while (chpnt < epnt) X *chpnt++ = '\0'; X return; X} X XU_PNT allocate_user() X{ U_PNT t_user_pnt; X X if ((t_user_pnt = (U_PNT) malloc(sizeof (struct user_node))) == NULL) X { perror("Can not allocate user node"); X exit(1); X } X clear_memory(t_user_pnt, (int) sizeof(struct user_node)); X t_user_pnt->next = NULL; X t_user_pnt->prior = NULL; X t_user_pnt->user_id = NULL; X t_user_pnt->xqt = NULL; X t_user_pnt->locks_first = NULL; X X if (g_first_user == NULL) X { g_first_user = t_user_pnt; X } X else X { g_last_user->next = t_user_pnt; X t_user_pnt->prior = g_last_user; X } X g_last_user = t_user_pnt; X return(t_user_pnt); X} X XL_PNT allocate_lock() X{ L_PNT t_lock_pnt; X X if ((t_lock_pnt = (L_PNT) malloc(sizeof(struct lock_node))) == NULL) X { perror("Can not allocate lock node"); X exit(1); X } X X clear_memory(t_lock_pnt, (int) sizeof(struct lock_node)); X t_lock_pnt->next = NULL; X t_lock_pnt->prior = NULL; X t_lock_pnt->o_next = NULL; X t_lock_pnt->wtlist = NULL; X t_lock_pnt->owner = NULL; X X if (g_first_lock == NULL) X { g_first_lock = t_lock_pnt; X } X else X { g_last_lock->next = t_lock_pnt; X t_lock_pnt->prior = g_last_lock; X } X g_last_lock = t_lock_pnt; X return(t_lock_pnt); X} X X Xint load_tbstat_u() X{ FILE *tbstat_u_fp; X char input_buffer[400]; X unsigned long t_address; X char t_flags[20]; X char t_pid[20]; X char t_user[20]; X unsigned long t_wait; X char t_tout[20]; X char t_locks[20]; X char t_nreads[20]; X char t_nwrites[20]; X int num_users = 0; X U_PNT this_user; X char chpnt; X char tbuff[80]; X X if (strcmp(tbstat_u_filename,"")) X { if ((tbstat_u_fp = fopen(tbstat_u_filename, "r")) == NULL) X { perror("Can not open tbstat -u file"); X exit(1); X } X } X else X { strcpy(tbuff,INFORMIXDIR); X strcat(tbuff,"/bin/onstat -u"); X tbstat_u_fp = popen(tbuff,"r"); X } X X strcpy(input_buffer,""); X X if (!(feof(tbstat_u_fp))) X { while ((memcmp(input_buffer,"address",sizeof("address")-1)) && X (!(feof(tbstat_u_fp)))) X { fgets(input_buffer,sizeof(input_buffer),tbstat_u_fp); X } X while (!(feof(tbstat_u_fp))) X { char end_field[80]; X if (fgets(input_buffer,sizeof(input_buffer),tbstat_u_fp) == NULL) X { break; X } X if ((int)strlen(input_buffer) < (int)40) X { break; X } X sscanf(input_buffer,"%*s %s",end_field); X if (strstr(input_buffer,"total")) break; X num_users++; X this_user = allocate_user(); X sscanf(input_buffer,"%x %s %s %s", X &t_address, t_flags,t_pid, t_user); X strcpy(this_user->flags,t_flags); X sscanf(input_buffer+43,"%x %s %s %s %s", X &t_wait, t_tout, t_locks, t_nreads, t_nwrites); X this_user->address = t_address; X this_user->pid = atol(t_pid); X if ((this_user->user_id = (char *) malloc(strlen(t_user) + 1)) == X NULL) X { perror("Can not allocate space for user id"); X exit(1); X } X strcpy(this_user->user_id, t_user); X this_user->wait = t_wait; X this_user->tout = atoi(t_tout); X this_user->locks = atoi(t_locks); X this_user->nreads = atoi(t_nreads); X this_user->nwrites = atoi(t_nwrites); X } X } X if (strcmp(tbstat_u_filename,"")) X fclose(tbstat_u_fp); X else X pclose(tbstat_u_fp); X return(num_users); X} X Xint load_tbstat_s() X{ FILE *tbstat_s_fp; X int tnum; X char input_buffer[400]; X ADDRESS t_owner; X ADDRESS t_address; X U_PNT t_upnt; X L_PNT this_lock; X char tbuff[80]; X X if (strcmp(tbstat_s_filename,"")) X { if ((tbstat_s_fp = fopen(tbstat_s_filename,"r")) == NULL) X { perror("Can not open tbstat -s file"); X exit(1); X } X } X else X { strcpy(tbuff,INFORMIXDIR); X strcat(tbuff,"/bin/onstat -s"); X tbstat_s_fp = popen(tbuff,"r"); X } X X if (!(feof(tbstat_s_fp))) X { input_buffer[0] = '\0'; X while((memcmp(input_buffer,"name",sizeof("name")-1)) & X (!(feof(tbstat_s_fp)))) X { fgets(input_buffer,sizeof(input_buffer),tbstat_s_fp); X } X X while (!(feof(tbstat_s_fp))) X { if (fgets(input_buffer,sizeof(input_buffer),tbstat_s_fp) == NULL) X { break; X } X this_lock = allocate_lock(); X this_lock->lock_type = '2'; X sscanf(input_buffer,"%s %x %*s %*s %x", X &(this_lock->type), X &(this_lock->address), X &t_owner); X this_lock->owner = find_user_node(t_owner); X this_lock->tblsnum = this_lock->rowid = 0; X } X } X if (strcmp(tbstat_s_filename,"")) fclose (tbstat_s_fp); X else pclose(tbstat_s_fp); X return 0; X} Xint load_tbstat_k() X{ FILE *tbstat_k_fp; X int tnum; X char input_buffer[400]; X unsigned long t_owner; X unsigned long t_address; X U_PNT t_upnt; X L_PNT this_lock; X char tbuff[80]; X X if (strcmp(tbstat_k_filename,"")) X { if ((tbstat_k_fp = fopen(tbstat_k_filename,"r")) == NULL) X { perror("Can not open tbstat -k file"); X exit(1); X } X } X else X { strcpy(tbuff,INFORMIXDIR); X strcat(tbuff,"/bin/onstat -k"); X tbstat_k_fp = popen(tbuff,"r"); X } X X if (!(feof(tbstat_k_fp))) X { input_buffer[0] = '\0'; X while ((memcmp(input_buffer,"address",sizeof("address")-1)) && X (!(feof(tbstat_k_fp)))) X { fgets(input_buffer,sizeof(input_buffer),tbstat_k_fp); X } X X while (!(feof(tbstat_k_fp))) X { if (fgets(input_buffer,sizeof(input_buffer),tbstat_k_fp) == NULL) X { break; X } X if (strstr(input_buffer,"active") != NULL) X { break; X } X this_lock = allocate_lock(); X this_lock->lock_type = '1'; X sscanf(input_buffer,"%x %x %x %x %s %x %x", X &(this_lock->address), X &(this_lock->wtlist), X &t_owner, X &(this_lock->lklist), X &(this_lock->type), X &(this_lock->tblsnum), X &(this_lock->rowid)); X this_lock->owner = find_user_node(t_owner); X } X } X if (strcmp(tbstat_k_filename,"")) X fclose(tbstat_k_fp); X else X pclose(tbstat_k_fp); X return; X} X X XU_PNT find_user_node(u_address) XADDRESS u_address; X{ U_PNT t_pnt; X X for (t_pnt = g_first_user; t_pnt != NULL; X t_pnt = t_pnt->next) X { if (t_pnt->address == u_address) X return(t_pnt); X } X return((U_PNT) NULL); X} X XL_PNT find_lock_node(l_address) XADDRESS l_address; X{ L_PNT t_pnt; X X for (t_pnt = g_first_lock; t_pnt != NULL; t_pnt = t_pnt->next) X if (t_pnt->address == l_address) return (t_pnt); X X return ((L_PNT) NULL); X} X Xchar *find_table(partnum) XADDRESS partnum; X{ X $char db_tblname[19]; X $long db_partnum; X static int first_time = 1; X X T_PNT t_pnt = g_first_table; X X while (t_pnt) X { if (partnum == t_pnt->tblsnum) X return t_pnt->tbl_name; X t_pnt = t_pnt->next; X } X X if (first_time) X { first_time = 0; X $database sysmaster; X } X X db_partnum = partnum; X X $select tabname into :db_tblname X from systabnames X where partnum = :db_partnum; X X t_pnt = (T_PNT) malloc (sizeof (struct tbl_node)); X if (t_pnt == NULL) X { perror("Can not allocate space for table node"); X exit(1); X } X t_pnt->tblsnum = partnum; X X if (db_tblname[0] <= ' ' ) X sprintf(t_pnt->tbl_name,"0x%x", partnum); X else strcpy(t_pnt->tbl_name,db_tblname); X X t_pnt->next = NULL; X X if (g_first_table == NULL) X g_first_table = t_pnt; X else g_last_table->next = t_pnt; X g_last_table = t_pnt; X return t_pnt->tbl_name; X} X X X Xvoid link_locks() X{ L_PNT lock_pnt; X L_PNT t_lock_pnt; X U_PNT user_pnt; X L_PNT null_pnt; X X null_pnt = (L_PNT) NULL; X X for (lock_pnt = g_first_lock; X lock_pnt != NULL; X lock_pnt = lock_pnt->next) X { if (lock_pnt->lklist != 0) X { t_lock_pnt = find_lock_node(lock_pnt->lklist); X if (t_lock_pnt != null_pnt) X { t_lock_pnt->o_prior = lock_pnt; X lock_pnt->o_next = t_lock_pnt; X } X } X } X X for (lock_pnt = g_first_lock; X lock_pnt != NULL; X lock_pnt = lock_pnt->next) X { if (lock_pnt->o_prior == NULL) X { if (lock_pnt->owner != NULL) X { lock_pnt->owner->locks_first = lock_pnt; X } X } X } X return; X} X Xvoid link_users_to_locks() X{ U_PNT user_pnt; X L_PNT lock_pnt; X W_PNT wait_pnt; X X for (user_pnt = g_first_user; X user_pnt != NULL; X user_pnt = user_pnt->next) X { if (user_pnt->wait != NULL) X { if ((lock_pnt = find_lock_node(user_pnt->wait)) != NULL) X { wait_pnt = (W_PNT) malloc ( sizeof(struct wait_node)); X wait_pnt->next = NULL; X if (wait_pnt == NULL) X { perror("Could not allocate wait node"); X exit(1); X } X if (lock_pnt->wlst == NULL) X { lock_pnt->wlst = wait_pnt; X } X else X { lock_pnt->wlst_end->next = wait_pnt; X } X lock_pnt->wlst_end = wait_pnt; X wait_pnt->user_waiting = user_pnt; X lock_pnt->owner->wait_cnt++; X } X } X } X return; X} X Xint find_table_name(tblsnum, rtn_buffer) XADDRESS tblsnum; Xchar *rtn_buffer; X{ FILE *tfile; X char tbuff[100]; X char parm1[40]; X int rtn_code=0; X X sprintf(tbuff,"%s/bin/oncheck -pt 0x0%x",INFORMIXDIR,tblsnum); X X if ((tfile = popen(tbuff, "r")) != NULL) X { while (!feof(tfile)) X { if (fgets(tbuff,sizeof(tbuff),tfile) == NULL) X { rtn_code = 0; X break; X } X sscanf(tbuff,"%s %*s %*s %s", parm1, rtn_buffer); X if (!strncmp(parm1,"Error",5) || X !strncmp(parm1,"ERROR",5)) X { rtn_code = 0; X break; X } X if (!strcmp(parm1,"TBLSpace")) X { rtn_code = 1; X break; X } X } X } X fclose(tfile); X return (rtn_code); X} X X X X Xvoid print_users() X{ U_PNT this_user; X L_PNT this_lock; X T_PNT this_tbl; X W_PNT t_wt; X int first_line = 1; X int first_wait; X X for (this_user = g_first_user; this_user != NULL; X this_user = this_user->next) X { if ((this_user->locks_first != NULL) && X (this_user->wait_cnt > 0)) X { if (first_line) X { printf("\nProcesses are being locked\n"); X first_line = 0; X } X printf("\nuserid (%s) session(%d) flags(%s) nreads(%d) nwrites(%d)\n", X this_user->user_id, X this_user->pid, X this_user->flags, X this_user->nreads, X this_user->nwrites); X printf("%-40s%-40s\n","resources held by user","waiting processes"); X printf("%-18s %-12s %-12s\n","table","rowid","type"); X for (this_lock = this_user->locks_first; X this_lock != NULL; X this_lock = this_lock->o_next) X { char tbuff[80]; X char tblname[80]; X first_wait = 1; X if (this_lock->lock_type == '2') X { sprintf(tbuff,"%-25s %s", X " ***LATCH LOCK***",this_lock->type); X } X else X { sprintf(tbuff,"%-18s %-12x %s", X find_table(this_lock->tblsnum), X this_lock->rowid, X this_lock->type); X printf("%-40s",tbuff); X } X X if (this_lock->wlst != NULL) X { for (t_wt = this_lock->wlst; X t_wt != NULL; X t_wt = t_wt->next) X { if (!first_wait) printf("%40s",""); X else X first_wait = 0; X printf("waiting:%s session(%d)\n", X t_wt->user_waiting->user_id, X t_wt->user_waiting->pid); X } X } X printf("\n"); X } X } X } X if (first_line) printf("No processes being locked\n"); X X return; X} X SHAR_EOF if [ `wc -c < uque.ec` -ne 15857 ] then echo "Lengths do not match -- Bad Copy of uque.ec" fi echo "Done." exit 0