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 libraries 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 extern CHAR_P Dbpgbuff; /* allocated by dio_init used by o_update */
178 extern LOOKUP_ENTRY_P Db_lookup; /* database page lookup table */
179 extern PAGE_ENTRY_P Dbpg_table; /* database page table */
180 extern LOOKUP_ENTRY_P Ix_lookup; /* index page lookup table */
181 extern PAGE_ENTRY_P Ixpg_table; /* index page table */
182 extern INT_P Used_files;
186 #define lsn (db_global.Lsn)
188 BOOLEAN trcommit = FALSE;
189 int db_txtest = 0; /* transaction commit failure testing flag */
191 #define FL_LIST_ACCESS(ld_ptr) (FILE_NO *)(ld_ptr)->fl_list.ptr
192 #define FL_LIST_DEACCESS(ld_ptr) /**/
197 static char type[5]; /* open type (s or x) */
203 /* transaction activity file info */
204 extern INT taf_count;
205 extern char taf_files[TAFLIMIT][FILENMLEN];
209 /* Internal function prototypes */
211 static void pr_lock_descr(P1(struct lock_descr *) Pi(int)
213 static int process_lock(P1(struct lock_descr *) Pi(char));
214 static int keep_locks(P1(struct lock_descr *));
215 static int free_files(P1(struct lock_descr *));
217 static int bld_lock_tables(P0);
218 static int initses(P0);
219 static int lock_files(P1(int) Pi(LOCK_REQUEST *));
220 static int send_lock(P0);
221 static int send_free(P0);
222 static void reset_locks(P0);
223 static int recovery_check(P0);
229 /* Set the number of lock request retries
231 d_retries(num TASK_PARM)
235 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_NONE));
240 RETURN( db_status = S_OKAY );
246 /* Set the lock request timeout value
248 d_timeout(secs TASK_PARM)
253 return(db_status = S_OKAY);
255 LM_SETTIME sto; /* send timeout packet */
257 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_ALL));
258 if ( !dbopen ) RETURN( dberr(S_DBOPEN) );
263 if ( nw_send(lsn, (MESSAGE *)&sto, sizeof(LM_SETTIME)) )
267 RETURN( db_status = S_OKAY );
273 /* Open db_VISTA database
276 d_open(dbnames, opentype TASK_PARM)
278 const char *opentype;
281 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_ALL));
283 if (debugging_dopen) {
284 puts (__FILE__"265 d_open");
289 if ( dbopen ) d_close(TASK_ONLY);
293 switch ( *opentype ) {
297 if ( netbios_chk() == 0 )
298 RETURN( dberr( S_NONETBIOS ) );
301 strcpy(type, opentype);
310 RETURN( dberr(S_BADTYPE) );
318 #ifdef MIKER /**@@@***/
320 /* initialize the country table if "vista.ctb" exists */
321 if ( ctb_init() != S_OKAY )
328 /* open transaction activity file */
329 if ( taf_open() != S_OKAY )
334 /* initialize multi-db tables */
335 if ( initdbt(dbnames) != S_OKAY ) RETURN( db_status );
337 /* read in schema tables */
338 if ( inittab() != S_OKAY ) RETURN( db_status );
341 if (debugging_dopen) {
342 puts(__FILE__"324 d_open calling renfiles");
346 if ( renfiles() != S_OKAY ) RETURN( db_status );
350 if ( db_lockmgr ) { /* [637] Only alloc file_refs for shared open */
351 /* Macro references must be on one line for some compilers */
352 if (ALLOC_TABLE(&db_global.File_refs, size_ft*sizeof(FILE_NO),old_size_ft*sizeof(FILE_NO), "file_refs")
358 if ( *type == 's' ) {
359 /* build application file lock tables */
360 if ( bld_lock_tables() != S_OKAY )
371 if ( initses() != S_OKAY ) {
376 } /* [713] perform external recovery in one-user mode */
378 if ( recovery_check() != S_OKAY ) RETURN(db_status);
382 /* [713] perform external recovery in single-user mode */
383 if ( recovery_check() != S_OKAY ) RETURN(db_status);
388 if ( o_setup() != S_OKAY ) RETURN( db_status );
393 if (debugging_dopen) {
394 printf(__FILE__"392 d_open before key_open. pgsz=%hd lrgst=%hd\n",
395 page_size,largest_page);
399 if ( key_open() == S_OKAY ) {
400 if ( dio_init() == S_OKAY ) {
406 if (debugging_dopen) {
407 printf(__FILE__"404 d_open after dio_init. pgsz=%hd lrgst=%hd\n",
408 page_size,largest_page);
416 /* Initialize a task structure
421 byteset(tsk, '\0', sizeof(TASK));
427 tsk->Dbwait_time = 1;
428 tsk->Db_timeout = TIMEOUT_DEF;
432 tsk->Dboptions = DCHAINUSE | TRLOGGING;
434 tsk->Dboptions = DCHAINUSE;
440 /* Initialize multiple database table entries
446 int dbt_lc; /* loop control */
447 char dbfile [DtSrFILENMLEN];
455 /* compute number of databases to be opened */
456 old_no_of_dbs = (( no_of_dbs == 1 ) ? 0 : no_of_dbs);
457 for ( cp = dbnames; *cp; ++cp )
458 if ( *cp == ';' ) ++no_of_dbs;
460 if (debugging_dopen) {
461 printf(__FILE__"457 initdbt: new#dbs=%d\n", (int)no_of_dbs);
466 /* Now make sure there are the right # of elements in dbd/dbfpath */
468 if (get_element(dbdpath,no_of_dbs-1) == NULL) /* Not enuf? */
469 return( dberr(S_BADBDPATH) );
470 if (strrchr(dbdpath,';') != NULL) /* Is dbdpath single element */
471 if (get_element(dbdpath,no_of_dbs) != NULL) /* Too many? */
472 return( dberr(S_BADBDPATH) );
475 if (get_element(dbfpath,no_of_dbs-1) == NULL) /* Not enuf? */
476 return( dberr(S_BADBFPATH) );
477 if (strrchr(dbfpath,';') != NULL) { /* Is dbfpath single element */
478 if (get_element(dbfpath,no_of_dbs) != NULL) /* Too many? */
479 return( dberr(S_BADBFPATH) );
483 /* allocate db_table space */
484 /* Macro references must be on one line for some compilers */
485 if ((ALLOC_TABLE(&db_global.Db_table, no_of_dbs*sizeof(DB_ENTRY),
486 old_no_of_dbs*sizeof(DB_ENTRY), "db_table") != S_OKAY) ||
487 (ALLOC_TABLE(&db_global.Rn_table, no_of_dbs*sizeof(RN_ENTRY),
488 old_no_of_dbs*sizeof(RN_ENTRY), "rn_table") != S_OKAY)) {
492 /* initialize db_table entries */
493 for (dbt_lc = no_of_dbs, cp = dbnames,
494 curr_db_table = &db_table[old_no_of_dbs];
496 ++cp, ++curr_db_table) {
497 /* extract database name */
498 for ( i = 0; *cp && *cp != ';'; ++cp, ++i )
502 strcpy(dbfile, dbnames);
504 if ( (ptr = strrchr(dbfile, DIRCHAR)) == NULL )
505 ptr = strrchr(dbfile, ':');
507 if ( strlen(ptr+1) >= DBNMLEN ) RETURN( dberr(S_NAMELEN) );
508 strcpy(DB_REF(db_name), ptr+1);
510 if ( strlen(dbfile) >= PATHLEN ) RETURN( dberr(S_NAMELEN) );
511 strcpy(DB_REF(db_path), dbfile);
514 strcpy(DB_REF(db_path), "");
515 strcpy(DB_REF(db_name), dbfile);
520 return( db_status = S_OKAY );
526 /* Check for possible recovery
528 static recovery_check()
533 int tn; /* transaction number */
534 int tc; /* transaction count */
539 /* open tr activity file */
540 if ( taf_access() == S_OKAY ) {
544 if (taf_count != 0) {
545 if (d_recover(taf_files[0] CURRTASK_PARM) != S_OKAY)
551 if ( tc = taf_count ) {
552 /* perform recovery on each file */
553 for ( tn = 0; tn < tc; ++tn ) {
554 if ( d_recover(taf_files[0] CURRTASK_PARM) != S_OKAY ) return( db_status );
565 /* tell lock manager that we're done */
566 trend_pkt.fcn = L_RECDONE;
567 if ( nw_send(lsn, (MESSAGE *)&trend_pkt, sizeof(LM_TREND)) )
579 /* Initial lock manager session
583 LM_DBOPEN_P Send_pkt;
584 LR_DBOPEN_P Recv_pkt;
585 int ft_lc; /* loop control */
587 int send_size, recv_size, recvd_sz;
590 FILE_ENTRY *file_ptr;
594 if ( (net_status=nw_addnm(dbuserid, (int *)NULL) ) != N_OKAY )
595 if ( net_status == N_DUPNAME ) {
596 /* It is okay to reuse this name, but first be sure that all
597 sessions are hung up.
599 nw_cleanup(dbuserid);
604 if ( nw_call("lockmgr", dbuserid, &lsn) ) {
607 db_timeout = TIMEOUT_DEF; /* reset default timeout value */
611 /* This section of code MUST be identical to else (DOS) below */
613 for (ft_lc = size_ft - old_size_ft, file_ptr = &file_table[old_size_ft];
614 --ft_lc >= 0; ++file_ptr)
615 send_size += strlen(file_ptr->ft_name) + 1;
616 send_size += sizeof(LM_DBOPEN);
617 send_size += send_size % 2;
619 send_size = sizeof(LM_DBOPEN) + (size_ft-1)*sizeof(LM_FILEID);
621 send_pkt = (LM_DBOPEN *)ALLOC(&Send_pkt, send_size, "send_pkt");
622 recv_size = sizeof(LR_DBOPEN) + (size_ft-1)*sizeof(INT);
623 recv_pkt = (LR_DBOPEN *)ALLOC(&Recv_pkt, recv_size, "recv_pkt");
624 if (send_pkt == NULL || recv_pkt == NULL) {
626 return(dberr(S_NOMEMORY));
629 send_pkt->fcn = L_DBOPEN;
630 send_pkt->nfiles = size_ft;
631 send_pkt->type = type[0];
632 for (ft_lc = size_ft - old_size_ft, file_ptr = &file_table[old_size_ft],
633 fi_ptr = send_pkt->fnames;
635 --ft_lc >= 0; fi_ptr += strlen(file_ptr->ft_name)+1,++file_ptr) {
637 --ft_lc >= 0; ++fi_ptr,++file_ptr) {
639 if (stat(file_ptr->ft_name, &stbuf) == -1) {
641 return(dberr(S_NOFILE));
644 fi_ptr->inode = stbuf.st_ino;
645 fi_ptr->device = stbuf.st_dev;
647 strcpy(fi_ptr,file_ptr->ft_name);
651 if (nw_send(lsn, (MESSAGE *)send_pkt, send_size) ||
652 nw_rcvmsg(lsn, (MESSAGE *)recv_pkt, recv_size, &recvd_sz)) {
657 if ( recv_pkt->status == L_RECOVER ) {
658 /* perform auto-recovery */
659 d_recover( (const char *)recv_pkt->logfile CURRTASK_PARM );
661 /* tell lock mgr we're done */
662 trend_pkt.fcn = L_RECDONE;
663 if ( nw_send(lsn, (MESSAGE *)&trend_pkt, sizeof(LM_TREND)) ) {
667 /* re-issue open request */
670 if ( recv_pkt->fcn != L_DBOPEN ) {
672 return(dberr(S_NETSYNC));
674 if ( recv_pkt->status != L_OKAY ) {
681 MEM_UNLOCK(&Send_pkt);
683 MEM_UNLOCK(&Recv_pkt);
686 return(db_status = S_UNAVAIL);
688 if ( recv_pkt->nusers == 1 )
689 if ( recovery_check() != S_OKAY ) {
694 /* [656] perform initialization if not general lockmgr */
696 for (ft_lc = size_ft - old_size_ft, fref_ptr = &file_refs[old_size_ft],
697 rcv_fref_ptr = recv_pkt->frefs;
698 --ft_lc >= 0; ++fref_ptr, ++rcv_fref_ptr) {
699 *fref_ptr = *rcv_fref_ptr;
702 MEM_UNLOCK(&Send_pkt);
704 MEM_UNLOCK(&Recv_pkt);
707 session_active = TRUE;
708 return(db_status = S_OKAY);
713 /* Build application file lock tables
715 static int bld_lock_tables()
718 int fd_lc; /* loop control */
719 int st_lc; /* loop control */
721 #define file_used File_used.ptr
726 struct lock_descr *ld_ptr;
727 RECORD_ENTRY *rec_ptr;
728 FIELD_ENTRY *fld_ptr;
730 MEMBER_ENTRY *mem_ptr;
737 old_size = old_size_ft*sizeof(int);
738 new_size = size_ft*sizeof(int);
739 File_used.ptr = NULL;
740 /* Macro references must be on one line for some compilers */
741 if ((ALLOC_TABLE(&db_global.App_locks, new_size, old_size, "app_locks")
743 (ALLOC_TABLE(&db_global.Excl_locks, new_size, old_size, "excl_locks")
745 (ALLOC_TABLE(&db_global.Kept_locks, new_size, old_size, "kept_locks")
747 (ALLOC_TABLE(&File_used, new_size, old_size, "file_used")
752 old_size = old_size_rt * sizeof(struct lock_descr);
753 new_size = size_rt * sizeof(struct lock_descr);
754 if ((ALLOC_TABLE(&db_global.Rec_locks, new_size, old_size, "rec_locks")
760 new_size = size_st * sizeof(struct lock_descr);
761 old_size = old_size_st * sizeof(struct lock_descr);
762 /* Macro references must be on one line for some compilers */
763 if (ALLOC_TABLE(&db_global.Set_locks, new_size, old_size, "set_locks")
769 /* build rec_locks table */
770 for (rec = old_size_rt, rec_ptr = &record_table[old_size_rt],
773 ++rec, ++rec_ptr, ++ld_ptr) {
774 ld_ptr->fl_type = 'f';
775 ld_ptr->fl_prev = 'f'; /*[367] init to free */
776 ld_ptr->fl_kept = FALSE;
778 /* put record's data file in list */
779 file_used[rec_ptr->rt_file] = TRUE;
781 /* add any key files to list */
782 fl_cnt = 1; /* count of used files */
783 for (fd_lc = size_fd - rec_ptr->rt_fields,
784 fld_ptr = &field_table[rec_ptr->rt_fields];
785 (--fd_lc >= 0) && (fld_ptr->fd_rec == rec);
787 if ( fld_ptr->fd_key != NOKEY ) {
788 fu_ptr = &file_used[fld_ptr->fd_keyfile];
795 ld_ptr->fl_cnt = fl_cnt;
796 ld_ptr->fl_list.ptr =
797 /* Macro references must be on one line for some compilers */
798 (FILE_NO *)ALLOC(&ld_ptr->fl_list, fl_cnt*sizeof(FILE_NO), db_avname);
799 if ( ld_ptr->fl_list.ptr == NULL ) return( dberr(S_NOMEMORY) );
800 fl_ptr = ld_ptr->fl_list.ptr;
801 for (i = 0, fu_ptr = file_used; i < size_ft; ++i, ++fu_ptr) {
807 FL_LIST_DEACCESS(ld_ptr);
809 /* build set_locks table */
811 for (st_lc = size_st - old_size_st, set_ptr = &set_table[old_size_st],
813 --st_lc >= 0; ++set_ptr, ++ld_ptr) {
814 /* add owner's data file */
815 file_used[record_table[set_ptr->st_own_rt].rt_file] = TRUE;
816 ld_ptr->fl_type = 'f';
817 ld_ptr->fl_prev = 'f'; /*[367] init to free */
818 ld_ptr->fl_kept = FALSE;
820 /* add member record data files to list */
821 fl_cnt = 1; /* count of used files */
822 for (mem = set_ptr->st_members, memtot = mem + set_ptr->st_memtot,
823 mem_ptr = &member_table[mem];
826 fu_ptr = &file_used[record_table[mem_ptr->mt_record].rt_file];
832 ld_ptr->fl_cnt = fl_cnt;
833 ld_ptr->fl_list.ptr =
834 /* Macro references must be on one line for some compilers */
835 (FILE_NO *)ALLOC(&ld_ptr->fl_list, fl_cnt*sizeof(FILE_NO), db_avname);
836 if ( ld_ptr->fl_list.ptr == NULL ) return( dberr(S_NOMEMORY) );
837 fl_ptr = ld_ptr->fl_list.ptr;
838 for (i = 0, fu_ptr = file_used; i < size_ft; ++i, ++fu_ptr) {
844 FL_LIST_DEACCESS(ld_ptr);
847 /* build key_locks table */
849 old_keyl_cnt = keyl_cnt;
850 for (fd_lc = size_fd - old_size_fd, fld_ptr = &field_table[old_size_fd];
851 --fd_lc >= 0; ++fld_ptr) {
852 /* count number of keys */
853 if (fld_ptr->fd_key != NOKEY)
857 old_size = old_keyl_cnt*sizeof(struct lock_descr);
858 new_size = keyl_cnt*sizeof(struct lock_descr);
859 /* Macro references must be on one line for some compilers */
860 if (ALLOC_TABLE(&db_global.Key_locks, new_size, old_size, "key_locks")
864 for (fd_lc = size_fd - old_size_fd, fld_ptr = &field_table[old_size_fd],
866 --fd_lc >= 0; ++fld_ptr) {
867 if (fld_ptr->fd_key != NOKEY) {
868 ld_ptr->fl_type = 'f';
869 ld_ptr->fl_prev = 'f'; /*[367] init to free */
870 ld_ptr->fl_kept = FALSE;
872 ld_ptr->fl_list.ptr = (FILE_NO *)ALLOC(&ld_ptr->fl_list, ld_ptr->fl_cnt*sizeof(FILE_NO), "fl_list");
873 if ( ld_ptr->fl_list.ptr == NULL ) return( dberr(S_NOMEMORY) );
874 *(ld_ptr->fl_list.ptr) = fld_ptr->fd_keyfile;
875 FL_LIST_DEACCESS(ld_ptr);
880 lp_size = sizeof(LM_LOCK) + (size_ft-1)*sizeof(LM_LOCKREQ);
881 fp_size = sizeof(LM_FREE) + (size_ft-1)*sizeof(INT);
882 lock_pkt = (LM_LOCK *)ALLOC(&db_global.Lock_pkt, lp_size, "lock_pkt");
883 free_pkt = (LM_FREE *)ALLOC(&db_global.Free_pkt, fp_size, "free_pkt");
884 if ( !lock_pkt || !free_pkt ) return( dberr(S_NOMEMORY) );
885 lock_pkt->fcn = L_LOCK;
886 free_pkt->fcn = L_FREE;
887 MEM_UNLOCK(&File_used);
891 return( db_status = S_OKAY );
896 /****************************************/
900 /****************************************/
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;
997 /* Terminate lock manager session
1001 LM_DBCLOSE_P Send_pkt;
1002 int ft_lc; /* loop control */
1007 if ( session_active ) {
1008 send_size = sizeof(LM_DBCLOSE) + (size_ft-1)*sizeof(INT);
1009 send_pkt = (LM_DBCLOSE *)ALLOC(&Send_pkt, send_size, "send_pkt");
1010 if ( send_pkt == NULL ) return( dberr(S_NOMEMORY) );
1011 send_pkt->fcn = L_DBCLOSE;
1012 send_pkt->nfiles = size_ft;
1013 for (ft_lc = size_ft, fref_ptr = file_refs,
1014 snd_fref_ptr = send_pkt->frefs;
1015 --ft_lc >= 0; ++fref_ptr, ++snd_fref_ptr)
1016 *snd_fref_ptr = *fref_ptr;
1017 if ( nw_send(lsn, (MESSAGE *)send_pkt, send_size) )
1022 MEM_UNLOCK(&Send_pkt);
1024 MEM_UNLOCK(&db_global.File_refs);
1025 FREE(&db_global.File_refs);
1026 session_active = FALSE;
1028 return( db_status = S_OKAY );
1034 /* Free all allocated memory upon termination
1040 struct lock_descr *ld_ptr;
1043 /* free all allocated memory */
1045 MEM_UNLOCK(&db_global.Curr_mem);
1046 FREE(&db_global.Curr_mem);
1049 MEM_UNLOCK(&db_global.Curr_own);
1050 FREE(&db_global.Curr_own);
1052 #ifndef NO_TIMESTAMP
1054 MEM_UNLOCK(&db_global.Co_time);
1055 FREE(&db_global.Co_time);
1058 MEM_UNLOCK(&db_global.Cm_time);
1059 FREE(&db_global.Cm_time);
1062 MEM_UNLOCK(&db_global.Cs_time);
1063 FREE(&db_global.Cs_time);
1067 MEM_UNLOCK(&db_global.Sort_table);
1068 FREE(&db_global.Sort_table);
1070 if ( member_table ) {
1071 MEM_UNLOCK(&db_global.Member_table);
1072 FREE(&db_global.Member_table);
1075 MEM_UNLOCK(&db_global.Set_table);
1076 FREE(&db_global.Set_table);
1078 if ( field_table ) {
1079 MEM_UNLOCK(&db_global.Field_table);
1080 FREE(&db_global.Field_table);
1083 MEM_UNLOCK(&db_global.Key_table);
1084 FREE(&db_global.Key_table);
1086 if ( record_table ) {
1087 MEM_UNLOCK(&db_global.Record_table);
1088 FREE(&db_global.Record_table);
1091 MEM_UNLOCK(&db_global.File_table);
1092 FREE(&db_global.File_table);
1096 MEM_UNLOCK(&db_global.App_locks);
1097 FREE(&db_global.App_locks);
1100 MEM_UNLOCK(&db_global.Excl_locks);
1101 FREE(&db_global.Excl_locks);
1104 MEM_UNLOCK(&db_global.Kept_locks);
1105 FREE(&db_global.Kept_locks);
1108 for (i = 0, ld_ptr = rec_locks; i < size_rt; ++i, ++ld_ptr) {
1109 MEM_UNLOCK(&ld_ptr->fl_list);
1110 FREE(&ld_ptr->fl_list);
1112 MEM_UNLOCK(&db_global.Rec_locks);
1113 FREE(&db_global.Rec_locks);
1116 for (i = 0, ld_ptr = set_locks; i < size_st; ++i, ++ld_ptr) {
1117 MEM_UNLOCK(&ld_ptr->fl_list);
1118 FREE(&ld_ptr->fl_list);
1120 MEM_UNLOCK(&db_global.Set_locks);
1121 FREE(&db_global.Set_locks);
1124 for (i = 0, ld_ptr = key_locks; i < keyl_cnt; ++i, ++ld_ptr) { /*[637]*/
1125 MEM_UNLOCK(&ld_ptr->fl_list);
1126 FREE(&ld_ptr->fl_list);
1128 MEM_UNLOCK(&db_global.Key_locks);
1129 FREE(&db_global.Key_locks);
1132 MEM_UNLOCK(&db_global.Lock_pkt);
1133 FREE(&db_global.Lock_pkt);
1136 MEM_UNLOCK(&db_global.Free_pkt);
1137 FREE(&db_global.Free_pkt);
1142 MEM_UNLOCK(&db_global.Db_table);
1143 FREE(&db_global.Db_table);
1146 MEM_UNLOCK(&db_global.Rn_table);
1147 FREE(&db_global.Rn_table);
1153 /* Establish record file locks
1155 d_reclock(rec, lock_type TASK_PARM DBN_PARM)
1162 return(db_status = S_OKAY);
1166 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1169 lr.type = *lock_type;
1171 RETURN( d_lock(1, &lr TASK_PARM DBN_PARM) );
1178 /* Establish set file locks
1180 d_setlock(set, lock_type TASK_PARM DBN_PARM)
1187 return (db_status = S_OKAY);
1191 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1194 lr.type = *lock_type;
1196 RETURN( d_lock(1, &lr TASK_PARM DBN_PARM) );
1204 d_keylock(key, lock_type TASK_PARM DBN_PARM)
1205 long key; /* field number of key */
1211 return (db_status = S_OKAY);
1215 RECORD_ENTRY *rec_ptr;
1216 FIELD_ENTRY *fld_ptr;
1218 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1220 if (nfld_check(key, &rec, &fld, (RECORD_ENTRY * *)&rec_ptr, (FIELD_ENTRY * *)&fld_ptr) != S_OKAY)
1221 RETURN( db_status );
1223 if (fld_ptr->fd_key == NOKEY)
1224 RETURN( dberr(S_NOTKEY) );
1226 /* KEYMARK allows 'fld' to be recognized as a key file. It is already
1227 adjusted (in nfld_check) to INTernal format. Don't play with it in
1228 d_lock and lock_files.
1230 lr.item = fld + KEYMARK;
1231 lr.type = *lock_type;
1233 RETURN( d_lock(1, &lr TASK_PARM DBN_PARM) );
1239 /* Return lock status for record type
1241 d_reclstat(rec, lstat TASK_PARM DBN_PARM)
1249 return( db_status = S_OKAY );
1251 RECORD_ENTRY *rec_ptr;
1253 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_NOIO));
1255 if (nrec_check(rec, &rec, (RECORD_ENTRY * *)&rec_ptr) != S_OKAY)
1256 RETURN( db_status );
1261 if (rec_ptr->rt_flags & STATIC)
1264 *lstat = rec_locks[rec].fl_type;
1266 RETURN( db_status = S_OKAY );
1272 /* Return lock status for set type
1274 d_setlstat(set, lstat TASK_PARM DBN_PARM)
1282 return (db_status = S_OKAY);
1286 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_NOIO));
1288 if (nset_check(set, &set, (SET_ENTRY * *)&set_ptr) != S_OKAY)
1289 RETURN( db_status );
1294 *lstat = set_locks[set].fl_type;
1296 RETURN( db_status = S_OKAY );
1302 /* Return lock status for key type
1304 d_keylstat(key, lstat TASK_PARM DBN_PARM)
1312 return (db_status = S_OKAY);
1315 RECORD_ENTRY *rec_ptr;
1316 FIELD_ENTRY *fld_ptr;
1318 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_NOIO));
1320 if (nfld_check(key, &rec, &fld, (RECORD_ENTRY * *)&rec_ptr, (FIELD_ENTRY * *)&fld_ptr) != S_OKAY)
1321 RETURN( db_status );
1323 if (fld_ptr->fd_key == NOKEY)
1324 RETURN( dberr(S_NOTKEY) );
1329 if ( file_table[fld_ptr->fd_keyfile].ft_flags & STATIC )
1332 *lstat = key_locks[fld_ptr->fd_keyno].fl_type;
1334 RETURN( db_status = S_OKAY );
1340 /* Lock a group of records and/or sets
1342 d_lock(count, lrpkt TASK_PARM DBN_PARM)
1344 LOCK_REQUEST *lrpkt;
1349 return (db_status = S_OKAY);
1353 LOCK_REQUEST *lrpkt_ptr;
1354 struct lock_descr *ld_ptr;
1356 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1359 RETURN( db_status = S_OKAY );
1361 lock_pkt->nfiles = 0;
1362 for (i = 0, lrpkt_ptr = lrpkt;
1363 (db_status == S_OKAY) && (i < count);
1365 if ( lrpkt_ptr->item >= KEYMARK ) {
1366 /* do not adjust lrpkt->item (see comment in d_keylock) */
1367 item = field_table[lrpkt_ptr->item - KEYMARK].fd_keyno;
1368 process_lock(&key_locks[item], lrpkt_ptr->type);
1370 else if ( lrpkt_ptr->item >= SETMARK ) {
1371 item = NUM2INT(lrpkt_ptr->item - SETMARK, st_offset);
1372 process_lock(&set_locks[item], lrpkt_ptr->type);
1374 else if ( lrpkt_ptr->item >= RECMARK ) {
1375 item = NUM2INT(lrpkt_ptr->item - RECMARK, rt_offset);
1376 if ( record_table[item].rt_flags & STATIC )
1379 process_lock(&rec_locks[item], lrpkt_ptr->type);
1384 if ( db_status == S_OKAY )
1385 lock_files(count, lrpkt);
1387 if ( db_status != S_OKAY ) {
1388 /* reset lock descriptor tables to previous state */
1389 for (i = 0, lrpkt_ptr = lrpkt; i < count; ++i, ++lrpkt_ptr) {
1390 /* do not adjust lrpkt->item (see comment in d_keylock) */
1391 if ( lrpkt_ptr->item >= KEYMARK ) {
1392 item = field_table[lrpkt_ptr->item - KEYMARK].fd_keyno;
1393 ld_ptr = &key_locks[item];
1395 else if ( lrpkt_ptr->item >= SETMARK ) {
1396 item = NUM2INT(lrpkt_ptr->item - SETMARK, st_offset);
1397 ld_ptr = &set_locks[item];
1399 else if ( lrpkt_ptr->item >= RECMARK ) {
1400 item = NUM2INT(lrpkt_ptr->item - RECMARK, rt_offset);
1401 ld_ptr = &rec_locks[item];
1405 ld_ptr->fl_type = ld_ptr->fl_prev;
1408 RETURN( db_status );
1415 /* Process set/record lock
1417 static process_lock(ld_ptr, type )
1418 struct lock_descr *ld_ptr;
1421 int fl_lc; /* loop control */
1424 LM_LOCKREQ *lockreq_ptr;
1425 FILE_NO *fl_ptr, fref;
1428 ld_ptr->fl_prev = ld_ptr->fl_type;
1432 dberr( S_TRNOTACT );
1433 else if ( ld_ptr->fl_prev == 'f' )
1434 dberr( S_NOTLOCKED );
1435 else if ( ld_ptr->fl_prev != 'x' )
1436 return( keep_locks(ld_ptr) );
1439 if( ld_ptr->fl_prev != 'f' )
1442 ld_ptr->fl_type = 'r';
1446 dberr( S_TRNOTACT );
1447 else if ( ld_ptr->fl_prev != 'f' && ld_ptr->fl_prev != 'r' )
1450 ld_ptr->fl_type = 'w';
1453 if ( ld_ptr->fl_prev != 'f' && ld_ptr->fl_prev != 'r' )
1456 ld_ptr->fl_type = 'x';
1461 if ( db_status == S_OKAY ) {
1462 /* build lock request packet */
1463 for (fl_lc = ld_ptr->fl_cnt, fl_ptr = FL_LIST_ACCESS(ld_ptr);
1464 --fl_lc >= 0; ++fl_ptr) {
1465 fref = file_refs[fno = *fl_ptr];
1466 for (i = 0, lockreq_ptr = lock_pkt->locks;
1467 (i < lock_pkt->nfiles) && (lockreq_ptr->fref != fref);
1469 ; /* null statement */
1471 if (i < lock_pkt->nfiles) {
1472 /* file already is in lock request packet */
1473 if ( lockreq_ptr->type == 'r' || ld_ptr->fl_type == 'x' )
1474 lockreq_ptr->type = ld_ptr->fl_type;
1476 else if ( !excl_locks[fno] && ( !app_locks[fno] ||
1477 (ld_ptr->fl_type == 'w' && app_locks[fno] > 0) ||
1478 (ld_ptr->fl_type == 'x') ) ) {
1479 /* add to lock request packet */
1481 lockreq_ptr->fref = fref;
1482 lockreq_ptr->type = ld_ptr->fl_type;
1485 FL_LIST_DEACCESS(ld_ptr);
1487 return( db_status );
1493 /* Lock database files
1495 static lock_files(count, lrpkt )
1497 LOCK_REQUEST *lrpkt;
1500 int fl_lc; /* loop control */
1501 struct lock_descr *ld_ptr;
1505 LOCK_REQUEST *lrpkt_ptr;
1506 int *appl_ptr, *excl_ptr;
1509 lock_reply.status = L_OKAY;
1510 if ( lock_pkt->nfiles == 0 ) goto skip_send;
1512 if ( send_lock() != S_OKAY )
1513 return( db_status );
1516 switch ( lock_reply.status ) {
1518 /* update app_locks and excl_lock tables */
1519 for (l = 0, lrpkt_ptr = lrpkt; l < count; ++l, ++lrpkt_ptr) {
1520 if (lrpkt_ptr->type == 'k')
1521 continue; /* skip keep lock requests */
1522 /* process each record/set lock */
1523 /* do not adjust lrpkt->item (see comment in d_keylock) */
1524 if ( lrpkt_ptr->item >= KEYMARK ) {
1525 item = field_table[lrpkt_ptr->item - KEYMARK].fd_keyno;
1526 ld_ptr = &key_locks[item];
1528 else if ( lrpkt_ptr->item >= SETMARK ) {
1529 item = NUM2INT(lrpkt_ptr->item - SETMARK, st_offset);
1530 ld_ptr = &set_locks[item];
1533 item = NUM2INT(lrpkt_ptr->item - RECMARK, rt_offset);
1534 ld_ptr = &rec_locks[item];
1536 for (fl_lc = ld_ptr->fl_cnt, fl_ptr = FL_LIST_ACCESS(ld_ptr);
1537 --fl_lc >= 0; ++fl_ptr) {
1538 /* process each file for each record/set lock */
1540 appl_ptr = &app_locks[fno];
1541 excl_ptr = &excl_locks[fno];
1542 if ( !*appl_ptr && !*excl_ptr ) {
1543 /* clear file's pages from cache */
1546 if ( ld_ptr->fl_type == 'r' ) {
1547 if ( *appl_ptr >= 0 )
1548 /* increment if file free or read-locked */
1552 if ( ld_ptr->fl_type == 'w' )
1554 else if ( ld_ptr->fl_type == 'x' ) {
1556 if ( ld_ptr->fl_prev == 'r' ) {
1557 /* read to excl lock upgrade */
1563 FL_LIST_DEACCESS(ld_ptr);
1568 return( db_status = S_UNAVAIL );
1570 return( dberr(S_SYSERR) );
1574 return( db_status = S_OKAY );
1580 /* Send lock request
1582 static int send_lock()
1586 int send_size, recv_size;
1588 if ( lock_pkt->nfiles ) {
1589 /* send lock request */
1590 send_size = sizeof(LM_LOCK) + (lock_pkt->nfiles-1)*sizeof(LM_LOCKREQ);
1591 if ( send_size > lp_size )
1592 return( dberr(S_SYSERR) );
1596 printf("nw_send(lsn,lock_pkt->fcn=%ld,size=%d\n",lock_pkt->fcn,send_size);
1598 if ( nw_send(lsn, (MESSAGE *)lock_pkt, send_size) )
1601 if ( nw_rcvmsg(lsn, (MESSAGE *)&lock_reply, sizeof(LR_LOCK), &recv_size) )
1604 printf("nw_rcvmsg(lock_reply.fcn=%ld,lock_reply.status=%d\n",
1605 lock_reply.fcn,lock_reply.status);
1608 /* request must always be granted */
1609 if ( lock_reply.fcn != L_LOCK )
1610 return( dberr(S_NETSYNC) );
1612 if (lock_reply.status == L_RECOVER) {
1613 /* perform auto-recovery */
1614 d_recover(lock_reply.logfile CURRTASK_PARM);
1616 /* tell lock mgr we're done */
1617 trend_pkt.fcn = L_RECDONE;
1618 if (nw_send(lsn, (MESSAGE *)&trend_pkt, sizeof(LM_TREND)))
1621 /* re-issue lock request */
1624 if (lock_reply.status == L_QUEUEFULL) {
1631 return( db_status = S_OKAY );
1639 d_keyfree(key TASK_PARM DBN_PARM)
1645 return (db_status = S_OKAY);
1648 RECORD_ENTRY *rec_ptr;
1649 FIELD_ENTRY *fld_ptr;
1650 struct lock_descr *ld_ptr;
1652 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1654 if (nfld_check(key, &rec, &fld, (RECORD_ENTRY * *)&rec_ptr, (FIELD_ENTRY * *)&fld_ptr) != S_OKAY)
1655 RETURN( db_status );
1657 if ( fld_ptr->fd_key == NOKEY )
1658 RETURN( dberr(S_NOTKEY) );
1660 if ( dbopen >= 2 ) /* exclusive access needs no locks */
1661 RETURN( db_status = S_OKAY );
1663 ld_ptr = &key_locks[fld_ptr->fd_keyno];
1665 RETURN( dberr(S_TRFREE) );
1667 if ( ld_ptr->fl_type == 'f' )
1668 RETURN( dberr(S_NOTLOCKED) );
1671 ld_ptr->fl_type = 'f';
1673 RETURN( db_status );
1680 /* Setup table to keep locks after transaction end
1682 static keep_locks( ld_ptr )
1683 struct lock_descr *ld_ptr; /* Lock descriptor */
1685 int fl_lc; /* loop control */
1688 /* Mark lock as kept */
1689 ld_ptr->fl_kept = TRUE;
1691 for (fl_lc = ld_ptr->fl_cnt, fl_ptr = FL_LIST_ACCESS(ld_ptr);
1692 --fl_lc >= 0; ++fl_ptr)
1693 ++kept_locks[*fl_ptr];
1694 FL_LIST_DEACCESS(ld_ptr);
1696 return( db_status = S_OKAY );
1703 d_recfree(rec TASK_PARM DBN_PARM)
1709 return (db_status = S_OKAY);
1711 RECORD_ENTRY *rec_ptr;
1712 struct lock_descr *ld_ptr;
1714 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1716 if (nrec_check(rec, &rec, (RECORD_ENTRY * *)&rec_ptr) != S_OKAY)
1717 RETURN( db_status );
1719 if ( dbopen >= 2 ) /* exclusive access needs no locks */
1720 RETURN( db_status = S_OKAY );
1722 ld_ptr = &rec_locks[rec];
1725 RETURN( dberr(S_TRFREE) );
1727 if ( ld_ptr->fl_type == 'f' )
1728 RETURN( dberr(S_NOTLOCKED) );
1731 ld_ptr->fl_type = 'f';
1733 RETURN( db_status );
1741 d_setfree(set TASK_PARM DBN_PARM)
1747 return (db_status = S_OKAY);
1750 struct lock_descr *ld_ptr;
1752 DB_ENTER(DB_ID TASK_ID LOCK_SET(LOCK_IO));
1754 if (nset_check(set, &set, (SET_ENTRY * *)&set_ptr) != S_OKAY)
1755 RETURN( db_status );
1757 if ( dbopen >= 2 ) /* exclusive access needs no locks */
1758 RETURN( db_status = S_OKAY );
1760 ld_ptr = &set_locks[set];
1763 RETURN( dberr(S_TRFREE) );
1765 if ( ld_ptr->fl_type == 'f' )
1766 RETURN( dberr(S_NOTLOCKED) );
1769 ld_ptr->fl_type = 'f';
1771 RETURN( db_status );
1779 /* Free read-locked files associated with record or set
1781 static int free_files(ld_ptr)
1782 struct lock_descr *ld_ptr;
1784 int fl_lc; /* loop control */
1786 LM_LOCKREQ *lockreq_ptr;
1791 /* fill free packet */
1792 lock_pkt->nfiles = free_pkt->nfiles = 0;
1793 for (fl_lc = ld_ptr->fl_cnt, fl_ptr = FL_LIST_ACCESS(ld_ptr);
1794 --fl_lc >= 0; ++fl_ptr) {
1796 appl_ptr = &app_locks[fno];
1797 fref = file_refs[fno];
1798 if ( ld_ptr->fl_type == 'r' && *appl_ptr > 0 ) {
1799 /* free read lock */
1800 if ( --*appl_ptr == 0 && excl_locks[fno] == 0 ) {
1801 free_pkt->frefs[free_pkt->nfiles++] = fref;
1802 /* reset key scan position */
1803 if ( file_table[fno].ft_type == 'k' )
1807 else if ( --excl_locks[fno] == 0 ) {
1808 /* free exclusive access lock */
1809 if ( *appl_ptr > 0 ) {
1810 /* downgrade to read-lock */
1811 lockreq_ptr = &lock_pkt->locks[lock_pkt->nfiles++];
1812 lockreq_ptr->type = 'r';
1813 lockreq_ptr->fref = fref;
1816 /* free excl-lock */
1817 free_pkt->frefs[free_pkt->nfiles++] = fref;
1819 /* reset key scan position */
1820 if ( file_table[fno].ft_type == 'k' )
1824 if ( ld_ptr->fl_kept ) {
1825 /* Remove hold on lock */
1826 if ( --kept_locks[fno] < 0 ) return( dberr(S_BADLOCKS) );
1827 ld_ptr->fl_kept = FALSE;
1830 FL_LIST_DEACCESS(ld_ptr);
1831 /* send any downgrades */
1832 if ( send_lock() == S_OKAY ) {
1833 /* free any files */
1836 return( db_status );
1841 /* free all locked files
1843 d_freeall(TASK_ONLY)
1847 return (db_status = S_OKAY);
1853 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
1855 if ( ! dbopen ) RETURN( dberr(S_DBOPEN) );
1857 if ( dbopen >= 2 ) /* exclusive access needs no locks */
1858 RETURN( db_status = S_OKAY );
1860 if ( trans_id ) RETURN( dberr(S_TRFREE) );
1862 free_pkt->nfiles = 0;
1863 for (i = 0, fref_ptr = file_refs, appl_ptr = app_locks;
1865 ++i, ++fref_ptr, ++appl_ptr) {
1869 free_pkt->frefs[free_pkt->nfiles++] = *fref_ptr;
1872 /* send free files packet */
1873 if ( send_free() != S_OKAY )
1874 RETURN( db_status );
1876 /* reset all lock descriptors */
1879 /* reset all key file positions */
1882 /* Clear cache pages and return */
1883 RETURN( dio_clear() );
1890 /* Reset lock descriptor tables
1892 static void reset_locks()
1896 struct lock_descr *ld_ptr;
1898 /* reset record lock descriptors */
1901 for (i = beg, ld_ptr = &rec_locks[i]; i < end; ++i, ++ld_ptr) {
1902 if ( ld_ptr->fl_kept ) {
1903 ld_ptr->fl_type = 'r';
1904 ld_ptr->fl_kept = FALSE;
1906 else if ( ld_ptr->fl_type != 'x' )
1907 ld_ptr->fl_type = 'f';
1909 /* reset set lock descriptors */
1912 for (i = beg, ld_ptr = &set_locks[i]; i < end; ++i, ++ld_ptr) {
1913 if ( ld_ptr->fl_kept ) {
1914 ld_ptr->fl_type = 'r';
1915 ld_ptr->fl_kept = FALSE;
1917 else if ( ld_ptr->fl_type != 'x' )
1918 ld_ptr->fl_type = 'f';
1920 /* reset key lock descriptors */
1923 for (i = beg, ld_ptr = &key_locks[i]; i < end; ++i, ++ld_ptr) {
1924 if ( ld_ptr->fl_kept ) {
1925 ld_ptr->fl_type = 'r';
1926 ld_ptr->fl_kept = FALSE;
1928 else if ( ld_ptr->fl_type != 'x' )
1929 ld_ptr->fl_type = 'f';
1935 /* Send free files packet
1937 static int send_free()
1942 /* send any free packets */
1943 if ( free_pkt->nfiles ) {
1944 send_size = sizeof(LM_FREE) + (free_pkt->nfiles-1)*sizeof(INT);
1945 if ( send_size > fp_size )
1946 return ( dberr(S_SYSERR) );
1948 if ( nw_send(lsn, (MESSAGE *)free_pkt, send_size) )
1952 return( db_status = S_OKAY );
1958 /*------------------------------------------------------------------------
1959 Record Lock Bit Functions
1960 ------------------------------------------------------------------------*/
1962 /* Set record lock bit of current record
1973 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
1975 if ( ! curr_rec ) RETURN( dberr(S_NOCR) );
1978 file = NUM2INT((FILE_NO)((curr_rec >> FILESHIFT) & FILEMASK), ft_offset);
1981 (record_lock = (app_locks[file] >= 0 && !excl_locks[file])) ) {
1982 /* request record-lock on file */
1983 lock_pkt->nfiles = 1;
1984 lock_pkt->locks[0].type = 'R';
1985 lock_pkt->locks[0].fref = file_refs[file];
1986 if ( send_lock() != S_OKAY ) RETURN( db_status );
1987 if ( lock_reply.status != L_OKAY )
1988 RETURN( db_status = S_UNAVAIL );
1990 if ( dio_rrlb(curr_rec, &rid) != S_OKAY )
1991 RETURN( db_status );
1992 if ( rid & RLBMASK )
1993 rlb_status = S_LOCKED;
1996 rlb_status = dio_wrlb(curr_rec, rid);
1998 if ( dbopen == 1 && record_lock ) {
1999 /* free or downgrade record-lock on file */
2000 if ( app_locks[file] ) {
2001 lock_pkt->nfiles = 1;
2002 lock_pkt->locks[0].type = 'r';
2003 lock_pkt->locks[0].fref = file_refs[file];
2004 if ( send_lock() != S_OKAY ) RETURN( db_status );
2007 free_pkt->nfiles = 1;
2008 free_pkt->frefs[0] = file_refs[file];
2009 if ( send_free() != S_OKAY ) RETURN( db_status );
2012 RETURN( db_status = rlb_status );
2014 RETURN( db_status = S_OKAY );
2020 /* Clear record lock bit of current record
2030 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
2032 if ( ! curr_rec ) RETURN( dberr(S_NOCR) );
2035 file = NUM2INT((FILE_NO)((curr_rec >> FILESHIFT) & FILEMASK), ft_offset);
2037 /* ensure that changes are allowed */
2038 if (dbopen == 1 && trans_id && app_locks[file] >= 0 && !excl_locks[file])
2039 RETURN( dberr(S_NOTLOCKED) );
2041 if ( dbopen == 1 && ! trans_id ) {
2042 /* request record-lock on file */
2043 lock_pkt->nfiles = 1;
2044 lock_pkt->locks[0].type = 'R';
2045 lock_pkt->locks[0].fref = file_refs[file];
2046 if ( send_lock() != S_OKAY ) RETURN( db_status );
2047 if ( lock_reply.status != L_OKAY )
2048 RETURN( db_status = S_UNAVAIL );
2052 if ( dio_rrlb(curr_rec, &rid) != S_OKAY )
2053 RETURN( db_status );
2057 rlb_status = S_UNLOCKED;
2058 dio_wrlb(curr_rec, rid);
2060 if ( dbopen == 1 && ! trans_id ) {
2061 /* free or downgrade record-lock on file */
2062 if ( app_locks[file] ) {
2063 lock_pkt->nfiles = 1;
2064 lock_pkt->locks[0].type = 'r';
2065 lock_pkt->locks[0].fref = file_refs[file];
2066 if ( send_lock() != S_OKAY ) RETURN( db_status );
2069 free_pkt->nfiles = 1;
2070 free_pkt->frefs[0] = file_refs[file];
2071 if ( send_free() != S_OKAY ) RETURN( db_status );
2077 RETURN( db_status );
2083 /* Test record lock bit of current record
2092 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
2094 if ( ! curr_rec ) RETURN( dberr(S_NOCR) );
2097 if ( dio_rrlb(curr_rec, &rid) != S_OKAY )
2098 RETURN( db_status );
2100 if ( rid & RLBMASK )
2101 db_status = S_LOCKED;
2103 db_status = S_UNLOCKED;
2105 RETURN( rlb_status = db_status );
2107 RETURN( db_status = S_UNLOCKED );
2116 /*------------------------------------------------------------------------
2117 Database Transaction Processing Functions
2118 ------------------------------------------------------------------------*/
2120 /* Begin transaction
2122 d_trbegin(tid TASK_PARM)
2126 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
2130 if ( ! dbopen ) RETURN( dberr(S_DBOPEN) );
2132 if ( tid == NULL ) RETURN( dberr(S_TRANSID) );
2135 if ( trans_id ) RETURN( dberr(S_TRACTIVE) );
2137 /* changes were possible outside a transaction */
2144 RETURN( db_status );
2156 int ft_lc; /* loop control */
2157 LM_TRCOMMIT trcom_pkt;
2159 LM_LOCKREQ *lockreq_ptr;
2161 int *appl_ptr, *keptl_ptr, *excl_ptr;
2164 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
2167 if( ! trans_id ) RETURN( dberr(S_TRNOTACT) );
2170 /* mark start of trx in archive log file */
2173 /* flush data to database or overflow */
2174 if ( dio_flush() != S_OKAY ) RETURN( db_status );
2176 if ( (dboptions & TRLOGGING) && use_ovfl ) {
2177 /* End trx using overflow file */
2179 /* flush recovery data to overflow file */
2180 if ( o_flush() != S_OKAY ) RETURN( db_status );
2183 trcom_pkt.fcn = L_TRCOMMIT;
2184 strcpy(trcom_pkt.logfile, dblog);
2185 if ( nw_send(lsn, (MESSAGE *)&trcom_pkt, sizeof(LM_TRCOMMIT)) )
2191 if ( taf_add(dblog) != S_OKAY ) RETURN( db_status ); /* after nw_send */
2194 /* allow for user interrupt to test recovery */
2195 if ( db_txtest ) dberr(S_DEBUG);
2198 /* update db from overflow file */
2199 if ( o_update() != S_OKAY ) RETURN( db_status );
2202 /* flush modified cache data to database */
2203 if ( dio_flush() != S_OKAY ) RETURN( db_status );
2206 if ( taf_del(dblog) != S_OKAY ) RETURN( db_status ); /* before nw_send */
2210 trend_pkt.fcn = L_TREND;
2211 if ( nw_send(lsn, (MESSAGE *)&trend_pkt, sizeof(LM_TREND)) )
2217 /* mark end of trx in archive log file */
2221 o_init(); /*[305] clear cache_ovfl flag */
2224 if ( dbopen == 1 ) {
2225 /* free unkept, non-exclusive file locks */
2226 lock_pkt->nfiles = free_pkt->nfiles = 0;
2227 for (ft_lc = size_ft, fref_ptr = file_refs, appl_ptr = app_locks,
2228 keptl_ptr = kept_locks, excl_ptr = excl_locks;
2229 --ft_lc >= 0; ++fref_ptr, ++appl_ptr, ++keptl_ptr, ++excl_ptr) {
2231 *appl_ptr = *keptl_ptr;
2232 else if ( *appl_ptr == -1 ) {
2233 if ( (*appl_ptr = *keptl_ptr) > 0 ) {
2234 lockreq_ptr = &lock_pkt->locks[lock_pkt->nfiles++];
2235 lockreq_ptr->type = 'r';
2236 lockreq_ptr->fref = *fref_ptr;
2239 free_pkt->frefs[free_pkt->nfiles++] = *fref_ptr;
2241 else if ( *appl_ptr && (*appl_ptr = *keptl_ptr) == 0 )
2242 free_pkt->frefs[free_pkt->nfiles++] = *fref_ptr;
2245 /* send lock downgrade request */
2246 if ( send_lock() != S_OKAY || send_free() != S_OKAY )
2247 RETURN( db_status );
2249 /* clear lock descriptors */
2252 /* reset all key file positions */
2255 /* clear page buffers */
2259 RETURN( db_status );
2265 /* Abort transaction
2267 d_trabort(TASK_ONLY)
2271 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
2273 RETURN (dberr(S_TRNOTACT));
2275 dio_pzclr(); /*[425] clear page zero BEFORE dio_clear */
2276 dio_clear(); /*[353] clear cache */
2277 RETURN (db_status = S_OKAY);
2281 struct lock_descr *ld_ptr;
2283 DB_ENTER(NO_DB_ID TASK_ID LOCK_SET(LOCK_IO));
2286 if ( ! trans_id ) RETURN( dberr(S_TRNOTACT) );
2288 if ( dbopen == 1 ) {
2289 /* Revert any kept locks to unkept status */
2290 for (i = 0, keptl_ptr = kept_locks; i < size_ft; ++i, ++keptl_ptr)
2292 for (i = 0, ld_ptr = rec_locks; i < size_rt; ++i, ++ld_ptr)
2293 ld_ptr->fl_kept = FALSE;
2294 for (i = 0, ld_ptr = set_locks; i < size_st; ++i, ++ld_ptr)
2295 ld_ptr->fl_kept = FALSE;
2296 for (i = 0, ld_ptr = key_locks; i < keyl_cnt; ++i, ++ld_ptr)
2297 ld_ptr->fl_kept = FALSE;
2300 o_init(); /*[305] clear cache_ovfl flag */
2302 dio_pzclr(); /*[425] clear page zero BEFORE d_freeall */
2303 if ( dbopen == 1 ) d_freeall(TASK_ONLY);
2306 RETURN( db_status = S_OKAY );
2312 /* Report a network error
2316 switch ( net_status ) {
2318 db_status = dberr( S_LMBUSY );
2321 db_status = dberr( S_NOLOCKMGR );
2324 db_status = dberr( S_DUPUSERID );
2327 db_status = dberr( S_NETERR );
2330 return( db_status );
2334 int alloc_table(Table, new_size, old_size )
2336 #define table Table->ptr
2342 Temp_table.ptr = ALLOC(&Temp_table, new_size, varname);
2343 if ( Temp_table.ptr == NULL ) {
2344 return( dberr(S_NOMEMORY) );
2346 byteset(&Temp_table.ptr[old_size], 0, new_size - old_size);
2349 bytecpy(Temp_table.ptr, table, old_size);
2354 *Table = Temp_table;
2355 return( db_status );
2357 /* vpp -nOS2 -dUNIX -nBSD -nVANILLA_BSD -nVMS -nMEMLOCK -nWINDOWS -nFAR_ALLOC -f/usr/users/master/config/nonwin dblfcns.c */