2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * COMPONENT_NAME: austext
26 * FUNCTIONS: FL_LIST_ACCESS
70 * This module contains IBM CONFIDENTIAL code. -- (IBM
71 * Confidential Restricted when combined with the aggregated
72 * modules for this product)
74 * OBJECT CODE ONLY SOURCE MATERIALS
75 * (C) COPYRIGHT International Business Machines Corp. 1995, 1996
77 * US Government Users Restricted Rights - Use, duplication or
78 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
80 /*-----------------------------------------------------------------------=
81 $XConsortium: dblfcns.c /main/6 1996/11/25 18:48:05 drk $
82 dblfcns -- Database Access & Locking Functions
84 This file contains functions which open/close a
85 db_VISTA database and manage multiuser access
86 to the db_VISTA database files
88 (C) Copyright 1985, 1986, 1987 by Raima Corp.
89 -----------------------------------------------------------------------*/
91 /* ********************** EDIT HISTORY *******************************
93 SCR DATE INI DESCRIPTION
94 ----- --------- --- -----------------------------------------------------
95 76 16-Jun-88 RSC Make dblfcns consistent when SINGLE_USER defined
96 240 17-Jun-88 RSC Make dblfcns consistent when NO_TRANS defined
97 103 24-Jun-88 RSC Improve generation of single user version
98 237 29-Jun-88 RSC Do not permit recfree/setfree/keyfree inside transaction
99 272 29-Jun-88 RSC make sure log entry is added to taf after lockmgr, and
100 deleted before lockmgr
101 305 01-Jul-88 RSC clear cache_ovfl flag after d_trend and d_trabort
102 ??? 06-Jul_88 WLW include GENERAL lockmgr changes
103 353 14-Jul-88 RSC place dio_clear outside ifndef SINGLE_USER in d_trabort
104 367 14-Jul-88 RSC initialize prev lock to 'f' in bld_lock_tables
105 115 18-Jul-88 RSC Integrate VAX/VMS changes into master source
106 76 27-Jul-88 RSC More work making dblfcns work with SINGLE_USER
107 03-AUG-88 RTK MULTI_TASKing changes
108 310 10-Aug-88 RSC Cleanup of function prototypes
109 11-Aug-88 RTK Incremental database open/multi-tasking changes
110 18-Aug-88 RSC Moved rn_type/dba to separate table
111 423 10-Sep-88 RSC Allocated wrong size for rec_locks
112 423 12-Sep-88 RSC Moved o_free above termfree
113 423 15-Sep-88 RSC Initialized no_of_dbs to 1 in d_close
114 424 21-Sep-88 RSC Integrated International Character Set (ESM)
115 04-Oct-88 WLW Removed taskinit call from d_close, replaced with init's
116 425 05-Oct-88 RSC d_trabort was not completely clearing page zero
117 05-Oct-88 RSC must also init no_of_dbs = 1 in d_close (cf 04-Oct above)
118 420 07-Oct-88 RSC Unoptimized usage of fl_list - was full of bugs.
119 11-Oct-88 RSC Fix for clean compile under Lattice 3.3
120 441 08-Dec-88 RSC Place call to netbios_chk within ifndef GENERAL
121 Placed setting of inode/device within ifndef GENERAL
122 Removed undef UNIX / define MSC inside GENERAL
123 440 13-Dec-88 RSC Removed LR_LOCK lock_reply from db_global to scalar
124 440 22-Dec-88 RSC More modifications for General Lockmgr
125 539 18-Jan-89 RSC General Lockmgr was broke when open mode = one user
126 420 24-Jan-89 WLW Added ifdef's for SINGLE_USER in lock sets
127 571 27-Jan-89 RSC Remove defn of taf_close - General lockmgr lattice port issue
128 420 14-Feb-89 WLW Corrected KEYMARK handling in d_lock and lock_files
129 637 08-Mar-89 RSC Should not alloc file_refs in exclusive access, wasn't
130 Freeing fl_list of key_locks
131 713 08-May-89 WLW Make external recovery work for single-user and one-user
132 656 08-May-89 WLW Eliminate assignment to unallocated memory with gen lm.
135 * Revision 1.2 1995/10/13 18:44:53 miker
136 * Change hardcoded dbfile[] size from 48 to DtSrFILENMLEN.
137 * Remove call to initenv()--disregard environment variables.
140 /* To work with the General Lock Manager, the Unix case of using inode
141 number and device to identify a file is not used.
144 #define IS_UNIX_REALLY
148 int debugging_dopen = 0; /* 1 = TRUE */
154 #ifdef IS_UNIX_REALLY
159 #define KEYMARK 30000
161 #define send_pkt (Send_pkt.ptr)
162 #define recv_pkt (Recv_pkt.ptr)
164 TASK db_global = { 0 };
165 int db_glob_init = 0;
167 /* As a quick fix to the General Lockmgr, the structure lock_reply was
168 removed from db_global. However, this assumes that db_VISTA would
169 never be preempted in the multi-tasking version, and that all function
170 calls would complete before a new task is run. If this assumption is
171 ever "broken" then lock_reply will need to be placed back within db_global
174 static LR_LOCK lock_reply; /* This used to be in db_global */
178 DB_TASK Currtask = {POINTER_ASSIGN((TASK FAR *)&db_global), POINTER_ASSIGN((char FAR *)NULL)};
181 extern CHAR_P Dbpgbuff; /* allocated by dio_init used by o_update */
182 extern LOOKUP_ENTRY_P Db_lookup; /* database page lookup table */
183 extern PAGE_ENTRY_P Dbpg_table; /* database page table */
184 extern LOOKUP_ENTRY_P Ix_lookup; /* index page lookup table */
185 extern PAGE_ENTRY_P Ixpg_table; /* index page table */
186 extern INT_P Used_files;
190 #define lsn (db_global.Lsn)
192 BOOLEAN trcommit = FALSE;
193 int db_txtest = 0; /* transaction commit failure testing flag */
195 #define FL_LIST_ACCESS(ld_ptr) (FILE_NO *)(ld_ptr)->fl_list.ptr
196 #define FL_LIST_DEACCESS(ld_ptr) /**/
201 static char type[5]; /* open type (s or x) */
207 /* transaction activity file info */
208 extern INT taf_count;
209 extern char taf_files[TAFLIMIT][FILENMLEN];
213 /* Internal function prototypes */
215 static void pr_lock_descr(P1(struct lock_descr FAR *) Pi(int)
216 Pi(CONST char FAR *));
217 static int process_lock(P1(struct lock_descr FAR *) Pi(char));
218 static int keep_locks(P1(struct lock_descr FAR *));
219 static int free_files(P1(struct lock_descr FAR *));
221 static int bld_lock_tables(P0);
222 static int initses(P0);
223 static int lock_files(P1(int) Pi(LOCK_REQUEST FAR *));
224 static int send_lock(P0);
225 static int send_free(P0);
226 static void reset_locks(P0);
227 static int recovery_check(P0);
233 /* Set the number of lock request retries
235 d_retries(num TASK_PARM)
239 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_NONE));
244 RETURN( db_status = S_OKAY );
250 /* Set the lock request timeout value
252 d_timeout(secs TASK_PARM)
257 return(db_status = S_OKAY);
259 LM_SETTIME sto; /* send timeout packet */
261 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_ALL));
262 if ( !dbopen ) RETURN( dberr(S_DBOPEN) );
267 if ( nw_send(lsn, (MESSAGE FAR *)&sto, sizeof(LM_SETTIME)) )
271 RETURN( db_status = S_OKAY );
277 /* Open db_VISTA database
280 d_open(dbnames, opentype TASK_PARM)
281 CONST char FAR *dbnames;
282 CONST char FAR *opentype;
285 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_ALL));
287 if (debugging_dopen) {
288 puts (__FILE__"265 d_open");
293 if ( dbopen ) d_close(TASK_ONLY);
297 switch ( *opentype ) {
301 if ( netbios_chk() == 0 )
302 RETURN( dberr( S_NONETBIOS ) );
305 strcpy(type, opentype);
314 RETURN( dberr(S_BADTYPE) );
322 #ifdef MIKER /**@@@***/
324 /* initialize the country table if "vista.ctb" exists */
325 if ( ctb_init() != S_OKAY )
332 /* open transaction activity file */
333 if ( taf_open() != S_OKAY )
338 /* initialize multi-db tables */
339 if ( initdbt(dbnames) != S_OKAY ) RETURN( db_status );
341 /* read in schema tables */
342 if ( inittab() != S_OKAY ) RETURN( db_status );
345 if (debugging_dopen) {
346 puts(__FILE__"324 d_open calling renfiles");
350 if ( renfiles() != S_OKAY ) RETURN( db_status );
354 if ( db_lockmgr ) { /* [637] Only alloc file_refs for shared open */
355 /* Macro references must be on one line for some compilers */
356 if (ALLOC_TABLE(&db_global.File_refs, size_ft*sizeof(FILE_NO),old_size_ft*sizeof(FILE_NO), "file_refs")
362 if ( *type == 's' ) {
363 /* build application file lock tables */
364 if ( bld_lock_tables() != S_OKAY )
375 if ( initses() != S_OKAY ) {
380 } /* [713] perform external recovery in one-user mode */
382 if ( recovery_check() != S_OKAY ) RETURN(db_status);
386 /* [713] perform external recovery in single-user mode */
387 if ( recovery_check() != S_OKAY ) RETURN(db_status);
392 if ( o_setup() != S_OKAY ) RETURN( db_status );
397 if (debugging_dopen) {
398 printf(__FILE__"392 d_open before key_open. pgsz=%hd lrgst=%hd\n",
399 page_size,largest_page);
403 if ( key_open() == S_OKAY ) {
404 if ( dio_init() == S_OKAY ) {
410 if (debugging_dopen) {
411 printf(__FILE__"404 d_open after dio_init. pgsz=%hd lrgst=%hd\n",
412 page_size,largest_page);
420 /* Initialize a task structure
425 byteset(tsk, '\0', sizeof(TASK));
431 tsk->Dbwait_time = 1;
432 tsk->Db_timeout = TIMEOUT_DEF;
436 tsk->Dboptions = DCHAINUSE | TRLOGGING;
438 tsk->Dboptions = DCHAINUSE;
444 /* Initialize multiple database table entries
448 CONST char FAR *dbnames;
450 register int dbt_lc; /* loop control */
451 char dbfile [DtSrFILENMLEN];
459 /* compute number of databases to be opened */
460 old_no_of_dbs = (( no_of_dbs == 1 ) ? 0 : no_of_dbs);
461 for ( cp = dbnames; *cp; ++cp )
462 if ( *cp == ';' ) ++no_of_dbs;
464 if (debugging_dopen) {
465 printf(__FILE__"457 initdbt: new#dbs=%d\n", (int)no_of_dbs);
470 /* Now make sure there are the right # of elements in dbd/dbfpath */
472 if (get_element(dbdpath,no_of_dbs-1) == NULL) /* Not enuf? */
473 return( dberr(S_BADBDPATH) );
474 if (strrchr(dbdpath,';') != NULL) /* Is dbdpath single element */
475 if (get_element(dbdpath,no_of_dbs) != NULL) /* Too many? */
476 return( dberr(S_BADBDPATH) );
479 if (get_element(dbfpath,no_of_dbs-1) == NULL) /* Not enuf? */
480 return( dberr(S_BADBFPATH) );
481 if (strrchr(dbfpath,';') != NULL) { /* Is dbfpath single element */
482 if (get_element(dbfpath,no_of_dbs) != NULL) /* Too many? */
483 return( dberr(S_BADBFPATH) );
487 /* allocate db_table space */
488 /* Macro references must be on one line for some compilers */
489 if ((ALLOC_TABLE(&db_global.Db_table, no_of_dbs*sizeof(DB_ENTRY),
490 old_no_of_dbs*sizeof(DB_ENTRY), "db_table") != S_OKAY) ||
491 (ALLOC_TABLE(&db_global.Rn_table, no_of_dbs*sizeof(RN_ENTRY),
492 old_no_of_dbs*sizeof(RN_ENTRY), "rn_table") != S_OKAY)) {
496 /* initialize db_table entries */
497 for (dbt_lc = no_of_dbs, cp = dbnames,
498 curr_db_table = &db_table[old_no_of_dbs];
500 ++cp, ++curr_db_table) {
501 /* extract database name */
502 for ( i = 0; *cp && *cp != ';'; ++cp, ++i )
506 strcpy(dbfile, dbnames);
508 if ( (ptr = strrchr(dbfile, DIRCHAR)) == NULL )
509 ptr = strrchr(dbfile, ':');
511 if ( strlen(ptr+1) >= DBNMLEN ) RETURN( dberr(S_NAMELEN) );
512 strcpy(DB_REF(db_name), ptr+1);
514 if ( strlen(dbfile) >= PATHLEN ) RETURN( dberr(S_NAMELEN) );
515 strcpy(DB_REF(db_path), dbfile);
518 strcpy(DB_REF(db_path), "");
519 strcpy(DB_REF(db_name), dbfile);
524 return( db_status = S_OKAY );
530 /* Check for possible recovery
532 static recovery_check()
537 register int tn; /* transaction number */
538 register int tc; /* transaction count */
543 /* open tr activity file */
544 if ( taf_access() == S_OKAY ) {
548 if (taf_count != 0) {
549 if (d_recover(taf_files[0] CURRTASK_PARM) != S_OKAY)
555 if ( tc = taf_count ) {
556 /* perform recovery on each file */
557 for ( tn = 0; tn < tc; ++tn ) {
558 if ( d_recover(taf_files[0] CURRTASK_PARM) != S_OKAY ) return( db_status );
569 /* tell lock manager that we're done */
570 trend_pkt.fcn = L_RECDONE;
571 if ( nw_send(lsn, (MESSAGE FAR *)&trend_pkt, sizeof(LM_TREND)) )
583 /* Initial lock manager session
587 LM_DBOPEN_P Send_pkt;
588 LR_DBOPEN_P Recv_pkt;
589 register int ft_lc; /* loop control */
591 int send_size, recv_size, recvd_sz;
594 register FILE_ENTRY FAR *file_ptr;
595 FILE_NO FAR *fref_ptr;
596 INT FAR *rcv_fref_ptr;
598 if ( (net_status=nw_addnm(dbuserid, (int *)NULL) ) != N_OKAY )
599 if ( net_status == N_DUPNAME ) {
600 /* It is okay to reuse this name, but first be sure that all
601 sessions are hung up.
603 nw_cleanup(dbuserid);
608 if ( nw_call("lockmgr", dbuserid, &lsn) ) {
611 db_timeout = TIMEOUT_DEF; /* reset default timeout value */
615 /* This section of code MUST be identical to else (DOS) below */
617 for (ft_lc = size_ft - old_size_ft, file_ptr = &file_table[old_size_ft];
618 --ft_lc >= 0; ++file_ptr)
619 send_size += strlen(file_ptr->ft_name) + 1;
620 send_size += sizeof(LM_DBOPEN);
621 send_size += send_size % 2;
623 send_size = sizeof(LM_DBOPEN) + (size_ft-1)*sizeof(LM_FILEID);
625 send_pkt = (LM_DBOPEN FAR *)ALLOC(&Send_pkt, send_size, "send_pkt");
626 recv_size = sizeof(LR_DBOPEN) + (size_ft-1)*sizeof(INT);
627 recv_pkt = (LR_DBOPEN FAR *)ALLOC(&Recv_pkt, recv_size, "recv_pkt");
628 if (send_pkt == NULL || recv_pkt == NULL) {
630 return(dberr(S_NOMEMORY));
633 send_pkt->fcn = L_DBOPEN;
634 send_pkt->nfiles = size_ft;
635 send_pkt->type = type[0];
636 for (ft_lc = size_ft - old_size_ft, file_ptr = &file_table[old_size_ft],
637 fi_ptr = send_pkt->fnames;
639 --ft_lc >= 0; fi_ptr += strlen(file_ptr->ft_name)+1,++file_ptr) {
641 --ft_lc >= 0; ++fi_ptr,++file_ptr) {
643 if (stat(file_ptr->ft_name, &stbuf) == -1) {
645 return(dberr(S_NOFILE));
648 fi_ptr->inode = stbuf.st_ino;
649 fi_ptr->device = stbuf.st_dev;
651 strcpy(fi_ptr,file_ptr->ft_name);
655 if (nw_send(lsn, (MESSAGE FAR *)send_pkt, send_size) ||
656 nw_rcvmsg(lsn, (MESSAGE FAR *)recv_pkt, recv_size, &recvd_sz)) {
661 if ( recv_pkt->status == L_RECOVER ) {
662 /* perform auto-recovery */
663 d_recover( (CONST char FAR *)recv_pkt->logfile CURRTASK_PARM );
665 /* tell lock mgr we're done */
666 trend_pkt.fcn = L_RECDONE;
667 if ( nw_send(lsn, (MESSAGE FAR *)&trend_pkt, sizeof(LM_TREND)) ) {
671 /* re-issue open request */
674 if ( recv_pkt->fcn != L_DBOPEN ) {
676 return(dberr(S_NETSYNC));
678 if ( recv_pkt->status != L_OKAY ) {
685 MEM_UNLOCK(&Send_pkt);
687 MEM_UNLOCK(&Recv_pkt);
690 return(db_status = S_UNAVAIL);
692 if ( recv_pkt->nusers == 1 )
693 if ( recovery_check() != S_OKAY ) {
698 /* [656] perform initialization if not general lockmgr */
700 for (ft_lc = size_ft - old_size_ft, fref_ptr = &file_refs[old_size_ft],
701 rcv_fref_ptr = recv_pkt->frefs;
702 --ft_lc >= 0; ++fref_ptr, ++rcv_fref_ptr) {
703 *fref_ptr = *rcv_fref_ptr;
706 MEM_UNLOCK(&Send_pkt);
708 MEM_UNLOCK(&Recv_pkt);
711 session_active = TRUE;
712 return(db_status = S_OKAY);
717 /* Build application file lock tables
719 static int bld_lock_tables()
722 register int fd_lc; /* loop control */
723 register int st_lc; /* loop control */
725 #define file_used File_used.ptr
730 struct lock_descr FAR *ld_ptr;
731 RECORD_ENTRY FAR *rec_ptr;
732 FIELD_ENTRY FAR *fld_ptr;
733 SET_ENTRY FAR *set_ptr;
734 MEMBER_ENTRY FAR *mem_ptr;
735 register int FAR *fu_ptr;
741 old_size = old_size_ft*sizeof(int);
742 new_size = size_ft*sizeof(int);
743 File_used.ptr = NULL;
744 /* Macro references must be on one line for some compilers */
745 if ((ALLOC_TABLE(&db_global.App_locks, new_size, old_size, "app_locks")
747 (ALLOC_TABLE(&db_global.Excl_locks, new_size, old_size, "excl_locks")
749 (ALLOC_TABLE(&db_global.Kept_locks, new_size, old_size, "kept_locks")
751 (ALLOC_TABLE(&File_used, new_size, old_size, "file_used")
756 old_size = old_size_rt * sizeof(struct lock_descr);
757 new_size = size_rt * sizeof(struct lock_descr);
758 if ((ALLOC_TABLE(&db_global.Rec_locks, new_size, old_size, "rec_locks")
764 new_size = size_st * sizeof(struct lock_descr);
765 old_size = old_size_st * sizeof(struct lock_descr);
766 /* Macro references must be on one line for some compilers */
767 if (ALLOC_TABLE(&db_global.Set_locks, new_size, old_size, "set_locks")
773 /* build rec_locks table */
774 for (rec = old_size_rt, rec_ptr = &record_table[old_size_rt],
777 ++rec, ++rec_ptr, ++ld_ptr) {
778 ld_ptr->fl_type = 'f';
779 ld_ptr->fl_prev = 'f'; /*[367] init to free */
780 ld_ptr->fl_kept = FALSE;
782 /* put record's data file in list */
783 file_used[rec_ptr->rt_file] = TRUE;
785 /* add any key files to list */
786 fl_cnt = 1; /* count of used files */
787 for (fd_lc = size_fd - rec_ptr->rt_fields,
788 fld_ptr = &field_table[rec_ptr->rt_fields];
789 (--fd_lc >= 0) && (fld_ptr->fd_rec == rec);
791 if ( fld_ptr->fd_key != NOKEY ) {
792 fu_ptr = &file_used[fld_ptr->fd_keyfile];
799 ld_ptr->fl_cnt = fl_cnt;
800 ld_ptr->fl_list.ptr =
801 /* Macro references must be on one line for some compilers */
802 (FILE_NO FAR *)ALLOC(&ld_ptr->fl_list, fl_cnt*sizeof(FILE_NO), db_avname);
803 if ( ld_ptr->fl_list.ptr == NULL ) return( dberr(S_NOMEMORY) );
804 fl_ptr = ld_ptr->fl_list.ptr;
805 for (i = 0, fu_ptr = file_used; i < size_ft; ++i, ++fu_ptr) {
811 FL_LIST_DEACCESS(ld_ptr);
813 /* build set_locks table */
815 for (st_lc = size_st - old_size_st, set_ptr = &set_table[old_size_st],
817 --st_lc >= 0; ++set_ptr, ++ld_ptr) {
818 /* add owner's data file */
819 file_used[record_table[set_ptr->st_own_rt].rt_file] = TRUE;
820 ld_ptr->fl_type = 'f';
821 ld_ptr->fl_prev = 'f'; /*[367] init to free */
822 ld_ptr->fl_kept = FALSE;
824 /* add member record data files to list */
825 fl_cnt = 1; /* count of used files */
826 for (mem = set_ptr->st_members, memtot = mem + set_ptr->st_memtot,
827 mem_ptr = &member_table[mem];
830 fu_ptr = &file_used[record_table[mem_ptr->mt_record].rt_file];
836 ld_ptr->fl_cnt = fl_cnt;
837 ld_ptr->fl_list.ptr =
838 /* Macro references must be on one line for some compilers */
839 (FILE_NO FAR *)ALLOC(&ld_ptr->fl_list, fl_cnt*sizeof(FILE_NO), db_avname);
840 if ( ld_ptr->fl_list.ptr == NULL ) return( dberr(S_NOMEMORY) );
841 fl_ptr = ld_ptr->fl_list.ptr;
842 for (i = 0, fu_ptr = file_used; i < size_ft; ++i, ++fu_ptr) {
848 FL_LIST_DEACCESS(ld_ptr);
851 /* build key_locks table */
853 old_keyl_cnt = keyl_cnt;
854 for (fd_lc = size_fd - old_size_fd, fld_ptr = &field_table[old_size_fd];
855 --fd_lc >= 0; ++fld_ptr) {
856 /* count number of keys */
857 if (fld_ptr->fd_key != NOKEY)
861 old_size = old_keyl_cnt*sizeof(struct lock_descr);
862 new_size = keyl_cnt*sizeof(struct lock_descr);
863 /* Macro references must be on one line for some compilers */
864 if (ALLOC_TABLE(&db_global.Key_locks, new_size, old_size, "key_locks")
868 for (fd_lc = size_fd - old_size_fd, fld_ptr = &field_table[old_size_fd],
870 --fd_lc >= 0; ++fld_ptr) {
871 if (fld_ptr->fd_key != NOKEY) {
872 ld_ptr->fl_type = 'f';
873 ld_ptr->fl_prev = 'f'; /*[367] init to free */
874 ld_ptr->fl_kept = FALSE;
876 ld_ptr->fl_list.ptr = (FILE_NO FAR *)ALLOC(&ld_ptr->fl_list, ld_ptr->fl_cnt*sizeof(FILE_NO), "fl_list");
877 if ( ld_ptr->fl_list.ptr == NULL ) return( dberr(S_NOMEMORY) );
878 *(ld_ptr->fl_list.ptr) = fld_ptr->fd_keyfile;
879 FL_LIST_DEACCESS(ld_ptr);
884 lp_size = sizeof(LM_LOCK) + (size_ft-1)*sizeof(LM_LOCKREQ);
885 fp_size = sizeof(LM_FREE) + (size_ft-1)*sizeof(INT);
886 lock_pkt = (LM_LOCK FAR *)ALLOC(&db_global.Lock_pkt, lp_size, "lock_pkt");
887 free_pkt = (LM_FREE FAR *)ALLOC(&db_global.Free_pkt, fp_size, "free_pkt");
888 if ( !lock_pkt || !free_pkt ) return( dberr(S_NOMEMORY) );
889 lock_pkt->fcn = L_LOCK;
890 free_pkt->fcn = L_FREE;
891 MEM_UNLOCK(&File_used);
895 return( db_status = S_OKAY );
900 /****************************************/
904 /****************************************/
913 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_ALL));
918 /* in case they forgot to end the transaction */
920 d_trabort(TASK_ONLY);
928 for (i = 0; i < size_ft; ++i) {
929 /* close all files */
933 #ifdef MIKER /**@@@***/
935 /* free the country table */
936 if ( db_global.ctbl_activ )
947 d_freeall(TASK_ONLY);
950 if ( use_ovfl ) o_free();
975 session_active = FALSE;
995 bytecpy(task.v.ptr, &db_global, sizeof(TASK));
1004 /* Terminate lock manager session
1008 LM_DBCLOSE_P Send_pkt;
1009 register int ft_lc; /* loop control */
1011 register FILE_NO FAR *fref_ptr;
1012 register INT FAR *snd_fref_ptr;
1014 if ( session_active ) {
1015 send_size = sizeof(LM_DBCLOSE) + (size_ft-1)*sizeof(INT);
1016 send_pkt = (LM_DBCLOSE FAR *)ALLOC(&Send_pkt, send_size, "send_pkt");
1017 if ( send_pkt == NULL ) return( dberr(S_NOMEMORY) );
1018 send_pkt->fcn = L_DBCLOSE;
1019 send_pkt->nfiles = size_ft;
1020 for (ft_lc = size_ft, fref_ptr = file_refs,
1021 snd_fref_ptr = send_pkt->frefs;
1022 --ft_lc >= 0; ++fref_ptr, ++snd_fref_ptr)
1023 *snd_fref_ptr = *fref_ptr;
1024 if ( nw_send(lsn, (MESSAGE FAR *)send_pkt, send_size) )
1029 MEM_UNLOCK(&Send_pkt);
1031 MEM_UNLOCK(&db_global.File_refs);
1032 FREE(&db_global.File_refs);
1033 session_active = FALSE;
1035 return( db_status = S_OKAY );
1041 /* Free all allocated memory upon termination
1047 register struct lock_descr FAR *ld_ptr;
1050 /* free all allocated memory */
1052 MEM_UNLOCK(&db_global.Curr_mem);
1053 FREE(&db_global.Curr_mem);
1056 MEM_UNLOCK(&db_global.Curr_own);
1057 FREE(&db_global.Curr_own);
1059 #ifndef NO_TIMESTAMP
1061 MEM_UNLOCK(&db_global.Co_time);
1062 FREE(&db_global.Co_time);
1065 MEM_UNLOCK(&db_global.Cm_time);
1066 FREE(&db_global.Cm_time);
1069 MEM_UNLOCK(&db_global.Cs_time);
1070 FREE(&db_global.Cs_time);
1074 MEM_UNLOCK(&db_global.Sort_table);
1075 FREE(&db_global.Sort_table);
1077 if ( member_table ) {
1078 MEM_UNLOCK(&db_global.Member_table);
1079 FREE(&db_global.Member_table);
1082 MEM_UNLOCK(&db_global.Set_table);
1083 FREE(&db_global.Set_table);
1085 if ( field_table ) {
1086 MEM_UNLOCK(&db_global.Field_table);
1087 FREE(&db_global.Field_table);
1090 MEM_UNLOCK(&db_global.Key_table);
1091 FREE(&db_global.Key_table);
1093 if ( record_table ) {
1094 MEM_UNLOCK(&db_global.Record_table);
1095 FREE(&db_global.Record_table);
1098 MEM_UNLOCK(&db_global.File_table);
1099 FREE(&db_global.File_table);
1103 MEM_UNLOCK(&db_global.App_locks);
1104 FREE(&db_global.App_locks);
1107 MEM_UNLOCK(&db_global.Excl_locks);
1108 FREE(&db_global.Excl_locks);
1111 MEM_UNLOCK(&db_global.Kept_locks);
1112 FREE(&db_global.Kept_locks);
1115 for (i = 0, ld_ptr = rec_locks; i < size_rt; ++i, ++ld_ptr) {
1116 MEM_UNLOCK(&ld_ptr->fl_list);
1117 FREE(&ld_ptr->fl_list);
1119 MEM_UNLOCK(&db_global.Rec_locks);
1120 FREE(&db_global.Rec_locks);
1123 for (i = 0, ld_ptr = set_locks; i < size_st; ++i, ++ld_ptr) {
1124 MEM_UNLOCK(&ld_ptr->fl_list);
1125 FREE(&ld_ptr->fl_list);
1127 MEM_UNLOCK(&db_global.Set_locks);
1128 FREE(&db_global.Set_locks);
1131 for (i = 0, ld_ptr = key_locks; i < keyl_cnt; ++i, ++ld_ptr) { /*[637]*/
1132 MEM_UNLOCK(&ld_ptr->fl_list);
1133 FREE(&ld_ptr->fl_list);
1135 MEM_UNLOCK(&db_global.Key_locks);
1136 FREE(&db_global.Key_locks);
1139 MEM_UNLOCK(&db_global.Lock_pkt);
1140 FREE(&db_global.Lock_pkt);
1143 MEM_UNLOCK(&db_global.Free_pkt);
1144 FREE(&db_global.Free_pkt);
1149 MEM_UNLOCK(&db_global.Db_table);
1150 FREE(&db_global.Db_table);
1153 MEM_UNLOCK(&db_global.Rn_table);
1154 FREE(&db_global.Rn_table);
1160 /* Establish record file locks
1162 d_reclock(rec, lock_type TASK_PARM DBN_PARM)
1164 char FAR *lock_type;
1169 return(db_status = S_OKAY);
1173 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1176 lr.type = *lock_type;
1178 RETURN( d_lock(1, &lr TASK_PARM DBN_PARM) );
1185 /* Establish set file locks
1187 d_setlock(set, lock_type TASK_PARM DBN_PARM)
1189 char FAR *lock_type;
1194 return (db_status = S_OKAY);
1198 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1201 lr.type = *lock_type;
1203 RETURN( d_lock(1, &lr TASK_PARM DBN_PARM) );
1211 d_keylock(key, lock_type TASK_PARM DBN_PARM)
1212 long key; /* field number of key */
1213 char FAR *lock_type;
1218 return (db_status = S_OKAY);
1222 RECORD_ENTRY FAR *rec_ptr;
1223 FIELD_ENTRY FAR *fld_ptr;
1225 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1227 if (nfld_check(key, &rec, &fld, (RECORD_ENTRY FAR * FAR *)&rec_ptr, (FIELD_ENTRY FAR * FAR *)&fld_ptr) != S_OKAY)
1228 RETURN( db_status );
1230 if (fld_ptr->fd_key == NOKEY)
1231 RETURN( dberr(S_NOTKEY) );
1233 /* KEYMARK allows 'fld' to be recognized as a key file. It is already
1234 adjusted (in nfld_check) to INTernal format. Don't play with it in
1235 d_lock and lock_files.
1237 lr.item = fld + KEYMARK;
1238 lr.type = *lock_type;
1240 RETURN( d_lock(1, &lr TASK_PARM DBN_PARM) );
1246 /* Return lock status for record type
1248 d_reclstat(rec, lstat TASK_PARM DBN_PARM)
1256 return( db_status = S_OKAY );
1258 RECORD_ENTRY FAR *rec_ptr;
1260 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_NOIO));
1262 if (nrec_check(rec, &rec, (RECORD_ENTRY FAR * FAR *)&rec_ptr) != S_OKAY)
1263 RETURN( db_status );
1268 if (rec_ptr->rt_flags & STATIC)
1271 *lstat = rec_locks[rec].fl_type;
1273 RETURN( db_status = S_OKAY );
1279 /* Return lock status for set type
1281 d_setlstat(set, lstat TASK_PARM DBN_PARM)
1289 return (db_status = S_OKAY);
1291 SET_ENTRY FAR *set_ptr;
1293 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_NOIO));
1295 if (nset_check(set, &set, (SET_ENTRY FAR * FAR *)&set_ptr) != S_OKAY)
1296 RETURN( db_status );
1301 *lstat = set_locks[set].fl_type;
1303 RETURN( db_status = S_OKAY );
1309 /* Return lock status for key type
1311 d_keylstat(key, lstat TASK_PARM DBN_PARM)
1319 return (db_status = S_OKAY);
1322 RECORD_ENTRY FAR *rec_ptr;
1323 FIELD_ENTRY FAR *fld_ptr;
1325 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_NOIO));
1327 if (nfld_check(key, &rec, &fld, (RECORD_ENTRY FAR * FAR *)&rec_ptr, (FIELD_ENTRY FAR * FAR *)&fld_ptr) != S_OKAY)
1328 RETURN( db_status );
1330 if (fld_ptr->fd_key == NOKEY)
1331 RETURN( dberr(S_NOTKEY) );
1336 if ( file_table[fld_ptr->fd_keyfile].ft_flags & STATIC )
1339 *lstat = key_locks[fld_ptr->fd_keyno].fl_type;
1341 RETURN( db_status = S_OKAY );
1347 /* Lock a group of records and/or sets
1349 d_lock(count, lrpkt TASK_PARM DBN_PARM)
1351 LOCK_REQUEST FAR *lrpkt;
1356 return (db_status = S_OKAY);
1360 register LOCK_REQUEST FAR *lrpkt_ptr;
1361 struct lock_descr FAR *ld_ptr;
1363 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1366 RETURN( db_status = S_OKAY );
1368 lock_pkt->nfiles = 0;
1369 for (i = 0, lrpkt_ptr = lrpkt;
1370 (db_status == S_OKAY) && (i < count);
1372 if ( lrpkt_ptr->item >= KEYMARK ) {
1373 /* do not adjust lrpkt->item (see comment in d_keylock) */
1374 item = field_table[lrpkt_ptr->item - KEYMARK].fd_keyno;
1375 process_lock(&key_locks[item], lrpkt_ptr->type);
1377 else if ( lrpkt_ptr->item >= SETMARK ) {
1378 item = NUM2INT(lrpkt_ptr->item - SETMARK, st_offset);
1379 process_lock(&set_locks[item], lrpkt_ptr->type);
1381 else if ( lrpkt_ptr->item >= RECMARK ) {
1382 item = NUM2INT(lrpkt_ptr->item - RECMARK, rt_offset);
1383 if ( record_table[item].rt_flags & STATIC )
1386 process_lock(&rec_locks[item], lrpkt_ptr->type);
1391 if ( db_status == S_OKAY )
1392 lock_files(count, lrpkt);
1394 if ( db_status != S_OKAY ) {
1395 /* reset lock descriptor tables to previous state */
1396 for (i = 0, lrpkt_ptr = lrpkt; i < count; ++i, ++lrpkt_ptr) {
1397 /* do not adjust lrpkt->item (see comment in d_keylock) */
1398 if ( lrpkt_ptr->item >= KEYMARK ) {
1399 item = field_table[lrpkt_ptr->item - KEYMARK].fd_keyno;
1400 ld_ptr = &key_locks[item];
1402 else if ( lrpkt_ptr->item >= SETMARK ) {
1403 item = NUM2INT(lrpkt_ptr->item - SETMARK, st_offset);
1404 ld_ptr = &set_locks[item];
1406 else if ( lrpkt_ptr->item >= RECMARK ) {
1407 item = NUM2INT(lrpkt_ptr->item - RECMARK, rt_offset);
1408 ld_ptr = &rec_locks[item];
1412 ld_ptr->fl_type = ld_ptr->fl_prev;
1415 RETURN( db_status );
1422 /* Process set/record lock
1424 static process_lock(ld_ptr, type )
1425 struct lock_descr FAR *ld_ptr;
1428 register int fl_lc; /* loop control */
1431 register LM_LOCKREQ FAR *lockreq_ptr;
1432 FILE_NO FAR *fl_ptr, fref;
1435 ld_ptr->fl_prev = ld_ptr->fl_type;
1439 dberr( S_TRNOTACT );
1440 else if ( ld_ptr->fl_prev == 'f' )
1441 dberr( S_NOTLOCKED );
1442 else if ( ld_ptr->fl_prev != 'x' )
1443 return( keep_locks(ld_ptr) );
1446 if( ld_ptr->fl_prev != 'f' )
1449 ld_ptr->fl_type = 'r';
1453 dberr( S_TRNOTACT );
1454 else if ( ld_ptr->fl_prev != 'f' && ld_ptr->fl_prev != 'r' )
1457 ld_ptr->fl_type = 'w';
1460 if ( ld_ptr->fl_prev != 'f' && ld_ptr->fl_prev != 'r' )
1463 ld_ptr->fl_type = 'x';
1468 if ( db_status == S_OKAY ) {
1469 /* build lock request packet */
1470 for (fl_lc = ld_ptr->fl_cnt, fl_ptr = FL_LIST_ACCESS(ld_ptr);
1471 --fl_lc >= 0; ++fl_ptr) {
1472 fref = file_refs[fno = *fl_ptr];
1473 for (i = 0, lockreq_ptr = lock_pkt->locks;
1474 (i < lock_pkt->nfiles) && (lockreq_ptr->fref != fref);
1476 ; /* null statement */
1478 if (i < lock_pkt->nfiles) {
1479 /* file already is in lock request packet */
1480 if ( lockreq_ptr->type == 'r' || ld_ptr->fl_type == 'x' )
1481 lockreq_ptr->type = ld_ptr->fl_type;
1483 else if ( !excl_locks[fno] && ( !app_locks[fno] ||
1484 (ld_ptr->fl_type == 'w' && app_locks[fno] > 0) ||
1485 (ld_ptr->fl_type == 'x') ) ) {
1486 /* add to lock request packet */
1488 lockreq_ptr->fref = fref;
1489 lockreq_ptr->type = ld_ptr->fl_type;
1492 FL_LIST_DEACCESS(ld_ptr);
1494 return( db_status );
1500 /* Lock database files
1502 static lock_files(count, lrpkt )
1504 LOCK_REQUEST FAR *lrpkt;
1507 register int fl_lc; /* loop control */
1508 struct lock_descr FAR *ld_ptr;
1512 LOCK_REQUEST FAR *lrpkt_ptr;
1513 int FAR *appl_ptr, FAR *excl_ptr;
1514 FILE_NO FAR *fl_ptr;
1516 lock_reply.status = L_OKAY;
1517 if ( lock_pkt->nfiles == 0 ) goto skip_send;
1519 if ( send_lock() != S_OKAY )
1520 return( db_status );
1523 switch ( lock_reply.status ) {
1525 /* update app_locks and excl_lock tables */
1526 for (l = 0, lrpkt_ptr = lrpkt; l < count; ++l, ++lrpkt_ptr) {
1527 if (lrpkt_ptr->type == 'k')
1528 continue; /* skip keep lock requests */
1529 /* process each record/set lock */
1530 /* do not adjust lrpkt->item (see comment in d_keylock) */
1531 if ( lrpkt_ptr->item >= KEYMARK ) {
1532 item = field_table[lrpkt_ptr->item - KEYMARK].fd_keyno;
1533 ld_ptr = &key_locks[item];
1535 else if ( lrpkt_ptr->item >= SETMARK ) {
1536 item = NUM2INT(lrpkt_ptr->item - SETMARK, st_offset);
1537 ld_ptr = &set_locks[item];
1540 item = NUM2INT(lrpkt_ptr->item - RECMARK, rt_offset);
1541 ld_ptr = &rec_locks[item];
1543 for (fl_lc = ld_ptr->fl_cnt, fl_ptr = FL_LIST_ACCESS(ld_ptr);
1544 --fl_lc >= 0; ++fl_ptr) {
1545 /* process each file for each record/set lock */
1547 appl_ptr = &app_locks[fno];
1548 excl_ptr = &excl_locks[fno];
1549 if ( !*appl_ptr && !*excl_ptr ) {
1550 /* clear file's pages from cache */
1553 if ( ld_ptr->fl_type == 'r' ) {
1554 if ( *appl_ptr >= 0 )
1555 /* increment if file free or read-locked */
1559 if ( ld_ptr->fl_type == 'w' )
1561 else if ( ld_ptr->fl_type == 'x' ) {
1563 if ( ld_ptr->fl_prev == 'r' ) {
1564 /* read to excl lock upgrade */
1570 FL_LIST_DEACCESS(ld_ptr);
1575 return( db_status = S_UNAVAIL );
1577 return( dberr(S_SYSERR) );
1581 return( db_status = S_OKAY );
1587 /* Send lock request
1589 static int send_lock()
1593 int send_size, recv_size;
1595 if ( lock_pkt->nfiles ) {
1596 /* send lock request */
1597 send_size = sizeof(LM_LOCK) + (lock_pkt->nfiles-1)*sizeof(LM_LOCKREQ);
1598 if ( send_size > lp_size )
1599 return( dberr(S_SYSERR) );
1603 printf("nw_send(lsn,lock_pkt->fcn=%ld,size=%d\n",lock_pkt->fcn,send_size);
1605 if ( nw_send(lsn, (MESSAGE FAR *)lock_pkt, send_size) )
1608 if ( nw_rcvmsg(lsn, (MESSAGE FAR *)&lock_reply, sizeof(LR_LOCK), &recv_size) )
1611 printf("nw_rcvmsg(lock_reply.fcn=%ld,lock_reply.status=%d\n",
1612 lock_reply.fcn,lock_reply.status);
1615 /* request must always be granted */
1616 if ( lock_reply.fcn != L_LOCK )
1617 return( dberr(S_NETSYNC) );
1619 if (lock_reply.status == L_RECOVER) {
1620 /* perform auto-recovery */
1621 d_recover(lock_reply.logfile CURRTASK_PARM);
1623 /* tell lock mgr we're done */
1624 trend_pkt.fcn = L_RECDONE;
1625 if (nw_send(lsn, (MESSAGE FAR *)&trend_pkt, sizeof(LM_TREND)))
1628 /* re-issue lock request */
1631 if (lock_reply.status == L_QUEUEFULL) {
1638 return( db_status = S_OKAY );
1646 d_keyfree(key TASK_PARM DBN_PARM)
1652 return (db_status = S_OKAY);
1655 RECORD_ENTRY FAR *rec_ptr;
1656 FIELD_ENTRY FAR *fld_ptr;
1657 struct lock_descr FAR *ld_ptr;
1659 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1661 if (nfld_check(key, &rec, &fld, (RECORD_ENTRY FAR * FAR *)&rec_ptr, (FIELD_ENTRY FAR * FAR *)&fld_ptr) != S_OKAY)
1662 RETURN( db_status );
1664 if ( fld_ptr->fd_key == NOKEY )
1665 RETURN( dberr(S_NOTKEY) );
1667 if ( dbopen >= 2 ) /* exclusive access needs no locks */
1668 RETURN( db_status = S_OKAY );
1670 ld_ptr = &key_locks[fld_ptr->fd_keyno];
1672 RETURN( dberr(S_TRFREE) );
1674 if ( ld_ptr->fl_type == 'f' )
1675 RETURN( dberr(S_NOTLOCKED) );
1678 ld_ptr->fl_type = 'f';
1680 RETURN( db_status );
1687 /* Setup table to keep locks after transaction end
1689 static keep_locks( ld_ptr )
1690 struct lock_descr FAR *ld_ptr; /* Lock descriptor */
1692 register int fl_lc; /* loop control */
1693 register FILE_NO FAR *fl_ptr;
1695 /* Mark lock as kept */
1696 ld_ptr->fl_kept = TRUE;
1698 for (fl_lc = ld_ptr->fl_cnt, fl_ptr = FL_LIST_ACCESS(ld_ptr);
1699 --fl_lc >= 0; ++fl_ptr)
1700 ++kept_locks[*fl_ptr];
1701 FL_LIST_DEACCESS(ld_ptr);
1703 return( db_status = S_OKAY );
1710 d_recfree(rec TASK_PARM DBN_PARM)
1716 return (db_status = S_OKAY);
1718 RECORD_ENTRY FAR *rec_ptr;
1719 struct lock_descr FAR *ld_ptr;
1721 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1723 if (nrec_check(rec, &rec, (RECORD_ENTRY FAR * FAR *)&rec_ptr) != S_OKAY)
1724 RETURN( db_status );
1726 if ( dbopen >= 2 ) /* exclusive access needs no locks */
1727 RETURN( db_status = S_OKAY );
1729 ld_ptr = &rec_locks[rec];
1732 RETURN( dberr(S_TRFREE) );
1734 if ( ld_ptr->fl_type == 'f' )
1735 RETURN( dberr(S_NOTLOCKED) );
1738 ld_ptr->fl_type = 'f';
1740 RETURN( db_status );
1748 d_setfree(set TASK_PARM DBN_PARM)
1754 return (db_status = S_OKAY);
1756 SET_ENTRY FAR *set_ptr;
1757 struct lock_descr FAR *ld_ptr;
1759 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1761 if (nset_check(set, &set, (SET_ENTRY FAR * FAR *)&set_ptr) != S_OKAY)
1762 RETURN( db_status );
1764 if ( dbopen >= 2 ) /* exclusive access needs no locks */
1765 RETURN( db_status = S_OKAY );
1767 ld_ptr = &set_locks[set];
1770 RETURN( dberr(S_TRFREE) );
1772 if ( ld_ptr->fl_type == 'f' )
1773 RETURN( dberr(S_NOTLOCKED) );
1776 ld_ptr->fl_type = 'f';
1778 RETURN( db_status );
1786 /* Free read-locked files associated with record or set
1788 static int free_files(ld_ptr)
1789 struct lock_descr FAR *ld_ptr;
1791 register int fl_lc; /* loop control */
1793 LM_LOCKREQ FAR *lockreq_ptr;
1796 register FILE_NO FAR *fl_ptr;
1798 /* fill free packet */
1799 lock_pkt->nfiles = free_pkt->nfiles = 0;
1800 for (fl_lc = ld_ptr->fl_cnt, fl_ptr = FL_LIST_ACCESS(ld_ptr);
1801 --fl_lc >= 0; ++fl_ptr) {
1803 appl_ptr = &app_locks[fno];
1804 fref = file_refs[fno];
1805 if ( ld_ptr->fl_type == 'r' && *appl_ptr > 0 ) {
1806 /* free read lock */
1807 if ( --*appl_ptr == 0 && excl_locks[fno] == 0 ) {
1808 free_pkt->frefs[free_pkt->nfiles++] = fref;
1809 /* reset key scan position */
1810 if ( file_table[fno].ft_type == 'k' )
1814 else if ( --excl_locks[fno] == 0 ) {
1815 /* free exclusive access lock */
1816 if ( *appl_ptr > 0 ) {
1817 /* downgrade to read-lock */
1818 lockreq_ptr = &lock_pkt->locks[lock_pkt->nfiles++];
1819 lockreq_ptr->type = 'r';
1820 lockreq_ptr->fref = fref;
1823 /* free excl-lock */
1824 free_pkt->frefs[free_pkt->nfiles++] = fref;
1826 /* reset key scan position */
1827 if ( file_table[fno].ft_type == 'k' )
1831 if ( ld_ptr->fl_kept ) {
1832 /* Remove hold on lock */
1833 if ( --kept_locks[fno] < 0 ) return( dberr(S_BADLOCKS) );
1834 ld_ptr->fl_kept = FALSE;
1837 FL_LIST_DEACCESS(ld_ptr);
1838 /* send any downgrades */
1839 if ( send_lock() == S_OKAY ) {
1840 /* free any files */
1843 return( db_status );
1848 /* free all locked files
1850 d_freeall(TASK_ONLY)
1854 return (db_status = S_OKAY);
1857 register FILE_NO FAR *fref_ptr;
1858 register int FAR *appl_ptr;
1860 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
1862 if ( ! dbopen ) RETURN( dberr(S_DBOPEN) );
1864 if ( dbopen >= 2 ) /* exclusive access needs no locks */
1865 RETURN( db_status = S_OKAY );
1867 if ( trans_id ) RETURN( dberr(S_TRFREE) );
1869 free_pkt->nfiles = 0;
1870 for (i = 0, fref_ptr = file_refs, appl_ptr = app_locks;
1872 ++i, ++fref_ptr, ++appl_ptr) {
1876 free_pkt->frefs[free_pkt->nfiles++] = *fref_ptr;
1879 /* send free files packet */
1880 if ( send_free() != S_OKAY )
1881 RETURN( db_status );
1883 /* reset all lock descriptors */
1886 /* reset all key file positions */
1889 /* Clear cache pages and return */
1890 RETURN( dio_clear() );
1897 /* Reset lock descriptor tables
1899 static void reset_locks()
1903 register struct lock_descr FAR *ld_ptr;
1905 /* reset record lock descriptors */
1908 for (i = beg, ld_ptr = &rec_locks[i]; i < end; ++i, ++ld_ptr) {
1909 if ( ld_ptr->fl_kept ) {
1910 ld_ptr->fl_type = 'r';
1911 ld_ptr->fl_kept = FALSE;
1913 else if ( ld_ptr->fl_type != 'x' )
1914 ld_ptr->fl_type = 'f';
1916 /* reset set lock descriptors */
1919 for (i = beg, ld_ptr = &set_locks[i]; i < end; ++i, ++ld_ptr) {
1920 if ( ld_ptr->fl_kept ) {
1921 ld_ptr->fl_type = 'r';
1922 ld_ptr->fl_kept = FALSE;
1924 else if ( ld_ptr->fl_type != 'x' )
1925 ld_ptr->fl_type = 'f';
1927 /* reset key lock descriptors */
1930 for (i = beg, ld_ptr = &key_locks[i]; i < end; ++i, ++ld_ptr) {
1931 if ( ld_ptr->fl_kept ) {
1932 ld_ptr->fl_type = 'r';
1933 ld_ptr->fl_kept = FALSE;
1935 else if ( ld_ptr->fl_type != 'x' )
1936 ld_ptr->fl_type = 'f';
1942 /* Send free files packet
1944 static int send_free()
1949 /* send any free packets */
1950 if ( free_pkt->nfiles ) {
1951 send_size = sizeof(LM_FREE) + (free_pkt->nfiles-1)*sizeof(INT);
1952 if ( send_size > fp_size )
1953 return ( dberr(S_SYSERR) );
1955 if ( nw_send(lsn, (MESSAGE FAR *)free_pkt, send_size) )
1959 return( db_status = S_OKAY );
1965 /*------------------------------------------------------------------------
1966 Record Lock Bit Functions
1967 ------------------------------------------------------------------------*/
1969 /* Set record lock bit of current record
1980 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
1982 if ( ! curr_rec ) RETURN( dberr(S_NOCR) );
1985 file = NUM2INT((FILE_NO)((curr_rec >> FILESHIFT) & FILEMASK), ft_offset);
1988 (record_lock = (app_locks[file] >= 0 && !excl_locks[file])) ) {
1989 /* request record-lock on file */
1990 lock_pkt->nfiles = 1;
1991 lock_pkt->locks[0].type = 'R';
1992 lock_pkt->locks[0].fref = file_refs[file];
1993 if ( send_lock() != S_OKAY ) RETURN( db_status );
1994 if ( lock_reply.status != L_OKAY )
1995 RETURN( db_status = S_UNAVAIL );
1997 if ( dio_rrlb(curr_rec, &rid) != S_OKAY )
1998 RETURN( db_status );
1999 if ( rid & RLBMASK )
2000 rlb_status = S_LOCKED;
2003 rlb_status = dio_wrlb(curr_rec, rid);
2005 if ( dbopen == 1 && record_lock ) {
2006 /* free or downgrade record-lock on file */
2007 if ( app_locks[file] ) {
2008 lock_pkt->nfiles = 1;
2009 lock_pkt->locks[0].type = 'r';
2010 lock_pkt->locks[0].fref = file_refs[file];
2011 if ( send_lock() != S_OKAY ) RETURN( db_status );
2014 free_pkt->nfiles = 1;
2015 free_pkt->frefs[0] = file_refs[file];
2016 if ( send_free() != S_OKAY ) RETURN( db_status );
2019 RETURN( db_status = rlb_status );
2021 RETURN( db_status = S_OKAY );
2027 /* Clear record lock bit of current record
2037 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
2039 if ( ! curr_rec ) RETURN( dberr(S_NOCR) );
2042 file = NUM2INT((FILE_NO)((curr_rec >> FILESHIFT) & FILEMASK), ft_offset);
2044 /* ensure that changes are allowed */
2045 if (dbopen == 1 && trans_id && app_locks[file] >= 0 && !excl_locks[file])
2046 RETURN( dberr(S_NOTLOCKED) );
2048 if ( dbopen == 1 && ! trans_id ) {
2049 /* request record-lock on file */
2050 lock_pkt->nfiles = 1;
2051 lock_pkt->locks[0].type = 'R';
2052 lock_pkt->locks[0].fref = file_refs[file];
2053 if ( send_lock() != S_OKAY ) RETURN( db_status );
2054 if ( lock_reply.status != L_OKAY )
2055 RETURN( db_status = S_UNAVAIL );
2059 if ( dio_rrlb(curr_rec, &rid) != S_OKAY )
2060 RETURN( db_status );
2064 rlb_status = S_UNLOCKED;
2065 dio_wrlb(curr_rec, rid);
2067 if ( dbopen == 1 && ! trans_id ) {
2068 /* free or downgrade record-lock on file */
2069 if ( app_locks[file] ) {
2070 lock_pkt->nfiles = 1;
2071 lock_pkt->locks[0].type = 'r';
2072 lock_pkt->locks[0].fref = file_refs[file];
2073 if ( send_lock() != S_OKAY ) RETURN( db_status );
2076 free_pkt->nfiles = 1;
2077 free_pkt->frefs[0] = file_refs[file];
2078 if ( send_free() != S_OKAY ) RETURN( db_status );
2084 RETURN( db_status );
2090 /* Test record lock bit of current record
2099 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
2101 if ( ! curr_rec ) RETURN( dberr(S_NOCR) );
2104 if ( dio_rrlb(curr_rec, &rid) != S_OKAY )
2105 RETURN( db_status );
2107 if ( rid & RLBMASK )
2108 db_status = S_LOCKED;
2110 db_status = S_UNLOCKED;
2112 RETURN( rlb_status = db_status );
2114 RETURN( db_status = S_UNLOCKED );
2123 /*------------------------------------------------------------------------
2124 Database Transaction Processing Functions
2125 ------------------------------------------------------------------------*/
2127 /* Begin transaction
2129 d_trbegin(tid TASK_PARM)
2130 CONST char FAR *tid;
2133 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
2137 if ( ! dbopen ) RETURN( dberr(S_DBOPEN) );
2139 if ( tid == NULL ) RETURN( dberr(S_TRANSID) );
2142 if ( trans_id ) RETURN( dberr(S_TRACTIVE) );
2144 /* changes were possible outside a transaction */
2151 RETURN( db_status );
2163 register int ft_lc; /* loop control */
2164 LM_TRCOMMIT trcom_pkt;
2166 LM_LOCKREQ FAR *lockreq_ptr;
2167 register FILE_NO FAR *fref_ptr;
2168 register int FAR *appl_ptr, FAR *keptl_ptr, FAR *excl_ptr;
2171 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
2174 if( ! trans_id ) RETURN( dberr(S_TRNOTACT) );
2177 /* mark start of trx in archive log file */
2180 /* flush data to database or overflow */
2181 if ( dio_flush() != S_OKAY ) RETURN( db_status );
2183 if ( (dboptions & TRLOGGING) && use_ovfl ) {
2184 /* End trx using overflow file */
2186 /* flush recovery data to overflow file */
2187 if ( o_flush() != S_OKAY ) RETURN( db_status );
2190 trcom_pkt.fcn = L_TRCOMMIT;
2191 strcpy(trcom_pkt.logfile, dblog);
2192 if ( nw_send(lsn, (MESSAGE FAR *)&trcom_pkt, sizeof(LM_TRCOMMIT)) )
2198 if ( taf_add(dblog) != S_OKAY ) RETURN( db_status ); /* after nw_send */
2201 /* allow for user interrupt to test recovery */
2202 if ( db_txtest ) dberr(S_DEBUG);
2205 /* update db from overflow file */
2206 if ( o_update() != S_OKAY ) RETURN( db_status );
2209 /* flush modified cache data to database */
2210 if ( dio_flush() != S_OKAY ) RETURN( db_status );
2213 if ( taf_del(dblog) != S_OKAY ) RETURN( db_status ); /* before nw_send */
2217 trend_pkt.fcn = L_TREND;
2218 if ( nw_send(lsn, (MESSAGE FAR *)&trend_pkt, sizeof(LM_TREND)) )
2224 /* mark end of trx in archive log file */
2228 o_init(); /*[305] clear cache_ovfl flag */
2231 if ( dbopen == 1 ) {
2232 /* free unkept, non-exclusive file locks */
2233 lock_pkt->nfiles = free_pkt->nfiles = 0;
2234 for (ft_lc = size_ft, fref_ptr = file_refs, appl_ptr = app_locks,
2235 keptl_ptr = kept_locks, excl_ptr = excl_locks;
2236 --ft_lc >= 0; ++fref_ptr, ++appl_ptr, ++keptl_ptr, ++excl_ptr) {
2238 *appl_ptr = *keptl_ptr;
2239 else if ( *appl_ptr == -1 ) {
2240 if ( (*appl_ptr = *keptl_ptr) > 0 ) {
2241 lockreq_ptr = &lock_pkt->locks[lock_pkt->nfiles++];
2242 lockreq_ptr->type = 'r';
2243 lockreq_ptr->fref = *fref_ptr;
2246 free_pkt->frefs[free_pkt->nfiles++] = *fref_ptr;
2248 else if ( *appl_ptr && (*appl_ptr = *keptl_ptr) == 0 )
2249 free_pkt->frefs[free_pkt->nfiles++] = *fref_ptr;
2252 /* send lock downgrade request */
2253 if ( send_lock() != S_OKAY || send_free() != S_OKAY )
2254 RETURN( db_status );
2256 /* clear lock descriptors */
2259 /* reset all key file positions */
2262 /* clear page buffers */
2266 RETURN( db_status );
2272 /* Abort transaction
2274 d_trabort(TASK_ONLY)
2278 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
2280 RETURN (dberr(S_TRNOTACT));
2282 dio_pzclr(); /*[425] clear page zero BEFORE dio_clear */
2283 dio_clear(); /*[353] clear cache */
2284 RETURN (db_status = S_OKAY);
2287 register int FAR *keptl_ptr;
2288 register struct lock_descr FAR *ld_ptr;
2290 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
2293 if ( ! trans_id ) RETURN( dberr(S_TRNOTACT) );
2295 if ( dbopen == 1 ) {
2296 /* Revert any kept locks to unkept status */
2297 for (i = 0, keptl_ptr = kept_locks; i < size_ft; ++i, ++keptl_ptr)
2299 for (i = 0, ld_ptr = rec_locks; i < size_rt; ++i, ++ld_ptr)
2300 ld_ptr->fl_kept = FALSE;
2301 for (i = 0, ld_ptr = set_locks; i < size_st; ++i, ++ld_ptr)
2302 ld_ptr->fl_kept = FALSE;
2303 for (i = 0, ld_ptr = key_locks; i < keyl_cnt; ++i, ++ld_ptr)
2304 ld_ptr->fl_kept = FALSE;
2307 o_init(); /*[305] clear cache_ovfl flag */
2309 dio_pzclr(); /*[425] clear page zero BEFORE d_freeall */
2310 if ( dbopen == 1 ) d_freeall(TASK_ONLY);
2313 RETURN( db_status = S_OKAY );
2319 /* Report a network error
2323 switch ( net_status ) {
2325 db_status = dberr( S_LMBUSY );
2328 db_status = dberr( S_NOLOCKMGR );
2331 db_status = dberr( S_DUPUSERID );
2334 db_status = dberr( S_NETERR );
2337 return( db_status );
2341 int alloc_table(Table, new_size, old_size )
2343 #define table Table->ptr
2349 Temp_table.ptr = ALLOC(&Temp_table, new_size, varname);
2350 if ( Temp_table.ptr == NULL ) {
2351 return( dberr(S_NOMEMORY) );
2353 byteset(&Temp_table.ptr[old_size], 0, new_size - old_size);
2356 bytecpy(Temp_table.ptr, table, old_size);
2361 *Table = Temp_table;
2362 return( db_status );
2364 /* vpp -nOS2 -dUNIX -nBSD -nVANILLA_BSD -nVMS -nMEMLOCK -nWINDOWS -nFAR_ALLOC -f/usr/users/master/config/nonwin dblfcns.c */