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: EXCL_OPEN
62 * This module contains IBM CONFIDENTIAL code. -- (IBM
63 * Confidential Restricted when combined with the aggregated
64 * modules for this product)
66 * OBJECT CODE ONLY SOURCE MATERIALS
67 * (C) COPYRIGHT International Business Machines Corp. 1995, 1996
69 * US Government Users Restricted Rights - Use, duplication or
70 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
72 /*------------------------------------------------------------------------
73 $XConsortium: dio.c /main/7 1996/11/25 18:48:24 drk $
74 dio - Database Input/Output Control Functions
76 Copyright (C) 1984, 1985, 1986, 1987 by Raima Corporation
77 ------------------------------------------------------------------------*/
79 /* ********************** EDIT HISTORY *******************************
81 SCR DATE INI DESCRIPTION
82 ----- --------- --- -----------------------------------------------------
83 76 16-JUN-88 RSC Clean up so SINGLE_USER produces good code
84 240 20-Jun-88 RSC Clean up so NO_TRANS produces good code
85 103 24-Jun-88 RSC Improve generation of single user version
86 295 01-Jul-88 RSC make cnt_open_files global, to support initial.c mods
87 333 05-Jul-88 RSC make wrlb only fiddle with rlb, not entire rid
88 115 18-Jul-88 RSC Integrate VAX VMS changes into master code
89 366 25-Jul-88 RSC dio_pzread should use dio_open, not DB_OPEN
90 04-Aug-88 RTK MULTI_TASK changes
91 11-Aug-88 RTK d_setpages and d_setfiles must return immediately if
92 another task already has opened a database.
93 115 16-Aug-88 RSC Fixup of VMS integration
94 423 10-Sep-88 RSC Fixup of multi-task compile problems
95 420 15-Sep-88 RTK Encompassed calls to dio_unlock within an ifdef MEMLOCK
96 423 15-Sep-88 RSC Also cleared last_dblu in clear_cache
97 423 15-Sep-88 RSC Removed '#' from ifdef two lines up - vpp no like!!!!!
98 420 16-Sep-88 RTK A couple missing FAR's
99 425 05-Oct-88 RSC d_trabort wasn't completely clearing page zero, added
100 dio_pzclr to support d_trabort
101 433 31-Oct-88 RSC Fix for SCR #423 wasn't quite right - query wouldn't run
102 532 06-Jan-89 RSC Fix code so NO_TRANS compiles correctly
103 08-Feb-89 RSC Fix from AMCY - clear cache wasn't completely swapping.
104 420 13-Feb-89 WLW Cleared last_dblu in clear_cache (only safe thing to do)
105 14-Feb-89 RSC Misc fixes
106 588 16-Feb-89 RSC remove ifndef SINGLE_USER around CLOSE_FILES
107 612 21-Feb-89 RSC always clear ovfl_addr in dbpg_table
108 619 09-Mar-89 WLW call o_fileinit from dio_pzgetts, don't call dio_pzsetts
110 05-May-89 WLW Added ".v" tag to Currtask for MULTI_TASKing
113 * Revision 1.2 1995/10/17 19:15:37 miker
114 * Changed open mode from hardcoded O_RDWR to global var db_oflag.
127 int debugging_dio_init = FALSE;
128 int debugging_dio_close = FALSE;
133 /* On MS-DOS networks, files must be closed whenever a lock is freed.
134 Function dio_clrfile is called whenever a lock is freed to clear
135 from the cache the pages of the file whose lock is being freed.
136 CLosing and opening files on Unix, VMS and other host computers,
137 however, is very slow and is not necessary for database integrity.
138 The following constant definition specifies whether or not the files
139 need to be closed. A definition per supported MS-DOS compiler is
154 /*------------ transaction logging data ------------*/
155 #define DEFIXPAGES 4 /* default number of index cache pages */
156 #define MINIXPAGES 2 /* minimum number of index cache pages */
157 int ix_pgtab_sz = DEFIXPAGES;
158 LOOKUP_ENTRY_P Ix_lookup = POINTER_INIT(); /* index page lookup table */
159 PAGE_ENTRY_P Ixpg_table = POINTER_INIT(); /* index page table */
160 static int ixpg_lru_slot; /* least recently accessed ix page */
162 /* transaction logging enabled flag */
163 int trlog_flag = 0; /* set only by user implemented functions */
165 BOOLEAN use_ovfl = YES; /* Default to using overflow */
166 CHAR_P Dbpgbuff = POINTER_INIT(); /* allocated by dio_init used by o_update */
167 /*------------ end of transaction logging data ------------*/
168 #endif /* NO_TRANS */
171 #define EXCL_OPEN() (dbopen >= 2)
173 #define EXCL_OPEN() (TRUE)
176 #define DEFDBPAGES 16 /* default number of database cache pages */
177 #define MINDBPAGES 8 /* minimum number of database cache pages */
179 extern BOOLEAN trcommit;
181 int db_pgtab_sz = DEFDBPAGES;
183 LOOKUP_ENTRY_P Db_lookup = POINTER_INIT(); /* database page lookup table */
184 PAGE_ENTRY_P Dbpg_table = POINTER_INIT(); /* database page table */
193 } last_dblu; /* last found lookup entry in cache */
195 /* maximum number of open files allowed by
196 operating system (user settable) */
197 /* On VMS systems, max_open_files need to be defined with a globaldef
198 instead of just a normal external. This will force this module to be
199 included, thus giving a default value to max_open_files. If it were
200 just a normal external the VMS linker would not load this module unless
201 a reference to a function in it is made and it would leave max_open_files
202 with a value of 0. */
203 int max_open_files = 8;
204 INT_P Used_files = POINTER_INIT(); /* LRU file table */
205 int cnt_open_files = 0; /* count of currently open files */
206 static int last_file = 0; /* least recently used file */
208 static int dbpg_lru_slot; /* least recently accessed db page */
209 static int no_modheld; /* number of modified or held db pages */
210 static FILE_NO working_file; /* current key file being processed */
212 static void cache_init(P1(int) Pi(LOOKUP_ENTRY FAR *)
213 Pi(PAGE_ENTRY FAR *) Pi(int));
214 static int dio_pzinit(P0);
215 static int clear_cache(P1(FILE_NO) Pi(FILE_NO));
216 static int dio_pzflush(P0);
218 static int dio_in(P1(PAGE_ENTRY FAR *) Pi(LOOKUP_ENTRY FAR *));
220 static int dio_in(P1(PAGE_ENTRY FAR *) Pi(LOOKUP_ENTRY FAR *)
224 #define used_files Used_files.ptr
225 #define db_lookup Db_lookup.ptr
226 #define dbpg_table Dbpg_table.ptr
230 /* Set the maximum number of open db_VISTA files
236 if ( dbpg_table ) return( dberr(S_DBCLOSE) );
238 if ( num > 0 && num < 256 )
239 max_open_files = num;
241 return( db_status = S_OKAY );
245 /* Set number of virtual memory pages
248 d_setpages(dbpgs, ixpgs)
249 int dbpgs; /* # of db cache pages */
250 int ixpgs; /* # of index cache pages - ignored in single-user version */
252 if ( dbpg_table ) return( dberr(S_SETPAGES) );
254 db_pgtab_sz = (dbpgs <= MINDBPAGES) ? MINDBPAGES : dbpgs;
258 ix_pgtab_sz = (ixpgs <= MINIXPAGES) ? MINIXPAGES : ixpgs;
261 return( db_status = S_OKAY );
265 /****************************************/
269 /****************************************/
270 /* Open a database file
276 FILE_ENTRY FAR *file_ptr, FAR *lru_file_ptr;
277 register int FAR *uf_ptr;
279 file_ptr = &file_table[fno];
280 if ( file_ptr->ft_status == CLOSED ) {
281 if ( cnt_open_files == max_open_files ) {
282 /* find least recently used file */
283 uf_ptr = &used_files[last_file];
284 lru_file_ptr = &file_table[last_file];
285 while (*uf_ptr || (lru_file_ptr->ft_status == CLOSED)) {
287 if (++last_file >= size_ft) {
289 lru_file_ptr = file_table;
297 dio_close(last_file);
298 if (++last_file >= size_ft)
301 used_files[fno] = TRUE;
303 file_ptr->ft_desc = open_b(file_ptr->ft_name, db_oflag);
304 if (file_ptr->ft_desc < 0)
305 return( dberr( S_NOFILE ) );
306 file_ptr->ft_status = OPEN;
309 return( db_status = S_OKAY );
313 /****************************************/
317 /****************************************/
318 /* Close a database file
324 FILE_ENTRY FAR *file_ptr;
326 file_ptr = &file_table[fno];
327 if ( file_ptr->ft_status == OPEN ) {
328 DB_CLOSE( file_ptr->ft_desc );
329 file_ptr->ft_status = CLOSED;
332 return( db_status = S_OKAY );
336 /****************************************/
340 /****************************************/
341 /* Initialize database I/O
347 #define tempbuff Tempbuff.ptr
350 if (debugging_dio_init) {
351 printf (__FILE__"300 dio_init: dbpgtab=%p pgsz=%d largest=%d\n",
352 (void *) dbpg_table, (int)page_size, (int)largest_page);
358 if ( dio_pzinit() != S_OKAY ) {
361 if ( page_size > largest_page ) {
362 if ( (tempbuff = ALLOC(&Tempbuff, page_size, "tempbuff")) == NULL )
363 return( dberr(S_NOMEMORY) );
365 MEM_UNLOCK(&Dbpgbuff);
369 largest_page = page_size;
372 if (debugging_dio_init) {
373 printf (__FILE__"323 dio_init: pzinited ok. pgsz=%d largest=%d\n",
374 (int)page_size, (int)largest_page);
380 } /* end if ( dbpg_table ) */
383 /* Macro references must be on one line for some compilers */
384 (int FAR *)ALLOC(&Used_files, (size_ft+1)*sizeof(int), "used_files");
386 /* Macro references must be on one line for some compilers */
388 ALLOC(&Db_lookup, db_pgtab_sz*sizeof(LOOKUP_ENTRY), "db_lookup");
390 /* Macro references must be on one line for some compilers */
392 ALLOC(&Dbpg_table, db_pgtab_sz*sizeof(PAGE_ENTRY), "dbpg_table");
394 if (debugging_dio_init) {
395 printf (__FILE__"345 dio_init: usedfls=%p lookup=%p pgtab=%p\n",
396 (void *) used_files, (void *) db_lookup, (void *) dbpg_table);
400 if ( !used_files || !dbpg_table || !db_lookup )
401 return( dberr(S_NOMEMORY) );
402 byteset(used_files, 0, (size_ft + 1)*sizeof(*used_files));
405 last_dblu.task = NULL;
408 last_dblu.pageno = -1L;
411 /* initialize database cache */
412 cache_init((int)db_pgtab_sz, db_lookup, dbpg_table, (int)page_size);
413 /***cache_init(db_pgtab_sz, db_lookup, dbpg_table, page_size);****/
414 if (db_status != S_OKAY) return(db_status);
418 /* Macro references must be on one line for some compilers */
420 ALLOC(&Ix_lookup, ix_pgtab_sz*sizeof(LOOKUP_ENTRY),"ix_lookup");
422 /* Macro references must be on one line for some compilers */
424 ALLOC(&Ixpg_table, ix_pgtab_sz*sizeof(PAGE_ENTRY), "ixpg_table");
425 if ( !ix_lookup || !ixpg_table )
426 return( dberr(S_NOMEMORY) );
428 cache_init(ix_pgtab_sz, ix_lookup, ixpg_table, IX_PAGESIZE);
429 if (db_status != S_OKAY)
432 if ( (dbpgbuff = ALLOC(&Dbpgbuff, page_size, "dbpgbuff")) == NULL )
433 return( dberr(S_NOMEMORY) );
437 #endif /* NO_TRANS */
443 /* initialize the page zero table and return */
445 if (debugging_dio_init) {
446 puts (__FILE__"390 dio_init: last act is call to dio_pzinit.");
450 return( dio_pzinit() );
455 static void cache_init (pg_cnt, lu_ptr, pg_ptr, pgsize)
457 LOOKUP_ENTRY FAR * lu_ptr;
458 PAGE_ENTRY FAR * pg_ptr;
464 if (debugging_dio_init) {
465 printf (__FILE__"400 cache_init: pgcnt=%d lu=%p pgp=%p pgsz=%d\n",
466 pg_cnt, (void *) lu_ptr, (void *) pg_ptr, pgsize);
471 for (pg_no = 0; pg_no < pg_cnt; ++pg_no, ++lu_ptr, ++pg_ptr)
477 lu_ptr->pageno = -1L;
478 lu_ptr->pg_slot = pg_no;
480 pg_ptr->lu_slot = pg_no;
481 pg_ptr->recently_used = FALSE;
482 pg_ptr->modified = FALSE;
485 pg_ptr->ovfl_addr = 0L;
487 pg_ptr->buff = ALLOC(&pg_ptr->Buff, pgsize, db_avname);
488 if (pg_ptr->buff == NULL) {
490 if (debugging_dio_init) {
491 printf (__FILE__"428 cache_init: alloc failed pgsz=%d\n",
499 MEM_UNLOCK(&pg_ptr->Buff);
500 } /* end loop on pg_cnt */
505 /****************************************/
509 /****************************************/
510 /* Free the memory allocated for pages
514 register int pgt_lc; /* loop control */
515 register PAGE_ENTRY FAR *pg_ptr;
518 if ( task_count > 1 ) {
522 MEM_UNLOCK(&db_global.Pgzero);
523 FREE(&db_global.Pgzero);
524 MEM_UNLOCK(&Used_files);
526 MEM_UNLOCK(&Db_lookup);
528 for (pgt_lc = db_pgtab_sz, pg_ptr = dbpg_table; --pgt_lc >= 0; ++pg_ptr) {
529 MEM_UNLOCK(&pg_ptr->Buff);
532 MEM_UNLOCK(&Dbpg_table);
536 MEM_UNLOCK(&Ix_lookup);
538 for (pgt_lc = ix_pgtab_sz, pg_ptr = ixpg_table; --pgt_lc >= 0; ++pg_ptr) {
539 MEM_UNLOCK(&pg_ptr->Buff);
542 MEM_UNLOCK(&Ixpg_table);
544 MEM_UNLOCK(&Dbpgbuff);
551 /****************************************/
555 /****************************************/
556 /* Clear pages for a single file.
560 register FILE_NO fno;
562 return( clear_cache(fno, fno+1) );
567 /****************************************/
571 /****************************************/
572 /* Clear all pages for *all* files from I/O buffer
577 return( clear_cache(0, size_ft) );
581 /****************************************/
585 /****************************************/
586 /* Clear database page cache.
587 * Clears all pages for a range of specified files.
588 * Subroutine of dio_clrfile and dio_clear.
590 static int clear_cache(fr_file, to_file )
591 FILE_NO fr_file; /* clear from file "fr_file" */
592 FILE_NO to_file; /* ..to (not thru) file "to_file" */
594 FILE_NO s_file; /* start file to be cleared */
595 FILE_NO e_file; /* end file (+1) to be cleared */
597 LOOKUP_ENTRY FAR *lu_ptr, FAR *lu2_ptr;
599 PAGE_ENTRY FAR *pg_ptr;
600 PGZERO FAR *pgzero_ptr;
601 FILE_ENTRY FAR *file_ptr;
603 int FAR *appl_ptr, FAR *excl_ptr;
608 We only clear pages which are not from static files and are
609 not still locked. The check on app_locks is made to implement
610 the ability to hold locks after the end of a transaction
612 for (s_file = e_file = fr_file, file_ptr = &file_table[e_file],
613 appl_ptr = &app_locks[e_file], excl_ptr = &excl_locks[e_file];
615 ++file_ptr, ++appl_ptr, ++excl_ptr) {
617 for (s_file = e_file = fr_file, file_ptr = &file_table[e_file];
621 if ((e_file < to_file) &&
623 ((dbopen >= 2) || (!*appl_ptr && !*excl_ptr)) &&
625 !(file_ptr->ft_flags & STATIC))
628 if (s_file < e_file) {
629 /* find range of pages to be cleared */
630 dio_findpg(s_file, 0L, NULL, NULL, &lu_ptr);
631 dio_findpg(e_file, 0L, NULL, NULL, &lu2_ptr);
634 last_dblu.task = NULL;
637 last_dblu.pageno = -1L;
640 if (lu_ptr < lu2_ptr) { /* otherwise file has no pages in cache */
641 /* adjust lookup table entries */
642 while ((lu_ptr > db_lookup) && ((--lu_ptr)->file >= 0)) {
646 lu2_ptr->task = lu_ptr->task;
648 lu2_ptr->file = lu_ptr->file;
649 lu2_ptr->pageno = lu_ptr->pageno;
650 /* exchange page slot numbers */
651 pg_slot = lu_ptr->pg_slot;
652 lu_ptr->pg_slot = lu2_ptr->pg_slot;
653 lu2_ptr->pg_slot = pg_slot;
654 dbpg_table[pg_slot].lu_slot = lu2_ptr - db_lookup;
655 dbpg_table[lu_ptr->pg_slot].lu_slot = lu_ptr - db_lookup;
658 if ( lu_ptr->file < 0 )
661 while (lu_ptr < lu2_ptr) {
667 lu_ptr->pageno = -1L;
668 pg_ptr = &dbpg_table[lu_ptr->pg_slot];
669 if ( pg_ptr->modified || pg_ptr->holdcnt ) {
671 pg_ptr->modified = FALSE;
673 pg_ptr->recently_used = FALSE;
676 pg_ptr->ovfl_addr = 0L;
681 /* clear page zeroes and close files */
682 for (i = s_file, pgzero_ptr = &pgzero[i];
685 pgzero_ptr->pz_modified = FALSE;
686 pgzero_ptr->pz_next = 0L;
695 return( db_status = S_OKAY );
696 } /* clear_cache() */
699 /****************************************/
703 /****************************************/
704 /* Flushes entire database I/O cache.
705 * Writes out all modified cache pages to respective files (dio_out),
706 * then writes out page zero (dio_pzflush).
710 register int pgt_lc; /* loop control */
714 PAGE_ENTRY FAR *pg_ptr;
715 LOOKUP_ENTRY FAR *lu_ptr;
718 if (debugging_dio_close) {
719 printf (__FILE__"685 dio_flush: check cache dbpgtab=%p count=%d\n",
720 (void *) dbpg_table, (int)db_pgtab_sz);
724 if ( dbpg_table == NULL ) return( db_status = S_OKAY );
726 for (pgt_lc = db_pgtab_sz, pg_ptr = dbpg_table; --pgt_lc >= 0; ++pg_ptr) {
727 if (!pg_ptr->modified) {
729 pg_ptr->ovfl_addr = 0L; /*[612]*/
733 lu_ptr = &db_lookup[pg_ptr->lu_slot];
735 if ( lu_ptr->task != Currtask.v.ptr ) {
740 if ((dboptions & TRLOGGING) && trans_id && !trcommit && use_ovfl) {
741 /* flush to overflow/log file -- before tr commit */
742 if (o_write(pg_ptr, lu_ptr) != S_OKAY) return( db_status );
743 if ( lu_ptr->pageno > o_pages(lu_ptr->file) ) {
744 /* no need to rewrite this page at trcommit time */
746 pg_ptr->modified = FALSE;
751 pg_ptr->ovfl_addr = 0L;
753 /* write directly to database */
756 if (debugging_dio_close) {
757 printf (__FILE__"723 dio_flush: write modified pg#%d @ %p\n",
758 db_pgtab_sz - pgt_lc, (void *) pg_ptr);
762 if (dio_out(pg_ptr, lu_ptr) != S_OKAY) return( db_status );
764 if (dio_out(pg_ptr, lu_ptr, 1) != S_OKAY) return( db_status );
767 pg_ptr->modified = FALSE;
772 MEM_LOCK(&pg_ptr->Buff);
773 d_trlog(fno, (int)lu_ptr->pageno, pg_ptr->buff,
774 file_table[fno].ft_pgsize);
775 MEM_UNLOCK(&pg_ptr->Buff);
779 /* store the page zero values in the data file and return */
780 return( dio_pzflush() );
785 /* Set the default file number
787 void dio_setdef( file_no )
790 working_file = file_no;
795 /****************************************/
799 /****************************************/
800 /* Database I/O page get
803 dio_get( page_no, page_ptr, hold )
805 char FAR * FAR *page_ptr;
808 PAGE_ENTRY FAR *pg_ptr;
812 if ( !app_locks[working_file] && !excl_locks[working_file] &&
813 !(file_table[working_file].ft_flags & STATIC) )
814 return( dberr(S_NOTLOCKED) );
817 if ( pgzero[working_file].pz_next == 0L )
818 if ( dio_pzread(working_file) != S_OKAY )
821 if (dio_findpg(working_file, page_no, dbpg_table, &pg_ptr, NULL) == S_OKAY) {
822 MEM_LOCK(&pg_ptr->Buff);
823 *page_ptr = pg_ptr->buff;
824 pg_ptr->recently_used = TRUE;
825 used_files[working_file] = TRUE;
827 if ( ++pg_ptr->holdcnt > 1 )
829 else if ( ! pg_ptr->modified )
838 /****************************************/
842 /****************************************/
843 /* Set modified flag for a page
849 PAGE_ENTRY FAR *pg_ptr;
852 /* ensure overflow data is initialized when exclusive db access */
853 if ((trans_id && (dboptions & TRLOGGING) && use_ovfl) &&
854 (o_fileinit(working_file) != S_OKAY))
859 /* check shared access privileges */
860 if ( !trans_id && !excl_locks[working_file] )
861 return( dberr(S_NOTRANS) );
862 if ( app_locks[working_file] >= 0 && !excl_locks[working_file] )
863 return( dberr( S_NOTLOCKED ) );
866 if (dio_findpg(working_file, page_no, dbpg_table, &pg_ptr, NULL) == S_OKAY ) {
867 pg_ptr->recently_used = TRUE;
868 used_files[working_file] = TRUE;
869 if ( ! pg_ptr->modified ) {
870 pg_ptr->modified = TRUE;
871 if ( ! pg_ptr->holdcnt )
874 if ( pg_ptr->holdcnt > 0 ) {
876 if ( pg_ptr->holdcnt ) {
879 MEM_UNLOCK(&pg_ptr->Buff);
887 /****************************************/
891 /****************************************/
893 * Merely returns ptr into rec in a page
894 * unless a page swap is necessary.
897 dio_read( dba, recptr, hold )
899 char FAR * FAR *recptr;
905 FILE_ENTRY FAR *file_ptr;
906 PAGE_ENTRY FAR *pg_ptr;
908 file = NUM2INT((FILE_NO)((dba >> FILESHIFT) & FILEMASK), ft_offset);
909 file_ptr = &file_table[file];
911 if ( pgzero[file].pz_next == 0L )
912 if ( dio_pzread(file) != S_OKAY )
917 /* check shared access privileges */
918 if (!app_locks[file] &&
920 !(file_ptr->ft_flags & STATIC))
921 return( dberr(S_NOTLOCKED) );
924 us1 = ADDRMASK & dba;
925 us2 = (us1 - 1)/file_ptr->ft_slots;
926 if (dio_findpg(file, us2 + 1, dbpg_table, &pg_ptr, NULL) == S_OKAY ) {
927 pg_ptr->recently_used = TRUE;
928 used_files[file] = TRUE;
929 offset = file_ptr->ft_slsize*(int)(us1 - 1 - us2*file_ptr->ft_slots) +
931 MEM_LOCK(&pg_ptr->Buff);
932 *recptr = &pg_ptr->buff[offset];
934 if ( (++pg_ptr->holdcnt == 1) && !pg_ptr->modified) {
943 /****************************************/
947 /****************************************/
948 /* Database I/O write: copies data record into a page slot.
949 * Finds record's page, swapping it into cache if necessary.
950 * Sets page's 'touched' flags, timestamps, etc.
951 * If recptr not NULL, copies rec to page cache.
954 dio_write( dba, recptr, release )
956 CONST char FAR *recptr;
962 FILE_ENTRY FAR *file_ptr;
963 PAGE_ENTRY FAR *pg_ptr;
965 file = NUM2INT((FILE_NO)((dba >> FILESHIFT) & FILEMASK), ft_offset);
968 /* ensure overflow data is initialized when exclusive db access */
969 if ((trans_id && (dboptions & TRLOGGING) && use_ovfl) &&
970 (o_fileinit(file) != S_OKAY))
975 if (!trans_id && !excl_locks[file])
976 return( dberr(S_NOTRANS) );
978 /* check shared access privileges */
979 if ( app_locks[file] >= 0 && !excl_locks[file] )
980 return( dberr(S_NOTLOCKED) );
983 file_ptr = &file_table[file];
984 us1 = ADDRMASK & dba;
985 us2 = (us1 - 1)/file_ptr->ft_slots;
986 if (dio_findpg(file, us2 + 1, dbpg_table, &pg_ptr, NULL) == S_OKAY ) {
987 pg_ptr->recently_used = TRUE;
988 used_files[file] = TRUE;
989 if ( recptr != NULL ) {
990 offset = file_ptr->ft_slsize*(int)(us1 - 1 - us2*file_ptr->ft_slots) +
992 MEM_LOCK(&pg_ptr->Buff);
993 bytecpy(&pg_ptr->buff[offset], recptr, file_ptr->ft_slsize);
994 MEM_UNLOCK(&pg_ptr->Buff);
996 if ( ! pg_ptr->modified ) {
997 pg_ptr->modified = TRUE;
998 if ( ! pg_ptr->holdcnt )
1002 if ( --pg_ptr->holdcnt < 0 )
1004 MEM_UNLOCK(&pg_ptr->Buff);
1007 return( db_status );
1011 /* Release database page hold
1019 PAGE_ENTRY FAR *pg_ptr;
1021 file = NUM2INT((FILE_NO)((dba >> FILESHIFT) & FILEMASK), ft_offset);
1022 us1 = ADDRMASK & dba;
1023 us2 = file_table[file].ft_slots;
1024 if (dio_findpg(file, ((us1 - 1)/us2) + 1, dbpg_table, &pg_ptr,
1026 if (pg_ptr->holdcnt) {
1028 if ( !pg_ptr->holdcnt && !pg_ptr->modified )
1030 MEM_UNLOCK(&pg_ptr->Buff);
1033 return( db_status );
1039 /* Read record lock bit
1045 FILE_NO file; /* file number */
1046 F_ADDR page; /* page number */
1047 F_ADDR sno; /* slot number */
1048 F_ADDR spp; /* slots per page */
1049 F_ADDR offset; /* lseek address - offset from start of file */
1050 FILE_ENTRY FAR *file_ptr;
1052 file = NUM2INT((FILE_NO)((dba >> FILESHIFT) & FILEMASK), ft_offset);
1053 if ( dio_open(file) == S_OKAY ) {
1054 file_ptr = &file_table[file];
1055 sno = ADDRMASK & dba;
1056 spp = file_ptr->ft_slots;
1057 page = (sno - 1)/spp + 1;
1058 offset = PGHDRSIZE + page*file_ptr->ft_pgsize +
1059 (sno - 1 - (page - 1)*spp)*file_ptr->ft_slsize;
1060 DB_LSEEK(file_ptr->ft_desc, (off_t)offset, 0);
1061 if ( DB_READ(file_ptr->ft_desc, (char FAR *)rid, sizeof(INT))
1067 return( db_status );
1071 /* Write record lock bit
1077 FILE_NO file; /* file number */
1078 F_ADDR page; /* page number */
1079 F_ADDR sno; /* slot number */
1080 F_ADDR spp; /* slots per page */
1081 F_ADDR offset; /* offset from start of page or file */
1082 int clr_in_tx; /* true if called from d_rlbclr in trx */
1083 INT trid; /* [333] working rid */
1084 FILE_ENTRY FAR *file_ptr;
1085 PAGE_ENTRY FAR *pg_ptr;
1087 file = NUM2INT((FILE_NO)((dba >> FILESHIFT) & FILEMASK), ft_offset);
1088 file_ptr = &file_table[file];
1089 sno = ADDRMASK & dba;
1090 spp = file_ptr->ft_slots;
1091 page = ((sno - 1)/spp) + 1;
1092 offset = PGHDRSIZE + (sno - 1 - (page - 1)*spp)*file_ptr->ft_slsize;
1093 clr_in_tx = !(rid & RLBMASK) && trans_id;
1095 if ( dbopen > 1 || (app_locks[file] || excl_locks[file]) ) {
1096 /* file is locked - check if record in cache */
1097 if (dio_findpg(file, page, dbpg_table, &pg_ptr, NULL) == S_OKAY) {
1098 MEM_LOCK(&pg_ptr->Buff);
1099 /* record in cache - update only rlb in rid */
1100 bytecpy(&trid, &pg_ptr->buff[offset], sizeof(INT));
1101 MEM_UNLOCK(&pg_ptr->Buff);
1102 rid = (trid & ~((INT)RLBMASK)) | (rid & RLBMASK);
1103 bytecpy(&pg_ptr->buff[offset], &rid, sizeof(INT));
1105 /* clearing within a transaction requires touching page */
1106 if ( ! pg_ptr->modified ) {
1107 pg_ptr->modified = TRUE;
1108 if ( ! pg_ptr->holdcnt )
1116 if ( ! clr_in_tx ) {
1117 /* update only rlb directly to disk */
1118 if ( dio_open(file) == S_OKAY ) {
1119 offset += page*file_ptr->ft_pgsize;
1121 /* read rid from disk, and set/clear rlb accordingly */
1122 DB_LSEEK(file_ptr->ft_desc, (off_t)offset, 0);
1123 if ( DB_READ(file_ptr->ft_desc, (char FAR *)&trid, sizeof(INT))
1128 rid = (trid & ~((INT)RLBMASK)) | (rid & RLBMASK);
1130 /* write original rid out with modified rlb */
1131 trid = htons (rid); /* make a copy in trid for byte swap */
1132 DB_LSEEK(file_ptr->ft_desc, (off_t)offset, 0); /* reseek */
1133 if ( DB_WRITE(file_ptr->ft_desc, (char FAR *)&trid, sizeof(INT)) !=
1138 return( db_status );
1140 #endif /* SINGLE_USER */
1143 /****************************************/
1147 /****************************************/
1148 /* Search a cache for page
1151 dio_findpg(file, page, pg_table, xpg_ptr, xlu_ptr )
1152 FILE_NO file; /* file number = 0..size_ft-1 */
1153 F_ADDR page; /* database page number */
1154 PAGE_ENTRY FAR *pg_table; /* = dbpg_table, ixpg_table, or NULL */
1155 PAGE_ENTRY FAR * FAR *xpg_ptr; /* pointer to page table entry for found page */
1156 LOOKUP_ENTRY FAR * FAR *xlu_ptr;/* pointer to lookup table slot for found page*/
1160 #define tempbuff Tempbuff.ptr
1162 LOOKUP_ENTRY FAR *lookup; /* = db_lookup or ix_lookup */
1163 int pgtab_sz; /* = db_pgtab_sz or ix_pgtab_sz */
1166 register int lu_slot, l, u;
1167 LOOKUP_ENTRY FAR *lu_ptr, FAR *replu_ptr;
1168 PAGE_ENTRY FAR *pg_ptr;
1172 BOOLEAN db_cache; /* TRUE if currently using dbpg_table */
1181 /* check if desired page was last one */
1183 if ((Currtask.v.ptr == last_dblu.task) && (file == last_dblu.file) && (page == last_dblu.pageno)) {
1185 if ((file == last_dblu.file) && (page == last_dblu.pageno)) {
1187 if (xlu_ptr != NULL)
1188 *xlu_ptr = &db_lookup[last_dblu.slot];
1189 if (xpg_ptr != NULL)
1190 *xpg_ptr = &dbpg_table[db_lookup[last_dblu.slot].pg_slot];
1191 return( db_status = S_OKAY );
1194 pgtab_sz = db_pgtab_sz;
1195 #else /* NO_TRANS */
1196 if (db_cache = (!pg_table || (pg_table == dbpg_table))) {
1197 /* check if desired page was last one */
1199 if ((Currtask.v.ptr == last_dblu.task) && (file == last_dblu.file) &&
1200 (page == last_dblu.pageno)) {
1202 if ((file == last_dblu.file) && (page == last_dblu.pageno)) {
1204 if (xlu_ptr != NULL)
1205 *xlu_ptr = &db_lookup[last_dblu.slot];
1206 if (xpg_ptr != NULL)
1207 *xpg_ptr = &dbpg_table[db_lookup[last_dblu.slot].pg_slot];
1208 return( db_status = S_OKAY );
1211 pgtab_sz = db_pgtab_sz;
1215 pgtab_sz = ix_pgtab_sz;
1217 #endif /* NO_TRANS */
1218 /* perform binary search of sorted lookup table */
1222 lu_ptr = &lookup[lu_slot = (l + u)/2];
1224 if ((cmp = Currtask.v.ptr - lu_ptr->task) == 0)
1226 if ((cmp = file - lu_ptr->file) == 0)
1227 cmp = page - lu_ptr->pageno;
1238 last_dblu.task = lu_ptr->task;
1240 last_dblu.file = lu_ptr->file;
1241 last_dblu.pageno = lu_ptr->pageno;
1242 last_dblu.slot = lu_slot;
1246 if (xlu_ptr != NULL)
1248 if (xpg_ptr != NULL)
1249 *xpg_ptr = &pg_table[lu_ptr->pg_slot];
1250 return( db_status = S_OKAY );
1254 /* null page table indicates that only a lookup was desired */
1257 if (xlu_ptr != NULL)
1259 return( db_status = S_NOTFOUND );
1261 /* page not found - read into cache */
1263 if( !use_ovfl && trans_id && (no_modheld == pgtab_sz) )
1264 return( db_status = S_TRCHANGES );
1266 /* check to see if page is in overflow file */
1268 if ( cache_ovfl && file != ov_file ) {
1269 if ( o_search( file, page, &ovfl_addr ) != S_OKAY )
1270 return( db_status );
1272 /* check for overflow */
1273 if ( db_cache && trans_id && (no_modheld == pgtab_sz) && !cache_ovfl ) {
1276 /* select a page to replace */
1278 lru_ptr = &dbpg_lru_slot;
1280 lru_ptr = &ixpg_lru_slot;
1283 /* select a page to replace */
1284 lru_ptr = &dbpg_lru_slot;
1285 #endif /* NO_TRANS */
1286 for (cnt = 2*pgtab_sz, pg_slot = *lru_ptr, pg_ptr = &pg_table[pg_slot];
1288 ++pg_slot, ++pg_ptr) {
1289 if (pg_slot >= pgtab_sz)
1294 replu_ptr = &lookup[pg_ptr->lu_slot];
1295 if (!pg_ptr->recently_used && (pg_ptr->holdcnt == 0)) {
1297 if (pg_ptr->modified) {
1298 dio_out(pg_ptr, replu_ptr);
1299 pg_ptr->modified = FALSE;
1303 if (pg_ptr->modified) {
1304 /* allow updates outside transactions for single-user mode */
1306 if (!db_cache || (EXCL_OPEN() && !trans_id)) {
1309 MEM_LOCK(&replu_ptr->task->Excl_locks);
1311 if (!db_cache || ((EXCL_OPEN() ||
1313 ( replu_ptr->task == Currtask.v.ptr ) ?
1314 excl_locks[lookup[pg_ptr->lu_slot].file] :
1315 replu_ptr->task->Excl_locks.ptr[replu_ptr->file]) &&
1318 excl_locks[lookup[pg_ptr->lu_slot].file]) && !trans_id)) {
1319 #endif /* MULTI_TASK */
1320 #endif /* SINGLE_USER */
1321 /* ix page swapping occurs here */
1322 dio_out(pg_ptr, replu_ptr, db_cache);
1323 pg_ptr->modified = FALSE;
1324 if ( db_cache ) --no_modheld;
1327 if (!use_ovfl || !cache_ovfl) continue; /* skip modified pages */
1328 /* Write out modified page */
1329 pg_ptr->modified = FALSE;
1330 --no_modheld; /* must be in db cache */
1331 if (o_write(pg_ptr, replu_ptr) != S_OKAY) return( db_status );
1334 MEM_UNLOCK(&replu_ptr->task->Excl_locks);
1337 pg_ptr->ovfl_addr = ovfl_addr;
1338 #endif /* NO_TRANS */
1339 pg_ptr->recently_used = TRUE;
1340 if ((*lru_ptr = (pg_slot + 1)) >= pgtab_sz)
1344 else if ( pg_ptr->holdcnt == 0 )
1345 pg_ptr->recently_used = FALSE;
1348 return( dberr(S_FAULT) );
1350 /* adjust lookup table */
1351 if (replu_ptr < lu_ptr) {
1357 while (replu_ptr < lu_ptr) {
1358 bytecpy(replu_ptr, replu_ptr + 1, sizeof(*replu_ptr));
1359 pg_table[replu_ptr->pg_slot].lu_slot = replu_ptr - lookup;
1363 else if (replu_ptr > lu_ptr) {
1369 while (replu_ptr > lu_ptr) {
1370 bytecpy(replu_ptr, replu_ptr - 1, sizeof(*replu_ptr));
1371 pg_table[replu_ptr->pg_slot].lu_slot = replu_ptr - lookup;
1378 pgsize = file_table[( lu_ptr->file > -1 ) ? lu_ptr->file : file].ft_pgsize;
1380 pgsize = ( db_cache )
1381 ? file_table[( lu_ptr->file > -1 ) ? lu_ptr->file : file].ft_pgsize
1382 : file_table[ov_file].ft_pgsize;
1388 if ( pgsize != file_table[file].ft_pgsize ) {
1389 Tempbuff.ptr = NULL;
1390 tempbuff = ALLOC(&Tempbuff, file_table[file].ft_pgsize, "dbpgbuff");
1392 return( dberr(S_NOMEMORY) );
1394 if ( pg_ptr->buff ) {
1395 MEM_UNLOCK(&pg_ptr->Buff);
1396 FREE(&pg_ptr->Buff);
1398 MEM_UNLOCK(&Tempbuff);
1399 pg_ptr->Buff = Tempbuff;
1401 #endif /* MULTI_TASK */
1404 lu_ptr->task = Currtask.v.ptr;
1406 lu_ptr->file = file;
1407 lu_ptr->pageno = page;
1408 lu_ptr->pg_slot = pg_slot;
1409 pg_ptr->lu_slot = lu_slot;
1410 if (xlu_ptr != NULL)
1412 if (xpg_ptr != NULL)
1416 last_dblu.task = lu_ptr->task;
1418 last_dblu.file = lu_ptr->file;
1419 last_dblu.pageno = lu_ptr->pageno;
1420 last_dblu.slot = lu_slot;
1421 dio_in(pg_ptr, lu_ptr);
1425 last_dblu.task = lu_ptr->task;
1427 last_dblu.file = lu_ptr->file;
1428 last_dblu.pageno = lu_ptr->pageno;
1429 last_dblu.slot = lu_slot;
1431 dio_in(pg_ptr, lu_ptr, db_cache);
1434 return( db_status );
1436 } /* dio_findpg() */
1439 /****************************************/
1443 /****************************************/
1444 /* Writes a page in the cache to file.
1445 * For byte order neutrality:
1446 * Each page is raima header data, then a bunch of slots.
1447 * The first 4 bytes of the page header is the timestamp
1448 * when the page was written, and it's swapped here.
1449 * Each slot is raima record header and user record data.
1450 * The user record data must already have been byte
1451 * swapped if necessary--to vista its just a large char buf.
1452 * The rest of the page header and the record header for each
1453 * slot is byte swapped before the io by calling the
1454 * page swap function.
1458 dio_out(pg_ptr, lu_ptr, db_cache)
1460 dio_out(pg_ptr, lu_ptr)
1462 PAGE_ENTRY FAR *pg_ptr; /* page table entry to be output */
1463 LOOKUP_ENTRY FAR *lu_ptr; /* corresponding lookup table entry */
1465 BOOLEAN db_cache; /* TRUE if pg_ptr is in db page cache */
1468 int desc; /* file descriptor */
1469 int fno; /* file number */
1470 int pgsize; /* size of page */
1471 long addr; /* file address */
1472 time_t host_timestamp;
1473 ULONG netorder_timestamp;
1475 MEM_LOCK(&pg_ptr->Buff);
1477 /* Get the current time in "network" format.
1478 * (Original vista code had it typed as a long.)
1480 time (&host_timestamp);
1481 netorder_timestamp = (ULONG) host_timestamp;
1482 HTONL (netorder_timestamp);
1486 pgsize = file_table[fno].ft_pgsize;
1487 addr = lu_ptr->pageno * (long)pgsize;
1488 memcpy (pg_ptr->buff, &netorder_timestamp, sizeof(ULONG));
1492 pgsize = file_table[fno].ft_pgsize;
1495 pgsize = file_table[ov_file].ft_pgsize;
1497 if ( pg_ptr->ovfl_addr == 0L ) {
1498 /* write to database */
1499 addr = lu_ptr->pageno * (long)pgsize;
1500 memcpy (pg_ptr->buff, &netorder_timestamp, sizeof(ULONG));
1503 /* write to overflow file */
1505 addr = pg_ptr->ovfl_addr;
1508 if ( dio_open(fno) == S_OKAY ) {
1509 swab_page (pg_ptr->buff, &file_table[fno], HTON);
1510 desc = file_table[fno].ft_desc;
1511 DB_LSEEK( desc, (off_t)addr, 0 );
1512 if (DB_WRITE( desc, pg_ptr->buff, pgsize ) != pgsize) dberr(S_BADWRITE);
1514 MEM_UNLOCK(&pg_ptr->Buff);
1515 return( db_status );
1520 /****************************************/
1524 /****************************************/
1526 /* Read in a page to the buffer
1528 static int dio_in(pg_ptr, lu_ptr)
1529 PAGE_ENTRY FAR *pg_ptr; /* page table entry to be input */
1530 LOOKUP_ENTRY FAR *lu_ptr; /* corresponding to pg_ptr */
1532 /* Read in a page to the buffer
1534 static int dio_in(pg_ptr, lu_ptr, db_cache )
1535 PAGE_ENTRY FAR *pg_ptr; /* page table entry to be input */
1536 LOOKUP_ENTRY FAR *lu_ptr; /* corresponding to pg_ptr */
1537 BOOLEAN db_cache; /* TRUE if pg_ptr in db cache */
1540 int desc; /* file descriptor */
1541 int fno; /* file number */
1542 int pgsize; /* page size */
1543 long addr; /* file address */
1544 PGZERO FAR *pgzero_ptr;
1545 FILE_ENTRY FAR *file_ptr;
1548 file_ptr = &file_table[fno = lu_ptr->file];
1550 pgsize = file_ptr->ft_pgsize;
1551 addr = lu_ptr->pageno*pgsize;
1553 pgsize = db_cache ? file_ptr->ft_pgsize : file_table[ov_file].ft_pgsize;
1555 if (pg_ptr->ovfl_addr == 0L) {
1556 /* read from database file */
1557 /* if !db_cache, overflow address not set on initial read */
1558 addr = db_cache ? lu_ptr->pageno*pgsize :
1559 (pg_ptr->ovfl_addr = lu_ptr->pageno);
1562 /* read from overflow file */
1563 file_ptr = &file_table[fno = ov_file];
1564 addr = pg_ptr->ovfl_addr;
1567 if ( dio_open(fno) == S_OKAY ) {
1568 desc = file_ptr->ft_desc;
1569 DB_LSEEK(desc, (off_t)addr, 0);
1570 MEM_LOCK(&pg_ptr->Buff);
1571 if ((r = DB_READ( desc, pg_ptr->buff, pgsize )) < pgsize) {
1572 byteset(&pg_ptr->buff[r], '\0', pgsize - r);
1573 DB_LSEEK(desc, (off_t)addr, 0);
1574 if (DB_WRITE( desc, pg_ptr->buff, pgsize ) != pgsize) {
1575 /* clean up and return out of space */
1576 DB_LSEEK(desc, (off_t)addr, 0);
1577 DB_WRITE(desc, "", 0);
1578 pgzero_ptr = &pgzero[fno];
1579 pgzero_ptr->pz_next--;
1580 pgzero_ptr->pz_modified = TRUE;
1585 swab_page (pg_ptr->buff, file_ptr, NTOH);
1586 MEM_UNLOCK(&pg_ptr->Buff);
1588 return( db_status );
1592 /***********************************************************************
1593 Page zero handling functions for data and key files
1594 ***********************************************************************/
1596 #ifndef NO_TIMESTAMP
1597 /* Increment and return file timestamp
1599 ULONG dio_pzsetts(fno )
1603 PGZERO FAR *pgzero_ptr;
1605 if ( db_tsrecs || db_tssets ) {
1606 pgzero_ptr = &pgzero[fno];
1607 pgzero_ptr->pz_modified = TRUE;
1608 ts = ++pgzero_ptr->pz_timestamp;
1617 /* Return file timestamp
1619 ULONG dio_pzgetts(fno)
1622 if ( pgzero[fno].pz_next == 0L )
1625 return ( pgzero[fno].pz_timestamp );
1630 /* Initialize page zero table
1632 static int dio_pzinit()
1635 PGZERO FAR *pgzero_ptr;
1638 if (debugging_dio_init) {
1639 printf (__FILE__"1430 dio_pzinit: szft=%d oldsz=%d\n",
1640 (int)size_ft, (int)old_size_ft);
1645 /* Macro references must be on one line for some compilers */
1646 if (ALLOC_TABLE(&db_global.Pgzero, size_ft*sizeof(PGZERO),
1647 old_size_ft*sizeof(PGZERO), "pgzero") != S_OKAY ) {
1649 if (debugging_dio_init) {
1650 printf (__FILE__"1444 pzinit: alloc_table failed, db_status=%d\n",
1655 return( db_status );
1658 /* read in page zeros */
1659 for (i = old_size_ft, pgzero_ptr = pgzero;
1661 ++i, ++pgzero_ptr) {
1662 pgzero_ptr->pz_dchain = 0L;
1663 pgzero_ptr->pz_next = 0L;
1664 pgzero_ptr->pz_timestamp = 0;
1665 pgzero_ptr->pz_modified = FALSE;
1667 return( db_status = S_OKAY );
1668 } /* dio_pzinit() */
1671 /****************************************/
1675 /****************************************/
1676 /* Flush page zero table
1677 * Complement to dio_out which writes all pages except page zero.
1679 static int dio_pzflush()
1683 register PGZERO FAR *pgzero_ptr;
1684 register FILE_ENTRY FAR *file_ptr;
1690 if ( (dboptions & TRLOGGING) && trans_id && !trcommit && use_ovfl ) {
1691 /* flush to overflow/log file -- before tx commit */
1692 for (i = 0, pgzero_ptr = pgzero; i < size_ft; ++i, ++pgzero_ptr) {
1693 if (pgzero_ptr->pz_modified )
1694 if ( o_pzwrite( i ) != S_OKAY ) return( db_status );
1699 /* flush modified page zeroes to database files */
1700 for (i = 0, pgzero_ptr = pgzero, file_ptr = file_table; i < size_ft;
1701 ++i, ++pgzero_ptr, ++file_ptr) {
1702 if ( pgzero_ptr->pz_modified ) {
1703 if ( dio_open(i) != S_OKAY )
1704 return( db_status );
1706 /* The only byte swap operations necessary
1707 * on a page zero are the first 5 LONG integers.
1709 for (j = 0, cptr = (char *) pgzero_ptr;
1710 j < PGZEROSZ/sizeof(LONG);
1711 ++j, cptr += sizeof(LONG)) {
1712 memcpy (&align_LONG, cptr, sizeof(LONG));
1714 memcpy (cptr, &align_LONG, sizeof(LONG));
1716 desc = file_ptr->ft_desc;
1717 DB_LSEEK(desc, (off_t)0L, 0);
1718 if (DB_WRITE(desc, (char FAR *)pgzero_ptr, PGZEROSZ) != PGZEROSZ)
1719 return( dberr(S_BADWRITE) );
1720 pgzero_ptr->pz_modified = FALSE;
1723 d_trlog(i, 0, (char FAR *)pgzero_ptr, PGZEROSZ);
1733 return( db_status = S_OKAY );
1734 } /* dio_pzflush() */
1737 /****************************************/
1741 /****************************************/
1742 /* Read a file's page zero
1746 FILE_NO fno; /* file number */
1748 FILE_ENTRY FAR *file_ptr;
1749 PGZERO FAR *pgzero_ptr;
1751 pgzero_ptr = &pgzero[fno];
1752 file_ptr = &file_table[fno];
1754 /* open this file, if not already open */
1756 if (file_ptr->ft_desc < 0) {
1757 pgzero_ptr->pz_dchain = 0;
1758 pgzero_ptr->pz_next = 0;
1759 pgzero_ptr->pz_timestamp = 0;
1760 pgzero_ptr->pz_modified = FALSE;
1761 return( db_status ); /* db_status set by dio_open */
1764 /* seek to and read page zero */
1765 DB_LSEEK(file_ptr->ft_desc, (off_t)0L, 0);
1766 if ( DB_READ(file_ptr->ft_desc, (char FAR *)pgzero_ptr, PGZEROSZ)
1768 return( dberr(S_BADREAD) );
1770 NTOHL (pgzero_ptr->pz_dchain);
1771 NTOHL (pgzero_ptr->pz_next);
1772 NTOHL (pgzero_ptr->pz_timestamp);
1773 return( db_status = S_OKAY );
1774 } /* dio_pzread() */
1778 /****************************************/
1782 /****************************************/
1783 /* Allocate new record slot or key node from page zero,
1784 * ie from delete chain if possible.
1785 * Returns memory address of the free slot into 'loc'.
1788 dio_pzalloc(fno, loc )
1789 FILE_NO fno; /* file number */
1790 F_ADDR *loc; /* pointer to allocated location */
1795 PGZERO FAR *pgzero_ptr;
1798 /* check shared access privileges */
1799 if ( dbopen == 1 && !trans_id && !excl_locks[fno] )
1800 return( dberr(S_NOTRANS) );
1803 pgzero_ptr = &pgzero[fno];
1804 if ( pgzero_ptr->pz_next == 0L )
1805 if ( dio_pzread(fno) != S_OKAY )
1806 RETURN( db_status );
1807 if ( file_table[fno].ft_type == KEY ) {
1808 if ( working_file != fno )
1809 return( dberr(S_NOWORK) );
1810 if ( pgzero_ptr->pz_dchain == NONE || ! (dboptions & DCHAINUSE) ) {
1811 if ( pgzero_ptr->pz_next == MAXRECORDS-1 )
1812 return( dberr(S_RECLIMIT) );
1813 pg = pgzero_ptr->pz_next++;
1816 pg = pgzero_ptr->pz_dchain;
1817 if ( dio_get( pg, (char FAR * FAR *)&ptr, NOPGHOLD ) != S_OKAY )
1818 return( db_status );
1819 /* Get the first key node on the delete chain.
1820 * (sizeof external timestamp set to 4 bytes)
1821 ****** bytecpy(&pgzero_ptr->pz_dchain,
1822 ****** ptr+sizeof(long)+sizeof(INT), sizeof(F_ADDR)); *********
1824 bytecpy (&pgzero_ptr->pz_dchain,
1825 ptr + sizeof(LONG) + sizeof(INT), sizeof(F_ADDR));
1829 if ( ! pgzero_ptr->pz_dchain || ! (dboptions & DCHAINUSE) ) {
1830 if ( pgzero_ptr->pz_next == MAXRECORDS )
1831 return( dberr(S_RECLIMIT) );
1832 pg = pgzero_ptr->pz_next++;
1835 pg = pgzero_ptr->pz_dchain;
1836 dba = ((NUM2EXT(fno, ft_offset) & FILEMASK) << FILESHIFT) | pg;
1837 if ( dio_read(dba, (char FAR * FAR *)&ptr, NOPGHOLD) != S_OKAY )
1838 return( db_status );
1839 bytecpy(&pgzero_ptr->pz_dchain, ptr+sizeof(INT), sizeof(F_ADDR));
1843 pgzero_ptr->pz_modified = TRUE;
1844 return( db_status = S_OKAY );
1845 } /* dio_pzalloc() */
1848 /****************************************/
1852 /****************************************/
1853 /* Delete record slot or key node from page zero
1856 dio_pzdel(fno, loc )
1857 FILE_NO fno; /* file number */
1858 F_ADDR loc; /* location to be freed */
1863 PGZERO FAR *pgzero_ptr;
1866 /* check shared access privileges */
1867 if ( dbopen == 1 && !trans_id && !excl_locks[fno] )
1868 return( dberr(S_NOTRANS) );
1871 pgzero_ptr = &pgzero[fno];
1872 if ( pgzero_ptr->pz_next == 0L )
1873 if ( dio_pzread(fno) != S_OKAY )
1874 RETURN( db_status );
1875 if ( file_table[fno].ft_type == KEY ) {
1876 if ( working_file != fno )
1877 return( dberr(S_NOWORK) );
1878 if ( dio_get( loc, (char FAR * FAR *)&ptr, PGHOLD ) != S_OKAY )
1879 return( db_status );
1880 /*********************************************
1881 * Delete chain ptr in key node page is in location
1882 * of orphan ptr, bytes 6 - 9, not bytes 4 - 7
1883 * as printed in raima User Guide.
1884 * (sizeof external timestamp set to 4 bytes).
1885 ****** bytecpy(ptr+sizeof(long)+sizeof(INT),
1886 ****** &pgzero_ptr->pz_dchain, sizeof(F_ADDR)); *********
1887 *****************************************/
1888 bytecpy (ptr + sizeof(LONG) + sizeof(INT),
1889 &pgzero_ptr->pz_dchain, sizeof(F_ADDR));
1890 pgzero_ptr->pz_dchain = loc;
1894 dba = ((NUM2EXT(fno, ft_offset) & FILEMASK) << FILESHIFT) | loc;
1895 if ( dio_read( dba, (char FAR * FAR *)&ptr , NOPGHOLD) != S_OKAY )
1896 return( db_status );
1897 bytecpy(&recnum, ptr, sizeof(INT));
1898 recnum = ~recnum; /* indicates deleted record */
1899 bytecpy(ptr, &recnum, sizeof(INT));
1900 bytecpy(ptr+sizeof(INT), &pgzero_ptr->pz_dchain, sizeof(F_ADDR));
1901 pgzero_ptr->pz_dchain = loc;
1902 if ( dio_write(dba, NULL, NOPGFREE) != S_OKAY )
1903 return( db_status );
1905 pgzero_ptr->pz_modified = TRUE;
1906 return( db_status = S_OKAY );
1910 /****************************************/
1914 /****************************************/
1915 /* Return pz_next for file fno
1917 F_ADDR dio_pznext(fno)
1920 if ( pgzero[fno].pz_next == 0L )
1922 return ( pgzero[fno].pz_next );
1925 /****************************************/
1929 /****************************************/
1930 /* Clear page zero cache
1935 register PGZERO FAR *pgzero_ptr;
1937 for (i = 0, pgzero_ptr = pgzero; i < size_ft; i++, pgzero_ptr++) {
1938 if (pgzero_ptr->pz_modified) {
1939 pgzero_ptr->pz_next = 0L;
1940 pgzero_ptr->pz_modified = FALSE;
1945 /* vpp -nOS2 -dUNIX -nBSD -nVANILLA_BSD -nVMS -nMEMLOCK -nWINDOWS -nFAR_ALLOC -f/usr/users/master/config/nonwin dio.c */