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 */
177 DB_TASK Currtask = {POINTER_ASSIGN((TASK FAR *)&db_global), POINTER_ASSIGN((char FAR *)NULL)};
180 extern CHAR_P Dbpgbuff; /* allocated by dio_init used by o_update */
181 extern LOOKUP_ENTRY_P Db_lookup; /* database page lookup table */
182 extern PAGE_ENTRY_P Dbpg_table; /* database page table */
183 extern LOOKUP_ENTRY_P Ix_lookup; /* index page lookup table */
184 extern PAGE_ENTRY_P Ixpg_table; /* index page table */
185 extern INT_P Used_files;
189 #define lsn (db_global.Lsn)
191 BOOLEAN trcommit = FALSE;
192 int db_txtest = 0; /* transaction commit failure testing flag */
194 #define FL_LIST_ACCESS(ld_ptr) (FILE_NO *)(ld_ptr)->fl_list.ptr
195 #define FL_LIST_DEACCESS(ld_ptr) /**/
200 static char type[5]; /* open type (s or x) */
206 /* transaction activity file info */
207 extern INT taf_count;
208 extern char taf_files[TAFLIMIT][FILENMLEN];
212 /* Internal function prototypes */
214 static void pr_lock_descr(P1(struct lock_descr FAR *) Pi(int)
215 Pi(CONST char FAR *));
216 static int process_lock(P1(struct lock_descr FAR *) Pi(char));
217 static int keep_locks(P1(struct lock_descr FAR *));
218 static int free_files(P1(struct lock_descr FAR *));
220 static int bld_lock_tables(P0);
221 static int initses(P0);
222 static int lock_files(P1(int) Pi(LOCK_REQUEST FAR *));
223 static int send_lock(P0);
224 static int send_free(P0);
225 static void reset_locks(P0);
226 static int recovery_check(P0);
232 /* Set the number of lock request retries
234 d_retries(num TASK_PARM)
238 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_NONE));
243 RETURN( db_status = S_OKAY );
249 /* Set the lock request timeout value
251 d_timeout(secs TASK_PARM)
256 return(db_status = S_OKAY);
258 LM_SETTIME sto; /* send timeout packet */
260 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_ALL));
261 if ( !dbopen ) RETURN( dberr(S_DBOPEN) );
266 if ( nw_send(lsn, (MESSAGE FAR *)&sto, sizeof(LM_SETTIME)) )
270 RETURN( db_status = S_OKAY );
276 /* Open db_VISTA database
278 d_open(dbnames, opentype TASK_PARM)
279 CONST char FAR *dbnames;
280 CONST char FAR *opentype;
283 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_ALL));
285 if (debugging_dopen) {
286 puts (__FILE__"265 d_open");
291 if ( dbopen ) d_close(TASK_ONLY);
295 switch ( *opentype ) {
299 if ( netbios_chk() == 0 )
300 RETURN( dberr( S_NONETBIOS ) );
303 strcpy(type, opentype);
312 RETURN( dberr(S_BADTYPE) );
320 #ifdef MIKER /**@@@***/
322 /* initialize the country table if "vista.ctb" exists */
323 if ( ctb_init() != S_OKAY )
330 /* open transaction activity file */
331 if ( taf_open() != S_OKAY )
336 /* initialize multi-db tables */
337 if ( initdbt(dbnames) != S_OKAY ) RETURN( db_status );
339 /* read in schema tables */
340 if ( inittab() != S_OKAY ) RETURN( db_status );
343 if (debugging_dopen) {
344 puts(__FILE__"324 d_open calling renfiles");
348 if ( renfiles() != S_OKAY ) RETURN( db_status );
352 if ( db_lockmgr ) { /* [637] Only alloc file_refs for shared open */
353 /* Macro references must be on one line for some compilers */
354 if (ALLOC_TABLE(&db_global.File_refs, size_ft*sizeof(FILE_NO),old_size_ft*sizeof(FILE_NO), "file_refs")
360 if ( *type == 's' ) {
361 /* build application file lock tables */
362 if ( bld_lock_tables() != S_OKAY )
373 if ( initses() != S_OKAY ) {
378 } /* [713] perform external recovery in one-user mode */
380 if ( recovery_check() != S_OKAY ) RETURN(db_status);
384 /* [713] perform external recovery in single-user mode */
385 if ( recovery_check() != S_OKAY ) RETURN(db_status);
390 if ( o_setup() != S_OKAY ) RETURN( db_status );
395 if (debugging_dopen) {
396 printf(__FILE__"392 d_open before key_open. pgsz=%hd lrgst=%hd\n",
397 page_size,largest_page);
401 if ( key_open() == S_OKAY ) {
402 if ( dio_init() == S_OKAY ) {
408 if (debugging_dopen) {
409 printf(__FILE__"404 d_open after dio_init. pgsz=%hd lrgst=%hd\n",
410 page_size,largest_page);
418 /* Initialize a task structure
423 byteset(tsk, '\0', sizeof(TASK));
429 tsk->Dbwait_time = 1;
430 tsk->Db_timeout = TIMEOUT_DEF;
434 tsk->Dboptions = DCHAINUSE | TRLOGGING;
436 tsk->Dboptions = DCHAINUSE;
442 /* Initialize multiple database table entries
445 CONST char FAR *dbnames;
447 register int dbt_lc; /* loop control */
448 char dbfile [DtSrFILENMLEN];
456 /* compute number of databases to be opened */
457 old_no_of_dbs = (( no_of_dbs == 1 ) ? 0 : no_of_dbs);
458 for ( cp = dbnames; *cp; ++cp )
459 if ( *cp == ';' ) ++no_of_dbs;
461 if (debugging_dopen) {
462 printf(__FILE__"457 initdbt: new#dbs=%d\n", (int)no_of_dbs);
467 /* Now make sure there are the right # of elements in dbd/dbfpath */
469 if (get_element(dbdpath,no_of_dbs-1) == NULL) /* Not enuf? */
470 return( dberr(S_BADBDPATH) );
471 if (strrchr(dbdpath,';') != NULL) /* Is dbdpath single element */
472 if (get_element(dbdpath,no_of_dbs) != NULL) /* Too many? */
473 return( dberr(S_BADBDPATH) );
476 if (get_element(dbfpath,no_of_dbs-1) == NULL) /* Not enuf? */
477 return( dberr(S_BADBFPATH) );
478 if (strrchr(dbfpath,';') != NULL) { /* Is dbfpath single element */
479 if (get_element(dbfpath,no_of_dbs) != NULL) /* Too many? */
480 return( dberr(S_BADBFPATH) );
484 /* allocate db_table space */
485 /* Macro references must be on one line for some compilers */
486 if ((ALLOC_TABLE(&db_global.Db_table, no_of_dbs*sizeof(DB_ENTRY),
487 old_no_of_dbs*sizeof(DB_ENTRY), "db_table") != S_OKAY) ||
488 (ALLOC_TABLE(&db_global.Rn_table, no_of_dbs*sizeof(RN_ENTRY),
489 old_no_of_dbs*sizeof(RN_ENTRY), "rn_table") != S_OKAY)) {
493 /* initialize db_table entries */
494 for (dbt_lc = no_of_dbs, cp = dbnames,
495 curr_db_table = &db_table[old_no_of_dbs];
497 ++cp, ++curr_db_table) {
498 /* extract database name */
499 for ( i = 0; *cp && *cp != ';'; ++cp, ++i )
503 strcpy(dbfile, dbnames);
505 if ( (ptr = strrchr(dbfile, DIRCHAR)) == NULL )
506 ptr = strrchr(dbfile, ':');
508 if ( strlen(ptr+1) >= DBNMLEN ) RETURN( dberr(S_NAMELEN) );
509 strcpy(DB_REF(db_name), ptr+1);
511 if ( strlen(dbfile) >= PATHLEN ) RETURN( dberr(S_NAMELEN) );
512 strcpy(DB_REF(db_path), dbfile);
515 strcpy(DB_REF(db_path), "");
516 strcpy(DB_REF(db_name), dbfile);
521 return( db_status = S_OKAY );
527 /* Check for possible recovery
529 static recovery_check()
534 register int tn; /* transaction number */
535 register int tc; /* transaction count */
540 /* open tr activity file */
541 if ( taf_access() == S_OKAY ) {
545 if (taf_count != 0) {
546 if (d_recover(taf_files[0] CURRTASK_PARM) != S_OKAY)
552 if ( tc = taf_count ) {
553 /* perform recovery on each file */
554 for ( tn = 0; tn < tc; ++tn ) {
555 if ( d_recover(taf_files[0] CURRTASK_PARM) != S_OKAY ) return( db_status );
566 /* tell lock manager that we're done */
567 trend_pkt.fcn = L_RECDONE;
568 if ( nw_send(lsn, (MESSAGE FAR *)&trend_pkt, sizeof(LM_TREND)) )
580 /* Initial lock manager session
584 LM_DBOPEN_P Send_pkt;
585 LR_DBOPEN_P Recv_pkt;
586 register int ft_lc; /* loop control */
588 int send_size, recv_size, recvd_sz;
591 register FILE_ENTRY FAR *file_ptr;
592 FILE_NO FAR *fref_ptr;
593 INT FAR *rcv_fref_ptr;
595 if ( (net_status=nw_addnm(dbuserid, (int *)NULL) ) != N_OKAY )
596 if ( net_status == N_DUPNAME ) {
597 /* It is okay to reuse this name, but first be sure that all
598 sessions are hung up.
600 nw_cleanup(dbuserid);
605 if ( nw_call("lockmgr", dbuserid, &lsn) ) {
608 db_timeout = TIMEOUT_DEF; /* reset default timeout value */
612 /* This section of code MUST be identical to else (DOS) below */
614 for (ft_lc = size_ft - old_size_ft, file_ptr = &file_table[old_size_ft];
615 --ft_lc >= 0; ++file_ptr)
616 send_size += strlen(file_ptr->ft_name) + 1;
617 send_size += sizeof(LM_DBOPEN);
618 send_size += send_size % 2;
620 send_size = sizeof(LM_DBOPEN) + (size_ft-1)*sizeof(LM_FILEID);
622 send_pkt = (LM_DBOPEN FAR *)ALLOC(&Send_pkt, send_size, "send_pkt");
623 recv_size = sizeof(LR_DBOPEN) + (size_ft-1)*sizeof(INT);
624 recv_pkt = (LR_DBOPEN FAR *)ALLOC(&Recv_pkt, recv_size, "recv_pkt");
625 if (send_pkt == NULL || recv_pkt == NULL) {
627 return(dberr(S_NOMEMORY));
630 send_pkt->fcn = L_DBOPEN;
631 send_pkt->nfiles = size_ft;
632 send_pkt->type = type[0];
633 for (ft_lc = size_ft - old_size_ft, file_ptr = &file_table[old_size_ft],
634 fi_ptr = send_pkt->fnames;
636 --ft_lc >= 0; fi_ptr += strlen(file_ptr->ft_name)+1,++file_ptr) {
638 --ft_lc >= 0; ++fi_ptr,++file_ptr) {
640 if (stat(file_ptr->ft_name, &stbuf) == -1) {
642 return(dberr(S_NOFILE));
645 fi_ptr->inode = stbuf.st_ino;
646 fi_ptr->device = stbuf.st_dev;
648 strcpy(fi_ptr,file_ptr->ft_name);
652 if (nw_send(lsn, (MESSAGE FAR *)send_pkt, send_size) ||
653 nw_rcvmsg(lsn, (MESSAGE FAR *)recv_pkt, recv_size, &recvd_sz)) {
658 if ( recv_pkt->status == L_RECOVER ) {
659 /* perform auto-recovery */
660 d_recover( (CONST char FAR *)recv_pkt->logfile CURRTASK_PARM );
662 /* tell lock mgr we're done */
663 trend_pkt.fcn = L_RECDONE;
664 if ( nw_send(lsn, (MESSAGE FAR *)&trend_pkt, sizeof(LM_TREND)) ) {
668 /* re-issue open request */
671 if ( recv_pkt->fcn != L_DBOPEN ) {
673 return(dberr(S_NETSYNC));
675 if ( recv_pkt->status != L_OKAY ) {
682 MEM_UNLOCK(&Send_pkt);
684 MEM_UNLOCK(&Recv_pkt);
687 return(db_status = S_UNAVAIL);
689 if ( recv_pkt->nusers == 1 )
690 if ( recovery_check() != S_OKAY ) {
695 /* [656] perform initialization if not general lockmgr */
697 for (ft_lc = size_ft - old_size_ft, fref_ptr = &file_refs[old_size_ft],
698 rcv_fref_ptr = recv_pkt->frefs;
699 --ft_lc >= 0; ++fref_ptr, ++rcv_fref_ptr) {
700 *fref_ptr = *rcv_fref_ptr;
703 MEM_UNLOCK(&Send_pkt);
705 MEM_UNLOCK(&Recv_pkt);
708 session_active = TRUE;
709 return(db_status = S_OKAY);
714 /* Build application file lock tables
716 static int bld_lock_tables()
719 register int fd_lc; /* loop control */
720 register int st_lc; /* loop control */
722 #define file_used File_used.ptr
727 struct lock_descr FAR *ld_ptr;
728 RECORD_ENTRY FAR *rec_ptr;
729 FIELD_ENTRY FAR *fld_ptr;
730 SET_ENTRY FAR *set_ptr;
731 MEMBER_ENTRY FAR *mem_ptr;
732 register int FAR *fu_ptr;
738 old_size = old_size_ft*sizeof(int);
739 new_size = size_ft*sizeof(int);
740 File_used.ptr = NULL;
741 /* Macro references must be on one line for some compilers */
742 if ((ALLOC_TABLE(&db_global.App_locks, new_size, old_size, "app_locks")
744 (ALLOC_TABLE(&db_global.Excl_locks, new_size, old_size, "excl_locks")
746 (ALLOC_TABLE(&db_global.Kept_locks, new_size, old_size, "kept_locks")
748 (ALLOC_TABLE(&File_used, new_size, old_size, "file_used")
753 old_size = old_size_rt * sizeof(struct lock_descr);
754 new_size = size_rt * sizeof(struct lock_descr);
755 if ((ALLOC_TABLE(&db_global.Rec_locks, new_size, old_size, "rec_locks")
761 new_size = size_st * sizeof(struct lock_descr);
762 old_size = old_size_st * sizeof(struct lock_descr);
763 /* Macro references must be on one line for some compilers */
764 if (ALLOC_TABLE(&db_global.Set_locks, new_size, old_size, "set_locks")
770 /* build rec_locks table */
771 for (rec = old_size_rt, rec_ptr = &record_table[old_size_rt],
774 ++rec, ++rec_ptr, ++ld_ptr) {
775 ld_ptr->fl_type = 'f';
776 ld_ptr->fl_prev = 'f'; /*[367] init to free */
777 ld_ptr->fl_kept = FALSE;
779 /* put record's data file in list */
780 file_used[rec_ptr->rt_file] = TRUE;
782 /* add any key files to list */
783 fl_cnt = 1; /* count of used files */
784 for (fd_lc = size_fd - rec_ptr->rt_fields,
785 fld_ptr = &field_table[rec_ptr->rt_fields];
786 (--fd_lc >= 0) && (fld_ptr->fd_rec == rec);
788 if ( fld_ptr->fd_key != NOKEY ) {
789 fu_ptr = &file_used[fld_ptr->fd_keyfile];
796 ld_ptr->fl_cnt = fl_cnt;
797 ld_ptr->fl_list.ptr =
798 /* Macro references must be on one line for some compilers */
799 (FILE_NO FAR *)ALLOC(&ld_ptr->fl_list, fl_cnt*sizeof(FILE_NO), db_avname);
800 if ( ld_ptr->fl_list.ptr == NULL ) return( dberr(S_NOMEMORY) );
801 fl_ptr = ld_ptr->fl_list.ptr;
802 for (i = 0, fu_ptr = file_used; i < size_ft; ++i, ++fu_ptr) {
808 FL_LIST_DEACCESS(ld_ptr);
810 /* build set_locks table */
812 for (st_lc = size_st - old_size_st, set_ptr = &set_table[old_size_st],
814 --st_lc >= 0; ++set_ptr, ++ld_ptr) {
815 /* add owner's data file */
816 file_used[record_table[set_ptr->st_own_rt].rt_file] = TRUE;
817 ld_ptr->fl_type = 'f';
818 ld_ptr->fl_prev = 'f'; /*[367] init to free */
819 ld_ptr->fl_kept = FALSE;
821 /* add member record data files to list */
822 fl_cnt = 1; /* count of used files */
823 for (mem = set_ptr->st_members, memtot = mem + set_ptr->st_memtot,
824 mem_ptr = &member_table[mem];
827 fu_ptr = &file_used[record_table[mem_ptr->mt_record].rt_file];
833 ld_ptr->fl_cnt = fl_cnt;
834 ld_ptr->fl_list.ptr =
835 /* Macro references must be on one line for some compilers */
836 (FILE_NO FAR *)ALLOC(&ld_ptr->fl_list, fl_cnt*sizeof(FILE_NO), db_avname);
837 if ( ld_ptr->fl_list.ptr == NULL ) return( dberr(S_NOMEMORY) );
838 fl_ptr = ld_ptr->fl_list.ptr;
839 for (i = 0, fu_ptr = file_used; i < size_ft; ++i, ++fu_ptr) {
845 FL_LIST_DEACCESS(ld_ptr);
848 /* build key_locks table */
850 old_keyl_cnt = keyl_cnt;
851 for (fd_lc = size_fd - old_size_fd, fld_ptr = &field_table[old_size_fd];
852 --fd_lc >= 0; ++fld_ptr) {
853 /* count number of keys */
854 if (fld_ptr->fd_key != NOKEY)
858 old_size = old_keyl_cnt*sizeof(struct lock_descr);
859 new_size = keyl_cnt*sizeof(struct lock_descr);
860 /* Macro references must be on one line for some compilers */
861 if (ALLOC_TABLE(&db_global.Key_locks, new_size, old_size, "key_locks")
865 for (fd_lc = size_fd - old_size_fd, fld_ptr = &field_table[old_size_fd],
867 --fd_lc >= 0; ++fld_ptr) {
868 if (fld_ptr->fd_key != NOKEY) {
869 ld_ptr->fl_type = 'f';
870 ld_ptr->fl_prev = 'f'; /*[367] init to free */
871 ld_ptr->fl_kept = FALSE;
873 ld_ptr->fl_list.ptr = (FILE_NO FAR *)ALLOC(&ld_ptr->fl_list, ld_ptr->fl_cnt*sizeof(FILE_NO), "fl_list");
874 if ( ld_ptr->fl_list.ptr == NULL ) return( dberr(S_NOMEMORY) );
875 *(ld_ptr->fl_list.ptr) = fld_ptr->fd_keyfile;
876 FL_LIST_DEACCESS(ld_ptr);
881 lp_size = sizeof(LM_LOCK) + (size_ft-1)*sizeof(LM_LOCKREQ);
882 fp_size = sizeof(LM_FREE) + (size_ft-1)*sizeof(INT);
883 lock_pkt = (LM_LOCK FAR *)ALLOC(&db_global.Lock_pkt, lp_size, "lock_pkt");
884 free_pkt = (LM_FREE FAR *)ALLOC(&db_global.Free_pkt, fp_size, "free_pkt");
885 if ( !lock_pkt || !free_pkt ) return( dberr(S_NOMEMORY) );
886 lock_pkt->fcn = L_LOCK;
887 free_pkt->fcn = L_FREE;
888 MEM_UNLOCK(&File_used);
892 return( db_status = S_OKAY );
897 /****************************************/
901 /****************************************/
909 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_ALL));
914 /* in case they forgot to end the transaction */
916 d_trabort(TASK_ONLY);
924 for (i = 0; i < size_ft; ++i) {
925 /* close all files */
929 #ifdef MIKER /**@@@***/
931 /* free the country table */
932 if ( db_global.ctbl_activ )
943 d_freeall(TASK_ONLY);
946 if ( use_ovfl ) o_free();
971 session_active = FALSE;
991 bytecpy(task.v.ptr, &db_global, sizeof(TASK));
1000 /* Terminate lock manager session
1004 LM_DBCLOSE_P Send_pkt;
1005 register int ft_lc; /* loop control */
1007 register FILE_NO FAR *fref_ptr;
1008 register INT FAR *snd_fref_ptr;
1010 if ( session_active ) {
1011 send_size = sizeof(LM_DBCLOSE) + (size_ft-1)*sizeof(INT);
1012 send_pkt = (LM_DBCLOSE FAR *)ALLOC(&Send_pkt, send_size, "send_pkt");
1013 if ( send_pkt == NULL ) return( dberr(S_NOMEMORY) );
1014 send_pkt->fcn = L_DBCLOSE;
1015 send_pkt->nfiles = size_ft;
1016 for (ft_lc = size_ft, fref_ptr = file_refs,
1017 snd_fref_ptr = send_pkt->frefs;
1018 --ft_lc >= 0; ++fref_ptr, ++snd_fref_ptr)
1019 *snd_fref_ptr = *fref_ptr;
1020 if ( nw_send(lsn, (MESSAGE FAR *)send_pkt, send_size) )
1025 MEM_UNLOCK(&Send_pkt);
1027 MEM_UNLOCK(&db_global.File_refs);
1028 FREE(&db_global.File_refs);
1029 session_active = FALSE;
1031 return( db_status = S_OKAY );
1037 /* Free all allocated memory upon termination
1043 register struct lock_descr FAR *ld_ptr;
1046 /* free all allocated memory */
1048 MEM_UNLOCK(&db_global.Curr_mem);
1049 FREE(&db_global.Curr_mem);
1052 MEM_UNLOCK(&db_global.Curr_own);
1053 FREE(&db_global.Curr_own);
1055 #ifndef NO_TIMESTAMP
1057 MEM_UNLOCK(&db_global.Co_time);
1058 FREE(&db_global.Co_time);
1061 MEM_UNLOCK(&db_global.Cm_time);
1062 FREE(&db_global.Cm_time);
1065 MEM_UNLOCK(&db_global.Cs_time);
1066 FREE(&db_global.Cs_time);
1070 MEM_UNLOCK(&db_global.Sort_table);
1071 FREE(&db_global.Sort_table);
1073 if ( member_table ) {
1074 MEM_UNLOCK(&db_global.Member_table);
1075 FREE(&db_global.Member_table);
1078 MEM_UNLOCK(&db_global.Set_table);
1079 FREE(&db_global.Set_table);
1081 if ( field_table ) {
1082 MEM_UNLOCK(&db_global.Field_table);
1083 FREE(&db_global.Field_table);
1086 MEM_UNLOCK(&db_global.Key_table);
1087 FREE(&db_global.Key_table);
1089 if ( record_table ) {
1090 MEM_UNLOCK(&db_global.Record_table);
1091 FREE(&db_global.Record_table);
1094 MEM_UNLOCK(&db_global.File_table);
1095 FREE(&db_global.File_table);
1099 MEM_UNLOCK(&db_global.App_locks);
1100 FREE(&db_global.App_locks);
1103 MEM_UNLOCK(&db_global.Excl_locks);
1104 FREE(&db_global.Excl_locks);
1107 MEM_UNLOCK(&db_global.Kept_locks);
1108 FREE(&db_global.Kept_locks);
1111 for (i = 0, ld_ptr = rec_locks; i < size_rt; ++i, ++ld_ptr) {
1112 MEM_UNLOCK(&ld_ptr->fl_list);
1113 FREE(&ld_ptr->fl_list);
1115 MEM_UNLOCK(&db_global.Rec_locks);
1116 FREE(&db_global.Rec_locks);
1119 for (i = 0, ld_ptr = set_locks; i < size_st; ++i, ++ld_ptr) {
1120 MEM_UNLOCK(&ld_ptr->fl_list);
1121 FREE(&ld_ptr->fl_list);
1123 MEM_UNLOCK(&db_global.Set_locks);
1124 FREE(&db_global.Set_locks);
1127 for (i = 0, ld_ptr = key_locks; i < keyl_cnt; ++i, ++ld_ptr) { /*[637]*/
1128 MEM_UNLOCK(&ld_ptr->fl_list);
1129 FREE(&ld_ptr->fl_list);
1131 MEM_UNLOCK(&db_global.Key_locks);
1132 FREE(&db_global.Key_locks);
1135 MEM_UNLOCK(&db_global.Lock_pkt);
1136 FREE(&db_global.Lock_pkt);
1139 MEM_UNLOCK(&db_global.Free_pkt);
1140 FREE(&db_global.Free_pkt);
1145 MEM_UNLOCK(&db_global.Db_table);
1146 FREE(&db_global.Db_table);
1149 MEM_UNLOCK(&db_global.Rn_table);
1150 FREE(&db_global.Rn_table);
1156 /* Establish record file locks
1158 d_reclock(rec, lock_type TASK_PARM DBN_PARM)
1160 char FAR *lock_type;
1165 return(db_status = S_OKAY);
1169 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1172 lr.type = *lock_type;
1174 RETURN( d_lock(1, &lr TASK_PARM DBN_PARM) );
1181 /* Establish set file locks
1183 d_setlock(set, lock_type TASK_PARM DBN_PARM)
1185 char FAR *lock_type;
1190 return (db_status = S_OKAY);
1194 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1197 lr.type = *lock_type;
1199 RETURN( d_lock(1, &lr TASK_PARM DBN_PARM) );
1207 d_keylock(key, lock_type TASK_PARM DBN_PARM)
1208 long key; /* field number of key */
1209 char FAR *lock_type;
1214 return (db_status = S_OKAY);
1218 RECORD_ENTRY FAR *rec_ptr;
1219 FIELD_ENTRY FAR *fld_ptr;
1221 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1223 if (nfld_check(key, &rec, &fld, (RECORD_ENTRY FAR * FAR *)&rec_ptr, (FIELD_ENTRY FAR * FAR *)&fld_ptr) != S_OKAY)
1224 RETURN( db_status );
1226 if (fld_ptr->fd_key == NOKEY)
1227 RETURN( dberr(S_NOTKEY) );
1229 /* KEYMARK allows 'fld' to be recognized as a key file. It is already
1230 adjusted (in nfld_check) to INTernal format. Don't play with it in
1231 d_lock and lock_files.
1233 lr.item = fld + KEYMARK;
1234 lr.type = *lock_type;
1236 RETURN( d_lock(1, &lr TASK_PARM DBN_PARM) );
1242 /* Return lock status for record type
1244 d_reclstat(rec, lstat TASK_PARM DBN_PARM)
1252 return( db_status = S_OKAY );
1254 RECORD_ENTRY FAR *rec_ptr;
1256 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_NOIO));
1258 if (nrec_check(rec, &rec, (RECORD_ENTRY FAR * FAR *)&rec_ptr) != S_OKAY)
1259 RETURN( db_status );
1264 if (rec_ptr->rt_flags & STATIC)
1267 *lstat = rec_locks[rec].fl_type;
1269 RETURN( db_status = S_OKAY );
1275 /* Return lock status for set type
1277 d_setlstat(set, lstat TASK_PARM DBN_PARM)
1285 return (db_status = S_OKAY);
1287 SET_ENTRY FAR *set_ptr;
1289 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_NOIO));
1291 if (nset_check(set, &set, (SET_ENTRY FAR * FAR *)&set_ptr) != S_OKAY)
1292 RETURN( db_status );
1297 *lstat = set_locks[set].fl_type;
1299 RETURN( db_status = S_OKAY );
1305 /* Return lock status for key type
1307 d_keylstat(key, lstat TASK_PARM DBN_PARM)
1315 return (db_status = S_OKAY);
1318 RECORD_ENTRY FAR *rec_ptr;
1319 FIELD_ENTRY FAR *fld_ptr;
1321 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_NOIO));
1323 if (nfld_check(key, &rec, &fld, (RECORD_ENTRY FAR * FAR *)&rec_ptr, (FIELD_ENTRY FAR * FAR *)&fld_ptr) != S_OKAY)
1324 RETURN( db_status );
1326 if (fld_ptr->fd_key == NOKEY)
1327 RETURN( dberr(S_NOTKEY) );
1332 if ( file_table[fld_ptr->fd_keyfile].ft_flags & STATIC )
1335 *lstat = key_locks[fld_ptr->fd_keyno].fl_type;
1337 RETURN( db_status = S_OKAY );
1343 /* Lock a group of records and/or sets
1345 d_lock(count, lrpkt TASK_PARM DBN_PARM)
1347 LOCK_REQUEST FAR *lrpkt;
1352 return (db_status = S_OKAY);
1356 register LOCK_REQUEST FAR *lrpkt_ptr;
1357 struct lock_descr FAR *ld_ptr;
1359 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1362 RETURN( db_status = S_OKAY );
1364 lock_pkt->nfiles = 0;
1365 for (i = 0, lrpkt_ptr = lrpkt;
1366 (db_status == S_OKAY) && (i < count);
1368 if ( lrpkt_ptr->item >= KEYMARK ) {
1369 /* do not adjust lrpkt->item (see comment in d_keylock) */
1370 item = field_table[lrpkt_ptr->item - KEYMARK].fd_keyno;
1371 process_lock(&key_locks[item], lrpkt_ptr->type);
1373 else if ( lrpkt_ptr->item >= SETMARK ) {
1374 item = NUM2INT(lrpkt_ptr->item - SETMARK, st_offset);
1375 process_lock(&set_locks[item], lrpkt_ptr->type);
1377 else if ( lrpkt_ptr->item >= RECMARK ) {
1378 item = NUM2INT(lrpkt_ptr->item - RECMARK, rt_offset);
1379 if ( record_table[item].rt_flags & STATIC )
1382 process_lock(&rec_locks[item], lrpkt_ptr->type);
1387 if ( db_status == S_OKAY )
1388 lock_files(count, lrpkt);
1390 if ( db_status != S_OKAY ) {
1391 /* reset lock descriptor tables to previous state */
1392 for (i = 0, lrpkt_ptr = lrpkt; i < count; ++i, ++lrpkt_ptr) {
1393 /* do not adjust lrpkt->item (see comment in d_keylock) */
1394 if ( lrpkt_ptr->item >= KEYMARK ) {
1395 item = field_table[lrpkt_ptr->item - KEYMARK].fd_keyno;
1396 ld_ptr = &key_locks[item];
1398 else if ( lrpkt_ptr->item >= SETMARK ) {
1399 item = NUM2INT(lrpkt_ptr->item - SETMARK, st_offset);
1400 ld_ptr = &set_locks[item];
1402 else if ( lrpkt_ptr->item >= RECMARK ) {
1403 item = NUM2INT(lrpkt_ptr->item - RECMARK, rt_offset);
1404 ld_ptr = &rec_locks[item];
1408 ld_ptr->fl_type = ld_ptr->fl_prev;
1411 RETURN( db_status );
1418 /* Process set/record lock
1420 static process_lock(ld_ptr, type )
1421 struct lock_descr FAR *ld_ptr;
1424 register int fl_lc; /* loop control */
1427 register LM_LOCKREQ FAR *lockreq_ptr;
1428 FILE_NO FAR *fl_ptr, fref;
1431 ld_ptr->fl_prev = ld_ptr->fl_type;
1435 dberr( S_TRNOTACT );
1436 else if ( ld_ptr->fl_prev == 'f' )
1437 dberr( S_NOTLOCKED );
1438 else if ( ld_ptr->fl_prev != 'x' )
1439 return( keep_locks(ld_ptr) );
1442 if( ld_ptr->fl_prev != 'f' )
1445 ld_ptr->fl_type = 'r';
1449 dberr( S_TRNOTACT );
1450 else if ( ld_ptr->fl_prev != 'f' && ld_ptr->fl_prev != 'r' )
1453 ld_ptr->fl_type = 'w';
1456 if ( ld_ptr->fl_prev != 'f' && ld_ptr->fl_prev != 'r' )
1459 ld_ptr->fl_type = 'x';
1464 if ( db_status == S_OKAY ) {
1465 /* build lock request packet */
1466 for (fl_lc = ld_ptr->fl_cnt, fl_ptr = FL_LIST_ACCESS(ld_ptr);
1467 --fl_lc >= 0; ++fl_ptr) {
1468 fref = file_refs[fno = *fl_ptr];
1469 for (i = 0, lockreq_ptr = lock_pkt->locks;
1470 (i < lock_pkt->nfiles) && (lockreq_ptr->fref != fref);
1472 ; /* null statement */
1474 if (i < lock_pkt->nfiles) {
1475 /* file already is in lock request packet */
1476 if ( lockreq_ptr->type == 'r' || ld_ptr->fl_type == 'x' )
1477 lockreq_ptr->type = ld_ptr->fl_type;
1479 else if ( !excl_locks[fno] && ( !app_locks[fno] ||
1480 (ld_ptr->fl_type == 'w' && app_locks[fno] > 0) ||
1481 (ld_ptr->fl_type == 'x') ) ) {
1482 /* add to lock request packet */
1484 lockreq_ptr->fref = fref;
1485 lockreq_ptr->type = ld_ptr->fl_type;
1488 FL_LIST_DEACCESS(ld_ptr);
1490 return( db_status );
1496 /* Lock database files
1498 static lock_files(count, lrpkt )
1500 LOCK_REQUEST FAR *lrpkt;
1503 register int fl_lc; /* loop control */
1504 struct lock_descr FAR *ld_ptr;
1508 LOCK_REQUEST FAR *lrpkt_ptr;
1509 int FAR *appl_ptr, FAR *excl_ptr;
1510 FILE_NO FAR *fl_ptr;
1512 lock_reply.status = L_OKAY;
1513 if ( lock_pkt->nfiles == 0 ) goto skip_send;
1515 if ( send_lock() != S_OKAY )
1516 return( db_status );
1519 switch ( lock_reply.status ) {
1521 /* update app_locks and excl_lock tables */
1522 for (l = 0, lrpkt_ptr = lrpkt; l < count; ++l, ++lrpkt_ptr) {
1523 if (lrpkt_ptr->type == 'k')
1524 continue; /* skip keep lock requests */
1525 /* process each record/set lock */
1526 /* do not adjust lrpkt->item (see comment in d_keylock) */
1527 if ( lrpkt_ptr->item >= KEYMARK ) {
1528 item = field_table[lrpkt_ptr->item - KEYMARK].fd_keyno;
1529 ld_ptr = &key_locks[item];
1531 else if ( lrpkt_ptr->item >= SETMARK ) {
1532 item = NUM2INT(lrpkt_ptr->item - SETMARK, st_offset);
1533 ld_ptr = &set_locks[item];
1536 item = NUM2INT(lrpkt_ptr->item - RECMARK, rt_offset);
1537 ld_ptr = &rec_locks[item];
1539 for (fl_lc = ld_ptr->fl_cnt, fl_ptr = FL_LIST_ACCESS(ld_ptr);
1540 --fl_lc >= 0; ++fl_ptr) {
1541 /* process each file for each record/set lock */
1543 appl_ptr = &app_locks[fno];
1544 excl_ptr = &excl_locks[fno];
1545 if ( !*appl_ptr && !*excl_ptr ) {
1546 /* clear file's pages from cache */
1549 if ( ld_ptr->fl_type == 'r' ) {
1550 if ( *appl_ptr >= 0 )
1551 /* increment if file free or read-locked */
1555 if ( ld_ptr->fl_type == 'w' )
1557 else if ( ld_ptr->fl_type == 'x' ) {
1559 if ( ld_ptr->fl_prev == 'r' ) {
1560 /* read to excl lock upgrade */
1566 FL_LIST_DEACCESS(ld_ptr);
1571 return( db_status = S_UNAVAIL );
1573 return( dberr(S_SYSERR) );
1577 return( db_status = S_OKAY );
1583 /* Send lock request
1585 static int send_lock()
1589 int send_size, recv_size;
1591 if ( lock_pkt->nfiles ) {
1592 /* send lock request */
1593 send_size = sizeof(LM_LOCK) + (lock_pkt->nfiles-1)*sizeof(LM_LOCKREQ);
1594 if ( send_size > lp_size )
1595 return( dberr(S_SYSERR) );
1599 printf("nw_send(lsn,lock_pkt->fcn=%ld,size=%d\n",lock_pkt->fcn,send_size);
1601 if ( nw_send(lsn, (MESSAGE FAR *)lock_pkt, send_size) )
1604 if ( nw_rcvmsg(lsn, (MESSAGE FAR *)&lock_reply, sizeof(LR_LOCK), &recv_size) )
1607 printf("nw_rcvmsg(lock_reply.fcn=%ld,lock_reply.status=%d\n",
1608 lock_reply.fcn,lock_reply.status);
1611 /* request must always be granted */
1612 if ( lock_reply.fcn != L_LOCK )
1613 return( dberr(S_NETSYNC) );
1615 if (lock_reply.status == L_RECOVER) {
1616 /* perform auto-recovery */
1617 d_recover(lock_reply.logfile CURRTASK_PARM);
1619 /* tell lock mgr we're done */
1620 trend_pkt.fcn = L_RECDONE;
1621 if (nw_send(lsn, (MESSAGE FAR *)&trend_pkt, sizeof(LM_TREND)))
1624 /* re-issue lock request */
1627 if (lock_reply.status == L_QUEUEFULL) {
1634 return( db_status = S_OKAY );
1642 d_keyfree(key TASK_PARM DBN_PARM)
1648 return (db_status = S_OKAY);
1651 RECORD_ENTRY FAR *rec_ptr;
1652 FIELD_ENTRY FAR *fld_ptr;
1653 struct lock_descr FAR *ld_ptr;
1655 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1657 if (nfld_check(key, &rec, &fld, (RECORD_ENTRY FAR * FAR *)&rec_ptr, (FIELD_ENTRY FAR * FAR *)&fld_ptr) != S_OKAY)
1658 RETURN( db_status );
1660 if ( fld_ptr->fd_key == NOKEY )
1661 RETURN( dberr(S_NOTKEY) );
1663 if ( dbopen >= 2 ) /* exclusive access needs no locks */
1664 RETURN( db_status = S_OKAY );
1666 ld_ptr = &key_locks[fld_ptr->fd_keyno];
1668 RETURN( dberr(S_TRFREE) );
1670 if ( ld_ptr->fl_type == 'f' )
1671 RETURN( dberr(S_NOTLOCKED) );
1674 ld_ptr->fl_type = 'f';
1676 RETURN( db_status );
1683 /* Setup table to keep locks after transaction end
1685 static keep_locks( ld_ptr )
1686 struct lock_descr FAR *ld_ptr; /* Lock descriptor */
1688 register int fl_lc; /* loop control */
1689 register FILE_NO FAR *fl_ptr;
1691 /* Mark lock as kept */
1692 ld_ptr->fl_kept = TRUE;
1694 for (fl_lc = ld_ptr->fl_cnt, fl_ptr = FL_LIST_ACCESS(ld_ptr);
1695 --fl_lc >= 0; ++fl_ptr)
1696 ++kept_locks[*fl_ptr];
1697 FL_LIST_DEACCESS(ld_ptr);
1699 return( db_status = S_OKAY );
1706 d_recfree(rec TASK_PARM DBN_PARM)
1712 return (db_status = S_OKAY);
1714 RECORD_ENTRY FAR *rec_ptr;
1715 struct lock_descr FAR *ld_ptr;
1717 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1719 if (nrec_check(rec, &rec, (RECORD_ENTRY FAR * FAR *)&rec_ptr) != S_OKAY)
1720 RETURN( db_status );
1722 if ( dbopen >= 2 ) /* exclusive access needs no locks */
1723 RETURN( db_status = S_OKAY );
1725 ld_ptr = &rec_locks[rec];
1728 RETURN( dberr(S_TRFREE) );
1730 if ( ld_ptr->fl_type == 'f' )
1731 RETURN( dberr(S_NOTLOCKED) );
1734 ld_ptr->fl_type = 'f';
1736 RETURN( db_status );
1744 d_setfree(set TASK_PARM DBN_PARM)
1750 return (db_status = S_OKAY);
1752 SET_ENTRY FAR *set_ptr;
1753 struct lock_descr FAR *ld_ptr;
1755 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1757 if (nset_check(set, &set, (SET_ENTRY FAR * FAR *)&set_ptr) != S_OKAY)
1758 RETURN( db_status );
1760 if ( dbopen >= 2 ) /* exclusive access needs no locks */
1761 RETURN( db_status = S_OKAY );
1763 ld_ptr = &set_locks[set];
1766 RETURN( dberr(S_TRFREE) );
1768 if ( ld_ptr->fl_type == 'f' )
1769 RETURN( dberr(S_NOTLOCKED) );
1772 ld_ptr->fl_type = 'f';
1774 RETURN( db_status );
1782 /* Free read-locked files associated with record or set
1784 static int free_files(ld_ptr)
1785 struct lock_descr FAR *ld_ptr;
1787 register int fl_lc; /* loop control */
1789 LM_LOCKREQ FAR *lockreq_ptr;
1792 register FILE_NO FAR *fl_ptr;
1794 /* fill free packet */
1795 lock_pkt->nfiles = free_pkt->nfiles = 0;
1796 for (fl_lc = ld_ptr->fl_cnt, fl_ptr = FL_LIST_ACCESS(ld_ptr);
1797 --fl_lc >= 0; ++fl_ptr) {
1799 appl_ptr = &app_locks[fno];
1800 fref = file_refs[fno];
1801 if ( ld_ptr->fl_type == 'r' && *appl_ptr > 0 ) {
1802 /* free read lock */
1803 if ( --*appl_ptr == 0 && excl_locks[fno] == 0 ) {
1804 free_pkt->frefs[free_pkt->nfiles++] = fref;
1805 /* reset key scan position */
1806 if ( file_table[fno].ft_type == 'k' )
1810 else if ( --excl_locks[fno] == 0 ) {
1811 /* free exclusive access lock */
1812 if ( *appl_ptr > 0 ) {
1813 /* downgrade to read-lock */
1814 lockreq_ptr = &lock_pkt->locks[lock_pkt->nfiles++];
1815 lockreq_ptr->type = 'r';
1816 lockreq_ptr->fref = fref;
1819 /* free excl-lock */
1820 free_pkt->frefs[free_pkt->nfiles++] = fref;
1822 /* reset key scan position */
1823 if ( file_table[fno].ft_type == 'k' )
1827 if ( ld_ptr->fl_kept ) {
1828 /* Remove hold on lock */
1829 if ( --kept_locks[fno] < 0 ) return( dberr(S_BADLOCKS) );
1830 ld_ptr->fl_kept = FALSE;
1833 FL_LIST_DEACCESS(ld_ptr);
1834 /* send any downgrades */
1835 if ( send_lock() == S_OKAY ) {
1836 /* free any files */
1839 return( db_status );
1844 /* free all locked files
1846 d_freeall(TASK_ONLY)
1850 return (db_status = S_OKAY);
1853 register FILE_NO FAR *fref_ptr;
1854 register int FAR *appl_ptr;
1856 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
1858 if ( ! dbopen ) RETURN( dberr(S_DBOPEN) );
1860 if ( dbopen >= 2 ) /* exclusive access needs no locks */
1861 RETURN( db_status = S_OKAY );
1863 if ( trans_id ) RETURN( dberr(S_TRFREE) );
1865 free_pkt->nfiles = 0;
1866 for (i = 0, fref_ptr = file_refs, appl_ptr = app_locks;
1868 ++i, ++fref_ptr, ++appl_ptr) {
1872 free_pkt->frefs[free_pkt->nfiles++] = *fref_ptr;
1875 /* send free files packet */
1876 if ( send_free() != S_OKAY )
1877 RETURN( db_status );
1879 /* reset all lock descriptors */
1882 /* reset all key file positions */
1885 /* Clear cache pages and return */
1886 RETURN( dio_clear() );
1893 /* Reset lock descriptor tables
1895 static void reset_locks()
1899 register struct lock_descr FAR *ld_ptr;
1901 /* reset record lock descriptors */
1904 for (i = beg, ld_ptr = &rec_locks[i]; i < end; ++i, ++ld_ptr) {
1905 if ( ld_ptr->fl_kept ) {
1906 ld_ptr->fl_type = 'r';
1907 ld_ptr->fl_kept = FALSE;
1909 else if ( ld_ptr->fl_type != 'x' )
1910 ld_ptr->fl_type = 'f';
1912 /* reset set lock descriptors */
1915 for (i = beg, ld_ptr = &set_locks[i]; i < end; ++i, ++ld_ptr) {
1916 if ( ld_ptr->fl_kept ) {
1917 ld_ptr->fl_type = 'r';
1918 ld_ptr->fl_kept = FALSE;
1920 else if ( ld_ptr->fl_type != 'x' )
1921 ld_ptr->fl_type = 'f';
1923 /* reset key lock descriptors */
1926 for (i = beg, ld_ptr = &key_locks[i]; i < end; ++i, ++ld_ptr) {
1927 if ( ld_ptr->fl_kept ) {
1928 ld_ptr->fl_type = 'r';
1929 ld_ptr->fl_kept = FALSE;
1931 else if ( ld_ptr->fl_type != 'x' )
1932 ld_ptr->fl_type = 'f';
1938 /* Send free files packet
1940 static int send_free()
1945 /* send any free packets */
1946 if ( free_pkt->nfiles ) {
1947 send_size = sizeof(LM_FREE) + (free_pkt->nfiles-1)*sizeof(INT);
1948 if ( send_size > fp_size )
1949 return ( dberr(S_SYSERR) );
1951 if ( nw_send(lsn, (MESSAGE FAR *)free_pkt, send_size) )
1955 return( db_status = S_OKAY );
1961 /*------------------------------------------------------------------------
1962 Record Lock Bit Functions
1963 ------------------------------------------------------------------------*/
1965 /* Set record lock bit of current record
1976 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
1978 if ( ! curr_rec ) RETURN( dberr(S_NOCR) );
1981 file = NUM2INT((FILE_NO)((curr_rec >> FILESHIFT) & FILEMASK), ft_offset);
1984 (record_lock = (app_locks[file] >= 0 && !excl_locks[file])) ) {
1985 /* request record-lock on file */
1986 lock_pkt->nfiles = 1;
1987 lock_pkt->locks[0].type = 'R';
1988 lock_pkt->locks[0].fref = file_refs[file];
1989 if ( send_lock() != S_OKAY ) RETURN( db_status );
1990 if ( lock_reply.status != L_OKAY )
1991 RETURN( db_status = S_UNAVAIL );
1993 if ( dio_rrlb(curr_rec, &rid) != S_OKAY )
1994 RETURN( db_status );
1995 if ( rid & RLBMASK )
1996 rlb_status = S_LOCKED;
1999 rlb_status = dio_wrlb(curr_rec, rid);
2001 if ( dbopen == 1 && record_lock ) {
2002 /* free or downgrade record-lock on file */
2003 if ( app_locks[file] ) {
2004 lock_pkt->nfiles = 1;
2005 lock_pkt->locks[0].type = 'r';
2006 lock_pkt->locks[0].fref = file_refs[file];
2007 if ( send_lock() != S_OKAY ) RETURN( db_status );
2010 free_pkt->nfiles = 1;
2011 free_pkt->frefs[0] = file_refs[file];
2012 if ( send_free() != S_OKAY ) RETURN( db_status );
2015 RETURN( db_status = rlb_status );
2017 RETURN( db_status = S_OKAY );
2023 /* Clear record lock bit of current record
2033 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
2035 if ( ! curr_rec ) RETURN( dberr(S_NOCR) );
2038 file = NUM2INT((FILE_NO)((curr_rec >> FILESHIFT) & FILEMASK), ft_offset);
2040 /* ensure that changes are allowed */
2041 if (dbopen == 1 && trans_id && app_locks[file] >= 0 && !excl_locks[file])
2042 RETURN( dberr(S_NOTLOCKED) );
2044 if ( dbopen == 1 && ! trans_id ) {
2045 /* request record-lock on file */
2046 lock_pkt->nfiles = 1;
2047 lock_pkt->locks[0].type = 'R';
2048 lock_pkt->locks[0].fref = file_refs[file];
2049 if ( send_lock() != S_OKAY ) RETURN( db_status );
2050 if ( lock_reply.status != L_OKAY )
2051 RETURN( db_status = S_UNAVAIL );
2055 if ( dio_rrlb(curr_rec, &rid) != S_OKAY )
2056 RETURN( db_status );
2060 rlb_status = S_UNLOCKED;
2061 dio_wrlb(curr_rec, rid);
2063 if ( dbopen == 1 && ! trans_id ) {
2064 /* free or downgrade record-lock on file */
2065 if ( app_locks[file] ) {
2066 lock_pkt->nfiles = 1;
2067 lock_pkt->locks[0].type = 'r';
2068 lock_pkt->locks[0].fref = file_refs[file];
2069 if ( send_lock() != S_OKAY ) RETURN( db_status );
2072 free_pkt->nfiles = 1;
2073 free_pkt->frefs[0] = file_refs[file];
2074 if ( send_free() != S_OKAY ) RETURN( db_status );
2080 RETURN( db_status );
2086 /* Test record lock bit of current record
2095 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
2097 if ( ! curr_rec ) RETURN( dberr(S_NOCR) );
2100 if ( dio_rrlb(curr_rec, &rid) != S_OKAY )
2101 RETURN( db_status );
2103 if ( rid & RLBMASK )
2104 db_status = S_LOCKED;
2106 db_status = S_UNLOCKED;
2108 RETURN( rlb_status = db_status );
2110 RETURN( db_status = S_UNLOCKED );
2119 /*------------------------------------------------------------------------
2120 Database Transaction Processing Functions
2121 ------------------------------------------------------------------------*/
2123 /* Begin transaction
2125 d_trbegin(tid TASK_PARM)
2126 CONST char FAR *tid;
2129 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
2133 if ( ! dbopen ) RETURN( dberr(S_DBOPEN) );
2135 if ( tid == NULL ) RETURN( dberr(S_TRANSID) );
2138 if ( trans_id ) RETURN( dberr(S_TRACTIVE) );
2140 /* changes were possible outside a transaction */
2147 RETURN( db_status );
2159 register int ft_lc; /* loop control */
2160 LM_TRCOMMIT trcom_pkt;
2162 LM_LOCKREQ FAR *lockreq_ptr;
2163 register FILE_NO FAR *fref_ptr;
2164 register int FAR *appl_ptr, FAR *keptl_ptr, FAR *excl_ptr;
2167 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
2170 if( ! trans_id ) RETURN( dberr(S_TRNOTACT) );
2173 /* mark start of trx in archive log file */
2176 /* flush data to database or overflow */
2177 if ( dio_flush() != S_OKAY ) RETURN( db_status );
2179 if ( (dboptions & TRLOGGING) && use_ovfl ) {
2180 /* End trx using overflow file */
2182 /* flush recovery data to overflow file */
2183 if ( o_flush() != S_OKAY ) RETURN( db_status );
2186 trcom_pkt.fcn = L_TRCOMMIT;
2187 strcpy(trcom_pkt.logfile, dblog);
2188 if ( nw_send(lsn, (MESSAGE FAR *)&trcom_pkt, sizeof(LM_TRCOMMIT)) )
2194 if ( taf_add(dblog) != S_OKAY ) RETURN( db_status ); /* after nw_send */
2197 /* allow for user interrupt to test recovery */
2198 if ( db_txtest ) dberr(S_DEBUG);
2201 /* update db from overflow file */
2202 if ( o_update() != S_OKAY ) RETURN( db_status );
2205 /* flush modified cache data to database */
2206 if ( dio_flush() != S_OKAY ) RETURN( db_status );
2209 if ( taf_del(dblog) != S_OKAY ) RETURN( db_status ); /* before nw_send */
2213 trend_pkt.fcn = L_TREND;
2214 if ( nw_send(lsn, (MESSAGE FAR *)&trend_pkt, sizeof(LM_TREND)) )
2220 /* mark end of trx in archive log file */
2224 o_init(); /*[305] clear cache_ovfl flag */
2227 if ( dbopen == 1 ) {
2228 /* free unkept, non-exclusive file locks */
2229 lock_pkt->nfiles = free_pkt->nfiles = 0;
2230 for (ft_lc = size_ft, fref_ptr = file_refs, appl_ptr = app_locks,
2231 keptl_ptr = kept_locks, excl_ptr = excl_locks;
2232 --ft_lc >= 0; ++fref_ptr, ++appl_ptr, ++keptl_ptr, ++excl_ptr) {
2234 *appl_ptr = *keptl_ptr;
2235 else if ( *appl_ptr == -1 ) {
2236 if ( (*appl_ptr = *keptl_ptr) > 0 ) {
2237 lockreq_ptr = &lock_pkt->locks[lock_pkt->nfiles++];
2238 lockreq_ptr->type = 'r';
2239 lockreq_ptr->fref = *fref_ptr;
2242 free_pkt->frefs[free_pkt->nfiles++] = *fref_ptr;
2244 else if ( *appl_ptr && (*appl_ptr = *keptl_ptr) == 0 )
2245 free_pkt->frefs[free_pkt->nfiles++] = *fref_ptr;
2248 /* send lock downgrade request */
2249 if ( send_lock() != S_OKAY || send_free() != S_OKAY )
2250 RETURN( db_status );
2252 /* clear lock descriptors */
2255 /* reset all key file positions */
2258 /* clear page buffers */
2262 RETURN( db_status );
2268 /* Abort transaction
2270 d_trabort(TASK_ONLY)
2274 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
2276 RETURN (dberr(S_TRNOTACT));
2278 dio_pzclr(); /*[425] clear page zero BEFORE dio_clear */
2279 dio_clear(); /*[353] clear cache */
2280 RETURN (db_status = S_OKAY);
2283 register int FAR *keptl_ptr;
2284 register struct lock_descr FAR *ld_ptr;
2286 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
2289 if ( ! trans_id ) RETURN( dberr(S_TRNOTACT) );
2291 if ( dbopen == 1 ) {
2292 /* Revert any kept locks to unkept status */
2293 for (i = 0, keptl_ptr = kept_locks; i < size_ft; ++i, ++keptl_ptr)
2295 for (i = 0, ld_ptr = rec_locks; i < size_rt; ++i, ++ld_ptr)
2296 ld_ptr->fl_kept = FALSE;
2297 for (i = 0, ld_ptr = set_locks; i < size_st; ++i, ++ld_ptr)
2298 ld_ptr->fl_kept = FALSE;
2299 for (i = 0, ld_ptr = key_locks; i < keyl_cnt; ++i, ++ld_ptr)
2300 ld_ptr->fl_kept = FALSE;
2303 o_init(); /*[305] clear cache_ovfl flag */
2305 dio_pzclr(); /*[425] clear page zero BEFORE d_freeall */
2306 if ( dbopen == 1 ) d_freeall(TASK_ONLY);
2309 RETURN( db_status = S_OKAY );
2315 /* Report a network error
2319 switch ( net_status ) {
2321 db_status = dberr( S_LMBUSY );
2324 db_status = dberr( S_NOLOCKMGR );
2327 db_status = dberr( S_DUPUSERID );
2330 db_status = dberr( S_NETERR );
2333 return( db_status );
2337 int alloc_table(Table, new_size, old_size )
2339 #define table Table->ptr
2345 Temp_table.ptr = ALLOC(&Temp_table, new_size, varname);
2346 if ( Temp_table.ptr == NULL ) {
2347 return( dberr(S_NOMEMORY) );
2349 byteset(&Temp_table.ptr[old_size], 0, new_size - old_size);
2352 bytecpy(Temp_table.ptr, table, old_size);
2357 *Table = Temp_table;
2358 return( db_status );
2360 /* vpp -nOS2 -dUNIX -nBSD -nVANILLA_BSD -nVMS -nMEMLOCK -nWINDOWS -nFAR_ALLOC -f/usr/users/master/config/nonwin dblfcns.c */