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.
126 int debugging_dio_init = FALSE;
127 int debugging_dio_close = FALSE;
132 /* On MS-DOS networks, files must be closed whenever a lock is freed.
133 Function dio_clrfile is called whenever a lock is freed to clear
134 from the cache the pages of the file whose lock is being freed.
135 CLosing and opening files on Unix, VMS and other host computers,
136 however, is very slow and is not necessary for database integrity.
137 The following constant definition specifies whether or not the files
138 need to be closed. A definition per supported MS-DOS compiler is
153 /*------------ transaction logging data ------------*/
154 #define DEFIXPAGES 4 /* default number of index cache pages */
155 #define MINIXPAGES 2 /* minimum number of index cache pages */
156 int ix_pgtab_sz = DEFIXPAGES;
157 LOOKUP_ENTRY_P Ix_lookup = POINTER_INIT(); /* index page lookup table */
158 PAGE_ENTRY_P Ixpg_table = POINTER_INIT(); /* index page table */
159 static int ixpg_lru_slot; /* least recently accessed ix page */
161 /* transaction logging enabled flag */
162 int trlog_flag = 0; /* set only by user implemented functions */
164 BOOLEAN use_ovfl = YES; /* Default to using overflow */
165 CHAR_P Dbpgbuff = POINTER_INIT(); /* allocated by dio_init used by o_update */
166 /*------------ end of transaction logging data ------------*/
167 #endif /* NO_TRANS */
170 #define EXCL_OPEN() (dbopen >= 2)
172 #define EXCL_OPEN() (TRUE)
175 #define DEFDBPAGES 16 /* default number of database cache pages */
176 #define MINDBPAGES 8 /* minimum number of database cache pages */
178 extern BOOLEAN trcommit;
180 int db_pgtab_sz = DEFDBPAGES;
182 LOOKUP_ENTRY_P Db_lookup = POINTER_INIT(); /* database page lookup table */
183 PAGE_ENTRY_P Dbpg_table = POINTER_INIT(); /* database page table */
192 } last_dblu; /* last found lookup entry in cache */
194 /* maximum number of open files allowed by
195 operating system (user settable) */
196 /* On VMS systems, max_open_files need to be defined with a globaldef
197 instead of just a normal external. This will force this module to be
198 included, thus giving a default value to max_open_files. If it were
199 just a normal external the VMS linker would not load this module unless
200 a reference to a function in it is made and it would leave max_open_files
201 with a value of 0. */
202 int max_open_files = 8;
203 INT_P Used_files = POINTER_INIT(); /* LRU file table */
204 int cnt_open_files = 0; /* count of currently open files */
205 static int last_file = 0; /* least recently used file */
207 static int dbpg_lru_slot; /* least recently accessed db page */
208 static int no_modheld; /* number of modified or held db pages */
209 static FILE_NO working_file; /* current key file being processed */
211 static void cache_init(P1(int) Pi(LOOKUP_ENTRY FAR *)
212 Pi(PAGE_ENTRY FAR *) Pi(int));
213 static int dio_pzinit(P0);
214 static int clear_cache(P1(FILE_NO) Pi(FILE_NO));
215 static int dio_pzflush(P0);
217 static int dio_in(P1(PAGE_ENTRY FAR *) Pi(LOOKUP_ENTRY FAR *));
219 static int dio_in(P1(PAGE_ENTRY FAR *) Pi(LOOKUP_ENTRY FAR *)
223 #define used_files Used_files.ptr
224 #define db_lookup Db_lookup.ptr
225 #define dbpg_table Dbpg_table.ptr
229 /* Set the maximum number of open db_VISTA files
235 if ( dbpg_table ) return( dberr(S_DBCLOSE) );
237 if ( num > 0 && num < 256 )
238 max_open_files = num;
240 return( db_status = S_OKAY );
244 /* Set number of virtual memory pages
247 d_setpages(dbpgs, ixpgs)
248 int dbpgs; /* # of db cache pages */
249 int ixpgs; /* # of index cache pages - ignored in single-user version */
251 if ( dbpg_table ) return( dberr(S_SETPAGES) );
253 db_pgtab_sz = (dbpgs <= MINDBPAGES) ? MINDBPAGES : dbpgs;
257 ix_pgtab_sz = (ixpgs <= MINIXPAGES) ? MINIXPAGES : ixpgs;
260 return( db_status = S_OKAY );
264 /****************************************/
268 /****************************************/
269 /* Open a database file
275 FILE_ENTRY FAR *file_ptr, FAR *lru_file_ptr;
276 register int FAR *uf_ptr;
278 file_ptr = &file_table[fno];
279 if ( file_ptr->ft_status == CLOSED ) {
280 if ( cnt_open_files == max_open_files ) {
281 /* find least recently used file */
282 uf_ptr = &used_files[last_file];
283 lru_file_ptr = &file_table[last_file];
284 while (*uf_ptr || (lru_file_ptr->ft_status == CLOSED)) {
286 if (++last_file >= size_ft) {
288 lru_file_ptr = file_table;
296 dio_close(last_file);
297 if (++last_file >= size_ft)
300 used_files[fno] = TRUE;
302 file_ptr->ft_desc = open_b(file_ptr->ft_name, db_oflag);
303 if (file_ptr->ft_desc < 0)
304 return( dberr( S_NOFILE ) );
305 file_ptr->ft_status = OPEN;
308 return( db_status = S_OKAY );
312 /****************************************/
316 /****************************************/
317 /* Close a database file
323 FILE_ENTRY FAR *file_ptr;
325 file_ptr = &file_table[fno];
326 if ( file_ptr->ft_status == OPEN ) {
327 DB_CLOSE( file_ptr->ft_desc );
328 file_ptr->ft_status = CLOSED;
331 return( db_status = S_OKAY );
335 /****************************************/
339 /****************************************/
340 /* Initialize database I/O
346 #define tempbuff Tempbuff.ptr
349 if (debugging_dio_init) {
350 printf (__FILE__"300 dio_init: dbpgtab=%p pgsz=%d largest=%d\n",
351 (void *) dbpg_table, (int)page_size, (int)largest_page);
357 if ( dio_pzinit() != S_OKAY ) {
360 if ( page_size > largest_page ) {
361 if ( (tempbuff = ALLOC(&Tempbuff, page_size, "tempbuff")) == NULL )
362 return( dberr(S_NOMEMORY) );
364 MEM_UNLOCK(&Dbpgbuff);
368 largest_page = page_size;
371 if (debugging_dio_init) {
372 printf (__FILE__"323 dio_init: pzinited ok. pgsz=%d largest=%d\n",
373 (int)page_size, (int)largest_page);
379 } /* end if ( dbpg_table ) */
382 /* Macro references must be on one line for some compilers */
383 (int FAR *)ALLOC(&Used_files, (size_ft+1)*sizeof(int), "used_files");
385 /* Macro references must be on one line for some compilers */
387 ALLOC(&Db_lookup, db_pgtab_sz*sizeof(LOOKUP_ENTRY), "db_lookup");
389 /* Macro references must be on one line for some compilers */
391 ALLOC(&Dbpg_table, db_pgtab_sz*sizeof(PAGE_ENTRY), "dbpg_table");
393 if (debugging_dio_init) {
394 printf (__FILE__"345 dio_init: usedfls=%p lookup=%p pgtab=%p\n",
395 (void *) used_files, (void *) db_lookup, (void *) dbpg_table);
399 if ( !used_files || !dbpg_table || !db_lookup )
400 return( dberr(S_NOMEMORY) );
401 byteset(used_files, 0, (size_ft + 1)*sizeof(*used_files));
404 last_dblu.task = NULL;
407 last_dblu.pageno = -1L;
410 /* initialize database cache */
411 cache_init((int)db_pgtab_sz, db_lookup, dbpg_table, (int)page_size);
412 /***cache_init(db_pgtab_sz, db_lookup, dbpg_table, page_size);****/
413 if (db_status != S_OKAY) return(db_status);
417 /* Macro references must be on one line for some compilers */
419 ALLOC(&Ix_lookup, ix_pgtab_sz*sizeof(LOOKUP_ENTRY),"ix_lookup");
421 /* Macro references must be on one line for some compilers */
423 ALLOC(&Ixpg_table, ix_pgtab_sz*sizeof(PAGE_ENTRY), "ixpg_table");
424 if ( !ix_lookup || !ixpg_table )
425 return( dberr(S_NOMEMORY) );
427 cache_init(ix_pgtab_sz, ix_lookup, ixpg_table, IX_PAGESIZE);
428 if (db_status != S_OKAY)
431 if ( (dbpgbuff = ALLOC(&Dbpgbuff, page_size, "dbpgbuff")) == NULL )
432 return( dberr(S_NOMEMORY) );
436 #endif /* NO_TRANS */
442 /* initialize the page zero table and return */
444 if (debugging_dio_init) {
445 puts (__FILE__"390 dio_init: last act is call to dio_pzinit.");
449 return( dio_pzinit() );
454 static void cache_init (pg_cnt, lu_ptr, pg_ptr, pgsize)
456 LOOKUP_ENTRY FAR * lu_ptr;
457 PAGE_ENTRY FAR * pg_ptr;
463 if (debugging_dio_init) {
464 printf (__FILE__"400 cache_init: pgcnt=%d lu=%p pgp=%p pgsz=%d\n",
465 pg_cnt, (void *) lu_ptr, (void *) pg_ptr, pgsize);
470 for (pg_no = 0; pg_no < pg_cnt; ++pg_no, ++lu_ptr, ++pg_ptr)
476 lu_ptr->pageno = -1L;
477 lu_ptr->pg_slot = pg_no;
479 pg_ptr->lu_slot = pg_no;
480 pg_ptr->recently_used = FALSE;
481 pg_ptr->modified = FALSE;
484 pg_ptr->ovfl_addr = 0L;
486 pg_ptr->buff = ALLOC(&pg_ptr->Buff, pgsize, db_avname);
487 if (pg_ptr->buff == NULL) {
489 if (debugging_dio_init) {
490 printf (__FILE__"428 cache_init: alloc failed pgsz=%d\n",
498 MEM_UNLOCK(&pg_ptr->Buff);
499 } /* end loop on pg_cnt */
504 /****************************************/
508 /****************************************/
509 /* Free the memory allocated for pages
513 register int pgt_lc; /* loop control */
514 register PAGE_ENTRY FAR *pg_ptr;
517 if ( task_count > 1 ) {
521 MEM_UNLOCK(&db_global.Pgzero);
522 FREE(&db_global.Pgzero);
523 MEM_UNLOCK(&Used_files);
525 MEM_UNLOCK(&Db_lookup);
527 for (pgt_lc = db_pgtab_sz, pg_ptr = dbpg_table; --pgt_lc >= 0; ++pg_ptr) {
528 MEM_UNLOCK(&pg_ptr->Buff);
531 MEM_UNLOCK(&Dbpg_table);
535 MEM_UNLOCK(&Ix_lookup);
537 for (pgt_lc = ix_pgtab_sz, pg_ptr = ixpg_table; --pgt_lc >= 0; ++pg_ptr) {
538 MEM_UNLOCK(&pg_ptr->Buff);
541 MEM_UNLOCK(&Ixpg_table);
543 MEM_UNLOCK(&Dbpgbuff);
550 /****************************************/
554 /****************************************/
555 /* Clear pages for a single file.
559 register FILE_NO fno;
561 return( clear_cache(fno, fno+1) );
566 /****************************************/
570 /****************************************/
571 /* Clear all pages for *all* files from I/O buffer
576 return( clear_cache(0, size_ft) );
580 /****************************************/
584 /****************************************/
585 /* Clear database page cache.
586 * Clears all pages for a range of specified files.
587 * Subroutine of dio_clrfile and dio_clear.
589 static int clear_cache(fr_file, to_file )
590 FILE_NO fr_file; /* clear from file "fr_file" */
591 FILE_NO to_file; /* ..to (not thru) file "to_file" */
593 FILE_NO s_file; /* start file to be cleared */
594 FILE_NO e_file; /* end file (+1) to be cleared */
596 LOOKUP_ENTRY FAR *lu_ptr, FAR *lu2_ptr;
598 PAGE_ENTRY FAR *pg_ptr;
599 PGZERO FAR *pgzero_ptr;
600 FILE_ENTRY FAR *file_ptr;
602 int FAR *appl_ptr, FAR *excl_ptr;
607 We only clear pages which are not from static files and are
608 not still locked. The check on app_locks is made to implement
609 the ability to hold locks after the end of a transaction
611 for (s_file = e_file = fr_file, file_ptr = &file_table[e_file],
612 appl_ptr = &app_locks[e_file], excl_ptr = &excl_locks[e_file];
614 ++file_ptr, ++appl_ptr, ++excl_ptr) {
616 for (s_file = e_file = fr_file, file_ptr = &file_table[e_file];
620 if ((e_file < to_file) &&
622 ((dbopen >= 2) || (!*appl_ptr && !*excl_ptr)) &&
624 !(file_ptr->ft_flags & STATIC))
627 if (s_file < e_file) {
628 /* find range of pages to be cleared */
629 dio_findpg(s_file, 0L, NULL, NULL, &lu_ptr);
630 dio_findpg(e_file, 0L, NULL, NULL, &lu2_ptr);
633 last_dblu.task = NULL;
636 last_dblu.pageno = -1L;
639 if (lu_ptr < lu2_ptr) { /* otherwise file has no pages in cache */
640 /* adjust lookup table entries */
641 while ((lu_ptr > db_lookup) && ((--lu_ptr)->file >= 0)) {
645 lu2_ptr->task = lu_ptr->task;
647 lu2_ptr->file = lu_ptr->file;
648 lu2_ptr->pageno = lu_ptr->pageno;
649 /* exchange page slot numbers */
650 pg_slot = lu_ptr->pg_slot;
651 lu_ptr->pg_slot = lu2_ptr->pg_slot;
652 lu2_ptr->pg_slot = pg_slot;
653 dbpg_table[pg_slot].lu_slot = lu2_ptr - db_lookup;
654 dbpg_table[lu_ptr->pg_slot].lu_slot = lu_ptr - db_lookup;
657 if ( lu_ptr->file < 0 )
660 while (lu_ptr < lu2_ptr) {
666 lu_ptr->pageno = -1L;
667 pg_ptr = &dbpg_table[lu_ptr->pg_slot];
668 if ( pg_ptr->modified || pg_ptr->holdcnt ) {
670 pg_ptr->modified = FALSE;
672 pg_ptr->recently_used = FALSE;
675 pg_ptr->ovfl_addr = 0L;
680 /* clear page zeroes and close files */
681 for (i = s_file, pgzero_ptr = &pgzero[i];
684 pgzero_ptr->pz_modified = FALSE;
685 pgzero_ptr->pz_next = 0L;
694 return( db_status = S_OKAY );
695 } /* clear_cache() */
698 /****************************************/
702 /****************************************/
703 /* Flushes entire database I/O cache.
704 * Writes out all modified cache pages to respective files (dio_out),
705 * then writes out page zero (dio_pzflush).
709 register int pgt_lc; /* loop control */
713 PAGE_ENTRY FAR *pg_ptr;
714 LOOKUP_ENTRY FAR *lu_ptr;
717 if (debugging_dio_close) {
718 printf (__FILE__"685 dio_flush: check cache dbpgtab=%p count=%d\n",
719 (void *) dbpg_table, (int)db_pgtab_sz);
723 if ( dbpg_table == NULL ) return( db_status = S_OKAY );
725 for (pgt_lc = db_pgtab_sz, pg_ptr = dbpg_table; --pgt_lc >= 0; ++pg_ptr) {
726 if (!pg_ptr->modified) {
728 pg_ptr->ovfl_addr = 0L; /*[612]*/
732 lu_ptr = &db_lookup[pg_ptr->lu_slot];
734 if ( lu_ptr->task != Currtask.v.ptr ) {
739 if ((dboptions & TRLOGGING) && trans_id && !trcommit && use_ovfl) {
740 /* flush to overflow/log file -- before tr commit */
741 if (o_write(pg_ptr, lu_ptr) != S_OKAY) return( db_status );
742 if ( lu_ptr->pageno > o_pages(lu_ptr->file) ) {
743 /* no need to rewrite this page at trcommit time */
745 pg_ptr->modified = FALSE;
750 pg_ptr->ovfl_addr = 0L;
752 /* write directly to database */
755 if (debugging_dio_close) {
756 printf (__FILE__"723 dio_flush: write modified pg#%d @ %p\n",
757 db_pgtab_sz - pgt_lc, (void *) pg_ptr);
761 if (dio_out(pg_ptr, lu_ptr) != S_OKAY) return( db_status );
763 if (dio_out(pg_ptr, lu_ptr, 1) != S_OKAY) return( db_status );
766 pg_ptr->modified = FALSE;
771 MEM_LOCK(&pg_ptr->Buff);
772 d_trlog(fno, (int)lu_ptr->pageno, pg_ptr->buff,
773 file_table[fno].ft_pgsize);
774 MEM_UNLOCK(&pg_ptr->Buff);
778 /* store the page zero values in the data file and return */
779 return( dio_pzflush() );
784 /* Set the default file number
786 void dio_setdef( file_no )
789 working_file = file_no;
794 /****************************************/
798 /****************************************/
799 /* Database I/O page get
802 dio_get( page_no, page_ptr, hold )
804 char FAR * FAR *page_ptr;
807 PAGE_ENTRY FAR *pg_ptr;
811 if ( !app_locks[working_file] && !excl_locks[working_file] &&
812 !(file_table[working_file].ft_flags & STATIC) )
813 return( dberr(S_NOTLOCKED) );
816 if ( pgzero[working_file].pz_next == 0L )
817 if ( dio_pzread(working_file) != S_OKAY )
820 if (dio_findpg(working_file, page_no, dbpg_table, &pg_ptr, NULL) == S_OKAY) {
821 MEM_LOCK(&pg_ptr->Buff);
822 *page_ptr = pg_ptr->buff;
823 pg_ptr->recently_used = TRUE;
824 used_files[working_file] = TRUE;
826 if ( ++pg_ptr->holdcnt > 1 )
828 else if ( ! pg_ptr->modified )
837 /****************************************/
841 /****************************************/
842 /* Set modified flag for a page
848 PAGE_ENTRY FAR *pg_ptr;
851 /* ensure overflow data is initialized when exclusive db access */
852 if ((trans_id && (dboptions & TRLOGGING) && use_ovfl) &&
853 (o_fileinit(working_file) != S_OKAY))
858 /* check shared access privileges */
859 if ( !trans_id && !excl_locks[working_file] )
860 return( dberr(S_NOTRANS) );
861 if ( app_locks[working_file] >= 0 && !excl_locks[working_file] )
862 return( dberr( S_NOTLOCKED ) );
865 if (dio_findpg(working_file, page_no, dbpg_table, &pg_ptr, NULL) == S_OKAY ) {
866 pg_ptr->recently_used = TRUE;
867 used_files[working_file] = TRUE;
868 if ( ! pg_ptr->modified ) {
869 pg_ptr->modified = TRUE;
870 if ( ! pg_ptr->holdcnt )
873 if ( pg_ptr->holdcnt > 0 ) {
875 if ( pg_ptr->holdcnt ) {
878 MEM_UNLOCK(&pg_ptr->Buff);
886 /****************************************/
890 /****************************************/
892 * Merely returns ptr into rec in a page
893 * unless a page swap is necessary.
896 dio_read( dba, recptr, hold )
898 char FAR * FAR *recptr;
904 FILE_ENTRY FAR *file_ptr;
905 PAGE_ENTRY FAR *pg_ptr;
907 file = NUM2INT((FILE_NO)((dba >> FILESHIFT) & FILEMASK), ft_offset);
908 file_ptr = &file_table[file];
910 if ( pgzero[file].pz_next == 0L )
911 if ( dio_pzread(file) != S_OKAY )
916 /* check shared access privileges */
917 if (!app_locks[file] &&
919 !(file_ptr->ft_flags & STATIC))
920 return( dberr(S_NOTLOCKED) );
923 us1 = ADDRMASK & dba;
924 us2 = (us1 - 1)/file_ptr->ft_slots;
925 if (dio_findpg(file, us2 + 1, dbpg_table, &pg_ptr, NULL) == S_OKAY ) {
926 pg_ptr->recently_used = TRUE;
927 used_files[file] = TRUE;
928 offset = file_ptr->ft_slsize*(int)(us1 - 1 - us2*file_ptr->ft_slots) +
930 MEM_LOCK(&pg_ptr->Buff);
931 *recptr = &pg_ptr->buff[offset];
933 if ( (++pg_ptr->holdcnt == 1) && !pg_ptr->modified) {
942 /****************************************/
946 /****************************************/
947 /* Database I/O write: copies data record into a page slot.
948 * Finds record's page, swapping it into cache if necessary.
949 * Sets page's 'touched' flags, timestamps, etc.
950 * If recptr not NULL, copies rec to page cache.
953 dio_write( dba, recptr, release )
955 CONST char FAR *recptr;
961 FILE_ENTRY FAR *file_ptr;
962 PAGE_ENTRY FAR *pg_ptr;
964 file = NUM2INT((FILE_NO)((dba >> FILESHIFT) & FILEMASK), ft_offset);
967 /* ensure overflow data is initialized when exclusive db access */
968 if ((trans_id && (dboptions & TRLOGGING) && use_ovfl) &&
969 (o_fileinit(file) != S_OKAY))
974 if (!trans_id && !excl_locks[file])
975 return( dberr(S_NOTRANS) );
977 /* check shared access privileges */
978 if ( app_locks[file] >= 0 && !excl_locks[file] )
979 return( dberr(S_NOTLOCKED) );
982 file_ptr = &file_table[file];
983 us1 = ADDRMASK & dba;
984 us2 = (us1 - 1)/file_ptr->ft_slots;
985 if (dio_findpg(file, us2 + 1, dbpg_table, &pg_ptr, NULL) == S_OKAY ) {
986 pg_ptr->recently_used = TRUE;
987 used_files[file] = TRUE;
988 if ( recptr != NULL ) {
989 offset = file_ptr->ft_slsize*(int)(us1 - 1 - us2*file_ptr->ft_slots) +
991 MEM_LOCK(&pg_ptr->Buff);
992 bytecpy(&pg_ptr->buff[offset], recptr, file_ptr->ft_slsize);
993 MEM_UNLOCK(&pg_ptr->Buff);
995 if ( ! pg_ptr->modified ) {
996 pg_ptr->modified = TRUE;
997 if ( ! pg_ptr->holdcnt )
1001 if ( --pg_ptr->holdcnt < 0 )
1003 MEM_UNLOCK(&pg_ptr->Buff);
1006 return( db_status );
1010 /* Release database page hold
1018 PAGE_ENTRY FAR *pg_ptr;
1020 file = NUM2INT((FILE_NO)((dba >> FILESHIFT) & FILEMASK), ft_offset);
1021 us1 = ADDRMASK & dba;
1022 us2 = file_table[file].ft_slots;
1023 if (dio_findpg(file, ((us1 - 1)/us2) + 1, dbpg_table, &pg_ptr,
1025 if (pg_ptr->holdcnt) {
1027 if ( !pg_ptr->holdcnt && !pg_ptr->modified )
1029 MEM_UNLOCK(&pg_ptr->Buff);
1032 return( db_status );
1038 /* Read record lock bit
1044 FILE_NO file; /* file number */
1045 F_ADDR page; /* page number */
1046 F_ADDR sno; /* slot number */
1047 F_ADDR spp; /* slots per page */
1048 F_ADDR offset; /* lseek address - offset from start of file */
1049 FILE_ENTRY FAR *file_ptr;
1051 file = NUM2INT((FILE_NO)((dba >> FILESHIFT) & FILEMASK), ft_offset);
1052 if ( dio_open(file) == S_OKAY ) {
1053 file_ptr = &file_table[file];
1054 sno = ADDRMASK & dba;
1055 spp = file_ptr->ft_slots;
1056 page = (sno - 1)/spp + 1;
1057 offset = PGHDRSIZE + page*file_ptr->ft_pgsize +
1058 (sno - 1 - (page - 1)*spp)*file_ptr->ft_slsize;
1059 DB_LSEEK(file_ptr->ft_desc, (off_t)offset, 0);
1060 if ( DB_READ(file_ptr->ft_desc, (char FAR *)rid, sizeof(INT))
1066 return( db_status );
1070 /* Write record lock bit
1076 FILE_NO file; /* file number */
1077 F_ADDR page; /* page number */
1078 F_ADDR sno; /* slot number */
1079 F_ADDR spp; /* slots per page */
1080 F_ADDR offset; /* offset from start of page or file */
1081 int clr_in_tx; /* true if called from d_rlbclr in trx */
1082 INT trid; /* [333] working rid */
1083 FILE_ENTRY FAR *file_ptr;
1084 PAGE_ENTRY FAR *pg_ptr;
1086 file = NUM2INT((FILE_NO)((dba >> FILESHIFT) & FILEMASK), ft_offset);
1087 file_ptr = &file_table[file];
1088 sno = ADDRMASK & dba;
1089 spp = file_ptr->ft_slots;
1090 page = ((sno - 1)/spp) + 1;
1091 offset = PGHDRSIZE + (sno - 1 - (page - 1)*spp)*file_ptr->ft_slsize;
1092 clr_in_tx = !(rid & RLBMASK) && trans_id;
1094 if ( dbopen > 1 || (app_locks[file] || excl_locks[file]) ) {
1095 /* file is locked - check if record in cache */
1096 if (dio_findpg(file, page, dbpg_table, &pg_ptr, NULL) == S_OKAY) {
1097 MEM_LOCK(&pg_ptr->Buff);
1098 /* record in cache - update only rlb in rid */
1099 bytecpy(&trid, &pg_ptr->buff[offset], sizeof(INT));
1100 MEM_UNLOCK(&pg_ptr->Buff);
1101 rid = (trid & ~((INT)RLBMASK)) | (rid & RLBMASK);
1102 bytecpy(&pg_ptr->buff[offset], &rid, sizeof(INT));
1104 /* clearing within a transaction requires touching page */
1105 if ( ! pg_ptr->modified ) {
1106 pg_ptr->modified = TRUE;
1107 if ( ! pg_ptr->holdcnt )
1115 if ( ! clr_in_tx ) {
1116 /* update only rlb directly to disk */
1117 if ( dio_open(file) == S_OKAY ) {
1118 offset += page*file_ptr->ft_pgsize;
1120 /* read rid from disk, and set/clear rlb accordingly */
1121 DB_LSEEK(file_ptr->ft_desc, (off_t)offset, 0);
1122 if ( DB_READ(file_ptr->ft_desc, (char FAR *)&trid, sizeof(INT))
1127 rid = (trid & ~((INT)RLBMASK)) | (rid & RLBMASK);
1129 /* write original rid out with modified rlb */
1130 trid = htons (rid); /* make a copy in trid for byte swap */
1131 DB_LSEEK(file_ptr->ft_desc, (off_t)offset, 0); /* reseek */
1132 if ( DB_WRITE(file_ptr->ft_desc, (char FAR *)&trid, sizeof(INT)) !=
1137 return( db_status );
1139 #endif /* SINGLE_USER */
1142 /****************************************/
1146 /****************************************/
1147 /* Search a cache for page
1150 dio_findpg(file, page, pg_table, xpg_ptr, xlu_ptr )
1151 FILE_NO file; /* file number = 0..size_ft-1 */
1152 F_ADDR page; /* database page number */
1153 PAGE_ENTRY FAR *pg_table; /* = dbpg_table, ixpg_table, or NULL */
1154 PAGE_ENTRY FAR * FAR *xpg_ptr; /* pointer to page table entry for found page */
1155 LOOKUP_ENTRY FAR * FAR *xlu_ptr;/* pointer to lookup table slot for found page*/
1159 #define tempbuff Tempbuff.ptr
1161 LOOKUP_ENTRY FAR *lookup; /* = db_lookup or ix_lookup */
1162 int pgtab_sz; /* = db_pgtab_sz or ix_pgtab_sz */
1165 register int lu_slot, l, u;
1166 LOOKUP_ENTRY FAR *lu_ptr, FAR *replu_ptr;
1167 PAGE_ENTRY FAR *pg_ptr;
1171 BOOLEAN db_cache; /* TRUE if currently using dbpg_table */
1180 /* check if desired page was last one */
1182 if ((Currtask.v.ptr == last_dblu.task) && (file == last_dblu.file) && (page == last_dblu.pageno)) {
1184 if ((file == last_dblu.file) && (page == last_dblu.pageno)) {
1186 if (xlu_ptr != NULL)
1187 *xlu_ptr = &db_lookup[last_dblu.slot];
1188 if (xpg_ptr != NULL)
1189 *xpg_ptr = &dbpg_table[db_lookup[last_dblu.slot].pg_slot];
1190 return( db_status = S_OKAY );
1193 pgtab_sz = db_pgtab_sz;
1194 #else /* NO_TRANS */
1195 if (db_cache = (!pg_table || (pg_table == dbpg_table))) {
1196 /* check if desired page was last one */
1198 if ((Currtask.v.ptr == last_dblu.task) && (file == last_dblu.file) &&
1199 (page == last_dblu.pageno)) {
1201 if ((file == last_dblu.file) && (page == last_dblu.pageno)) {
1203 if (xlu_ptr != NULL)
1204 *xlu_ptr = &db_lookup[last_dblu.slot];
1205 if (xpg_ptr != NULL)
1206 *xpg_ptr = &dbpg_table[db_lookup[last_dblu.slot].pg_slot];
1207 return( db_status = S_OKAY );
1210 pgtab_sz = db_pgtab_sz;
1214 pgtab_sz = ix_pgtab_sz;
1216 #endif /* NO_TRANS */
1217 /* perform binary search of sorted lookup table */
1221 lu_ptr = &lookup[lu_slot = (l + u)/2];
1223 if ((cmp = Currtask.v.ptr - lu_ptr->task) == 0)
1225 if ((cmp = file - lu_ptr->file) == 0)
1226 cmp = page - lu_ptr->pageno;
1237 last_dblu.task = lu_ptr->task;
1239 last_dblu.file = lu_ptr->file;
1240 last_dblu.pageno = lu_ptr->pageno;
1241 last_dblu.slot = lu_slot;
1245 if (xlu_ptr != NULL)
1247 if (xpg_ptr != NULL)
1248 *xpg_ptr = &pg_table[lu_ptr->pg_slot];
1249 return( db_status = S_OKAY );
1253 /* null page table indicates that only a lookup was desired */
1256 if (xlu_ptr != NULL)
1258 return( db_status = S_NOTFOUND );
1260 /* page not found - read into cache */
1262 if( !use_ovfl && trans_id && (no_modheld == pgtab_sz) )
1263 return( db_status = S_TRCHANGES );
1265 /* check to see if page is in overflow file */
1267 if ( cache_ovfl && file != ov_file ) {
1268 if ( o_search( file, page, &ovfl_addr ) != S_OKAY )
1269 return( db_status );
1271 /* check for overflow */
1272 if ( db_cache && trans_id && (no_modheld == pgtab_sz) && !cache_ovfl ) {
1275 /* select a page to replace */
1277 lru_ptr = &dbpg_lru_slot;
1279 lru_ptr = &ixpg_lru_slot;
1282 /* select a page to replace */
1283 lru_ptr = &dbpg_lru_slot;
1284 #endif /* NO_TRANS */
1285 for (cnt = 2*pgtab_sz, pg_slot = *lru_ptr, pg_ptr = &pg_table[pg_slot];
1287 ++pg_slot, ++pg_ptr) {
1288 if (pg_slot >= pgtab_sz)
1293 replu_ptr = &lookup[pg_ptr->lu_slot];
1294 if (!pg_ptr->recently_used && (pg_ptr->holdcnt == 0)) {
1296 if (pg_ptr->modified) {
1297 dio_out(pg_ptr, replu_ptr);
1298 pg_ptr->modified = FALSE;
1302 if (pg_ptr->modified) {
1303 /* allow updates outside transactions for single-user mode */
1305 if (!db_cache || (EXCL_OPEN() && !trans_id)) {
1308 MEM_LOCK(&replu_ptr->task->Excl_locks);
1310 if (!db_cache || ((EXCL_OPEN() ||
1312 ( replu_ptr->task == Currtask.v.ptr ) ?
1313 excl_locks[lookup[pg_ptr->lu_slot].file] :
1314 replu_ptr->task->Excl_locks.ptr[replu_ptr->file]) &&
1317 excl_locks[lookup[pg_ptr->lu_slot].file]) && !trans_id)) {
1318 #endif /* MULTI_TASK */
1319 #endif /* SINGLE_USER */
1320 /* ix page swapping occurs here */
1321 dio_out(pg_ptr, replu_ptr, db_cache);
1322 pg_ptr->modified = FALSE;
1323 if ( db_cache ) --no_modheld;
1326 if (!use_ovfl || !cache_ovfl) continue; /* skip modified pages */
1327 /* Write out modified page */
1328 pg_ptr->modified = FALSE;
1329 --no_modheld; /* must be in db cache */
1330 if (o_write(pg_ptr, replu_ptr) != S_OKAY) return( db_status );
1333 MEM_UNLOCK(&replu_ptr->task->Excl_locks);
1336 pg_ptr->ovfl_addr = ovfl_addr;
1337 #endif /* NO_TRANS */
1338 pg_ptr->recently_used = TRUE;
1339 if ((*lru_ptr = (pg_slot + 1)) >= pgtab_sz)
1343 else if ( pg_ptr->holdcnt == 0 )
1344 pg_ptr->recently_used = FALSE;
1347 return( dberr(S_FAULT) );
1349 /* adjust lookup table */
1350 if (replu_ptr < lu_ptr) {
1356 while (replu_ptr < lu_ptr) {
1357 bytecpy(replu_ptr, replu_ptr + 1, sizeof(*replu_ptr));
1358 pg_table[replu_ptr->pg_slot].lu_slot = replu_ptr - lookup;
1362 else if (replu_ptr > lu_ptr) {
1368 while (replu_ptr > lu_ptr) {
1369 bytecpy(replu_ptr, replu_ptr - 1, sizeof(*replu_ptr));
1370 pg_table[replu_ptr->pg_slot].lu_slot = replu_ptr - lookup;
1377 pgsize = file_table[( lu_ptr->file > -1 ) ? lu_ptr->file : file].ft_pgsize;
1379 pgsize = ( db_cache )
1380 ? file_table[( lu_ptr->file > -1 ) ? lu_ptr->file : file].ft_pgsize
1381 : file_table[ov_file].ft_pgsize;
1387 if ( pgsize != file_table[file].ft_pgsize ) {
1388 Tempbuff.ptr = NULL;
1389 tempbuff = ALLOC(&Tempbuff, file_table[file].ft_pgsize, "dbpgbuff");
1391 return( dberr(S_NOMEMORY) );
1393 if ( pg_ptr->buff ) {
1394 MEM_UNLOCK(&pg_ptr->Buff);
1395 FREE(&pg_ptr->Buff);
1397 MEM_UNLOCK(&Tempbuff);
1398 pg_ptr->Buff = Tempbuff;
1400 #endif /* MULTI_TASK */
1403 lu_ptr->task = Currtask.v.ptr;
1405 lu_ptr->file = file;
1406 lu_ptr->pageno = page;
1407 lu_ptr->pg_slot = pg_slot;
1408 pg_ptr->lu_slot = lu_slot;
1409 if (xlu_ptr != NULL)
1411 if (xpg_ptr != NULL)
1415 last_dblu.task = lu_ptr->task;
1417 last_dblu.file = lu_ptr->file;
1418 last_dblu.pageno = lu_ptr->pageno;
1419 last_dblu.slot = lu_slot;
1420 dio_in(pg_ptr, lu_ptr);
1424 last_dblu.task = lu_ptr->task;
1426 last_dblu.file = lu_ptr->file;
1427 last_dblu.pageno = lu_ptr->pageno;
1428 last_dblu.slot = lu_slot;
1430 dio_in(pg_ptr, lu_ptr, db_cache);
1433 return( db_status );
1435 } /* dio_findpg() */
1438 /****************************************/
1442 /****************************************/
1443 /* Writes a page in the cache to file.
1444 * For byte order neutrality:
1445 * Each page is raima header data, then a bunch of slots.
1446 * The first 4 bytes of the page header is the timestamp
1447 * when the page was written, and it's swapped here.
1448 * Each slot is raima record header and user record data.
1449 * The user record data must already have been byte
1450 * swapped if necessary--to vista its just a large char buf.
1451 * The rest of the page header and the record header for each
1452 * slot is byte swapped before the io by calling the
1453 * page swap function.
1457 dio_out(pg_ptr, lu_ptr, db_cache)
1459 dio_out(pg_ptr, lu_ptr)
1461 PAGE_ENTRY FAR *pg_ptr; /* page table entry to be output */
1462 LOOKUP_ENTRY FAR *lu_ptr; /* corresponding lookup table entry */
1464 BOOLEAN db_cache; /* TRUE if pg_ptr is in db page cache */
1467 int desc; /* file descriptor */
1468 int fno; /* file number */
1469 int pgsize; /* size of page */
1470 long addr; /* file address */
1471 time_t host_timestamp;
1472 ULONG netorder_timestamp;
1474 MEM_LOCK(&pg_ptr->Buff);
1476 /* Get the current time in "network" format.
1477 * (Original vista code had it typed as a long.)
1479 time (&host_timestamp);
1480 netorder_timestamp = (ULONG) host_timestamp;
1481 HTONL (netorder_timestamp);
1485 pgsize = file_table[fno].ft_pgsize;
1486 addr = lu_ptr->pageno * (long)pgsize;
1487 memcpy (pg_ptr->buff, &netorder_timestamp, sizeof(ULONG));
1491 pgsize = file_table[fno].ft_pgsize;
1494 pgsize = file_table[ov_file].ft_pgsize;
1496 if ( pg_ptr->ovfl_addr == 0L ) {
1497 /* write to database */
1498 addr = lu_ptr->pageno * (long)pgsize;
1499 memcpy (pg_ptr->buff, &netorder_timestamp, sizeof(ULONG));
1502 /* write to overflow file */
1504 addr = pg_ptr->ovfl_addr;
1507 if ( dio_open(fno) == S_OKAY ) {
1508 swab_page (pg_ptr->buff, &file_table[fno], HTON);
1509 desc = file_table[fno].ft_desc;
1510 DB_LSEEK( desc, (off_t)addr, 0 );
1511 if (DB_WRITE( desc, pg_ptr->buff, pgsize ) != pgsize) dberr(S_BADWRITE);
1513 MEM_UNLOCK(&pg_ptr->Buff);
1514 return( db_status );
1519 /****************************************/
1523 /****************************************/
1525 /* Read in a page to the buffer
1527 static int dio_in(pg_ptr, lu_ptr)
1528 PAGE_ENTRY FAR *pg_ptr; /* page table entry to be input */
1529 LOOKUP_ENTRY FAR *lu_ptr; /* corresponding to pg_ptr */
1531 /* Read in a page to the buffer
1533 static int dio_in(pg_ptr, lu_ptr, db_cache )
1534 PAGE_ENTRY FAR *pg_ptr; /* page table entry to be input */
1535 LOOKUP_ENTRY FAR *lu_ptr; /* corresponding to pg_ptr */
1536 BOOLEAN db_cache; /* TRUE if pg_ptr in db cache */
1539 int desc; /* file descriptor */
1540 int fno; /* file number */
1541 int pgsize; /* page size */
1542 long addr; /* file address */
1543 PGZERO FAR *pgzero_ptr;
1544 FILE_ENTRY FAR *file_ptr;
1547 file_ptr = &file_table[fno = lu_ptr->file];
1549 pgsize = file_ptr->ft_pgsize;
1550 addr = lu_ptr->pageno*pgsize;
1552 pgsize = db_cache ? file_ptr->ft_pgsize : file_table[ov_file].ft_pgsize;
1554 if (pg_ptr->ovfl_addr == 0L) {
1555 /* read from database file */
1556 /* if !db_cache, overflow address not set on initial read */
1557 addr = db_cache ? lu_ptr->pageno*pgsize :
1558 (pg_ptr->ovfl_addr = lu_ptr->pageno);
1561 /* read from overflow file */
1562 file_ptr = &file_table[fno = ov_file];
1563 addr = pg_ptr->ovfl_addr;
1566 if ( dio_open(fno) == S_OKAY ) {
1567 desc = file_ptr->ft_desc;
1568 DB_LSEEK(desc, (off_t)addr, 0);
1569 MEM_LOCK(&pg_ptr->Buff);
1570 if ((r = DB_READ( desc, pg_ptr->buff, pgsize )) < pgsize) {
1571 byteset(&pg_ptr->buff[r], '\0', pgsize - r);
1572 DB_LSEEK(desc, (off_t)addr, 0);
1573 if (DB_WRITE( desc, pg_ptr->buff, pgsize ) != pgsize) {
1574 /* clean up and return out of space */
1575 DB_LSEEK(desc, (off_t)addr, 0);
1576 DB_WRITE(desc, "", 0);
1577 pgzero_ptr = &pgzero[fno];
1578 pgzero_ptr->pz_next--;
1579 pgzero_ptr->pz_modified = TRUE;
1584 swab_page (pg_ptr->buff, file_ptr, NTOH);
1585 MEM_UNLOCK(&pg_ptr->Buff);
1587 return( db_status );
1591 /***********************************************************************
1592 Page zero handling functions for data and key files
1593 ***********************************************************************/
1595 #ifndef NO_TIMESTAMP
1596 /* Increment and return file timestamp
1598 ULONG dio_pzsetts(fno )
1602 PGZERO FAR *pgzero_ptr;
1604 if ( db_tsrecs || db_tssets ) {
1605 pgzero_ptr = &pgzero[fno];
1606 pgzero_ptr->pz_modified = TRUE;
1607 ts = ++pgzero_ptr->pz_timestamp;
1616 /* Return file timestamp
1618 ULONG dio_pzgetts(fno)
1621 if ( pgzero[fno].pz_next == 0L )
1624 return ( pgzero[fno].pz_timestamp );
1629 /* Initialize page zero table
1631 static int dio_pzinit()
1634 PGZERO FAR *pgzero_ptr;
1637 if (debugging_dio_init) {
1638 printf (__FILE__"1430 dio_pzinit: szft=%d oldsz=%d\n",
1639 (int)size_ft, (int)old_size_ft);
1644 /* Macro references must be on one line for some compilers */
1645 if (ALLOC_TABLE(&db_global.Pgzero, size_ft*sizeof(PGZERO),
1646 old_size_ft*sizeof(PGZERO), "pgzero") != S_OKAY ) {
1648 if (debugging_dio_init) {
1649 printf (__FILE__"1444 pzinit: alloc_table failed, db_status=%d\n",
1654 return( db_status );
1657 /* read in page zeros */
1658 for (i = old_size_ft, pgzero_ptr = pgzero;
1660 ++i, ++pgzero_ptr) {
1661 pgzero_ptr->pz_dchain = 0L;
1662 pgzero_ptr->pz_next = 0L;
1663 pgzero_ptr->pz_timestamp = 0;
1664 pgzero_ptr->pz_modified = FALSE;
1666 return( db_status = S_OKAY );
1667 } /* dio_pzinit() */
1670 /****************************************/
1674 /****************************************/
1675 /* Flush page zero table
1676 * Complement to dio_out which writes all pages except page zero.
1678 static int dio_pzflush()
1682 register PGZERO FAR *pgzero_ptr;
1683 register FILE_ENTRY FAR *file_ptr;
1689 if ( (dboptions & TRLOGGING) && trans_id && !trcommit && use_ovfl ) {
1690 /* flush to overflow/log file -- before tx commit */
1691 for (i = 0, pgzero_ptr = pgzero; i < size_ft; ++i, ++pgzero_ptr) {
1692 if (pgzero_ptr->pz_modified )
1693 if ( o_pzwrite( i ) != S_OKAY ) return( db_status );
1698 /* flush modified page zeroes to database files */
1699 for (i = 0, pgzero_ptr = pgzero, file_ptr = file_table; i < size_ft;
1700 ++i, ++pgzero_ptr, ++file_ptr) {
1701 if ( pgzero_ptr->pz_modified ) {
1702 if ( dio_open(i) != S_OKAY )
1703 return( db_status );
1705 /* The only byte swap operations necessary
1706 * on a page zero are the first 5 LONG integers.
1708 for (j = 0, cptr = (char *) pgzero_ptr;
1709 j < PGZEROSZ/sizeof(LONG);
1710 ++j, cptr += sizeof(LONG)) {
1711 memcpy (&align_LONG, cptr, sizeof(LONG));
1713 memcpy (cptr, &align_LONG, sizeof(LONG));
1715 desc = file_ptr->ft_desc;
1716 DB_LSEEK(desc, (off_t)0L, 0);
1717 if (DB_WRITE(desc, (char FAR *)pgzero_ptr, PGZEROSZ) != PGZEROSZ)
1718 return( dberr(S_BADWRITE) );
1719 pgzero_ptr->pz_modified = FALSE;
1722 d_trlog(i, 0, (char FAR *)pgzero_ptr, PGZEROSZ);
1732 return( db_status = S_OKAY );
1733 } /* dio_pzflush() */
1736 /****************************************/
1740 /****************************************/
1741 /* Read a file's page zero
1745 FILE_NO fno; /* file number */
1747 FILE_ENTRY FAR *file_ptr;
1748 PGZERO FAR *pgzero_ptr;
1750 pgzero_ptr = &pgzero[fno];
1751 file_ptr = &file_table[fno];
1753 /* open this file, if not already open */
1755 if (file_ptr->ft_desc < 0) {
1756 pgzero_ptr->pz_dchain = 0;
1757 pgzero_ptr->pz_next = 0;
1758 pgzero_ptr->pz_timestamp = 0;
1759 pgzero_ptr->pz_modified = FALSE;
1760 return( db_status ); /* db_status set by dio_open */
1763 /* seek to and read page zero */
1764 DB_LSEEK(file_ptr->ft_desc, (off_t)0L, 0);
1765 if ( DB_READ(file_ptr->ft_desc, (char FAR *)pgzero_ptr, PGZEROSZ)
1767 return( dberr(S_BADREAD) );
1769 NTOHL (pgzero_ptr->pz_dchain);
1770 NTOHL (pgzero_ptr->pz_next);
1771 NTOHL (pgzero_ptr->pz_timestamp);
1772 return( db_status = S_OKAY );
1773 } /* dio_pzread() */
1777 /****************************************/
1781 /****************************************/
1782 /* Allocate new record slot or key node from page zero,
1783 * ie from delete chain if possible.
1784 * Returns memory address of the free slot into 'loc'.
1787 dio_pzalloc(fno, loc )
1788 FILE_NO fno; /* file number */
1789 F_ADDR *loc; /* pointer to allocated location */
1794 PGZERO FAR *pgzero_ptr;
1797 /* check shared access privileges */
1798 if ( dbopen == 1 && !trans_id && !excl_locks[fno] )
1799 return( dberr(S_NOTRANS) );
1802 pgzero_ptr = &pgzero[fno];
1803 if ( pgzero_ptr->pz_next == 0L )
1804 if ( dio_pzread(fno) != S_OKAY )
1805 RETURN( db_status );
1806 if ( file_table[fno].ft_type == KEY ) {
1807 if ( working_file != fno )
1808 return( dberr(S_NOWORK) );
1809 if ( pgzero_ptr->pz_dchain == NONE || ! (dboptions & DCHAINUSE) ) {
1810 if ( pgzero_ptr->pz_next == MAXRECORDS-1 )
1811 return( dberr(S_RECLIMIT) );
1812 pg = pgzero_ptr->pz_next++;
1815 pg = pgzero_ptr->pz_dchain;
1816 if ( dio_get( pg, (char FAR * FAR *)&ptr, NOPGHOLD ) != S_OKAY )
1817 return( db_status );
1818 /* Get the first key node on the delete chain.
1819 * (sizeof external timestamp set to 4 bytes)
1820 ****** bytecpy(&pgzero_ptr->pz_dchain,
1821 ****** ptr+sizeof(long)+sizeof(INT), sizeof(F_ADDR)); *********
1823 bytecpy (&pgzero_ptr->pz_dchain,
1824 ptr + sizeof(LONG) + sizeof(INT), sizeof(F_ADDR));
1828 if ( ! pgzero_ptr->pz_dchain || ! (dboptions & DCHAINUSE) ) {
1829 if ( pgzero_ptr->pz_next == MAXRECORDS )
1830 return( dberr(S_RECLIMIT) );
1831 pg = pgzero_ptr->pz_next++;
1834 pg = pgzero_ptr->pz_dchain;
1835 dba = ((NUM2EXT(fno, ft_offset) & FILEMASK) << FILESHIFT) | pg;
1836 if ( dio_read(dba, (char FAR * FAR *)&ptr, NOPGHOLD) != S_OKAY )
1837 return( db_status );
1838 bytecpy(&pgzero_ptr->pz_dchain, ptr+sizeof(INT), sizeof(F_ADDR));
1842 pgzero_ptr->pz_modified = TRUE;
1843 return( db_status = S_OKAY );
1844 } /* dio_pzalloc() */
1847 /****************************************/
1851 /****************************************/
1852 /* Delete record slot or key node from page zero
1855 dio_pzdel(fno, loc )
1856 FILE_NO fno; /* file number */
1857 F_ADDR loc; /* location to be freed */
1862 PGZERO FAR *pgzero_ptr;
1865 /* check shared access privileges */
1866 if ( dbopen == 1 && !trans_id && !excl_locks[fno] )
1867 return( dberr(S_NOTRANS) );
1870 pgzero_ptr = &pgzero[fno];
1871 if ( pgzero_ptr->pz_next == 0L )
1872 if ( dio_pzread(fno) != S_OKAY )
1873 RETURN( db_status );
1874 if ( file_table[fno].ft_type == KEY ) {
1875 if ( working_file != fno )
1876 return( dberr(S_NOWORK) );
1877 if ( dio_get( loc, (char FAR * FAR *)&ptr, PGHOLD ) != S_OKAY )
1878 return( db_status );
1879 /*********************************************
1880 * Delete chain ptr in key node page is in location
1881 * of orphan ptr, bytes 6 - 9, not bytes 4 - 7
1882 * as printed in raima User Guide.
1883 * (sizeof external timestamp set to 4 bytes).
1884 ****** bytecpy(ptr+sizeof(long)+sizeof(INT),
1885 ****** &pgzero_ptr->pz_dchain, sizeof(F_ADDR)); *********
1886 *****************************************/
1887 bytecpy (ptr + sizeof(LONG) + sizeof(INT),
1888 &pgzero_ptr->pz_dchain, sizeof(F_ADDR));
1889 pgzero_ptr->pz_dchain = loc;
1893 dba = ((NUM2EXT(fno, ft_offset) & FILEMASK) << FILESHIFT) | loc;
1894 if ( dio_read( dba, (char FAR * FAR *)&ptr , NOPGHOLD) != S_OKAY )
1895 return( db_status );
1896 bytecpy(&recnum, ptr, sizeof(INT));
1897 recnum = ~recnum; /* indicates deleted record */
1898 bytecpy(ptr, &recnum, sizeof(INT));
1899 bytecpy(ptr+sizeof(INT), &pgzero_ptr->pz_dchain, sizeof(F_ADDR));
1900 pgzero_ptr->pz_dchain = loc;
1901 if ( dio_write(dba, NULL, NOPGFREE) != S_OKAY )
1902 return( db_status );
1904 pgzero_ptr->pz_modified = TRUE;
1905 return( db_status = S_OKAY );
1909 /****************************************/
1913 /****************************************/
1914 /* Return pz_next for file fno
1916 F_ADDR dio_pznext(fno)
1919 if ( pgzero[fno].pz_next == 0L )
1921 return ( pgzero[fno].pz_next );
1924 /****************************************/
1928 /****************************************/
1929 /* Clear page zero cache
1934 register PGZERO FAR *pgzero_ptr;
1936 for (i = 0, pgzero_ptr = pgzero; i < size_ft; i++, pgzero_ptr++) {
1937 if (pgzero_ptr->pz_modified) {
1938 pgzero_ptr->pz_next = 0L;
1939 pgzero_ptr->pz_modified = FALSE;
1944 /* vpp -nOS2 -dUNIX -nBSD -nVANILLA_BSD -nVMS -nMEMLOCK -nWINDOWS -nFAR_ALLOC -f/usr/users/master/config/nonwin dio.c */