2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * COMPONENT_NAME: austext
26 * FUNCTIONS: 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
234 if ( dbpg_table ) return( dberr(S_DBCLOSE) );
236 if ( num > 0 && num < 256 )
237 max_open_files = num;
239 return( db_status = S_OKAY );
243 /* Set number of virtual memory pages
245 d_setpages(dbpgs, ixpgs)
246 int dbpgs; /* # of db cache pages */
247 int ixpgs; /* # of index cache pages - ignored in single-user version */
249 if ( dbpg_table ) return( dberr(S_SETPAGES) );
251 db_pgtab_sz = (dbpgs <= MINDBPAGES) ? MINDBPAGES : dbpgs;
255 ix_pgtab_sz = (ixpgs <= MINIXPAGES) ? MINIXPAGES : ixpgs;
258 return( db_status = S_OKAY );
262 /****************************************/
266 /****************************************/
267 /* Open a database file
272 FILE_ENTRY FAR *file_ptr, FAR *lru_file_ptr;
273 register int FAR *uf_ptr;
275 file_ptr = &file_table[fno];
276 if ( file_ptr->ft_status == CLOSED ) {
277 if ( cnt_open_files == max_open_files ) {
278 /* find least recently used file */
279 uf_ptr = &used_files[last_file];
280 lru_file_ptr = &file_table[last_file];
281 while (*uf_ptr || (lru_file_ptr->ft_status == CLOSED)) {
283 if (++last_file >= size_ft) {
285 lru_file_ptr = file_table;
293 dio_close(last_file);
294 if (++last_file >= size_ft)
297 used_files[fno] = TRUE;
299 file_ptr->ft_desc = open_b(file_ptr->ft_name, db_oflag);
300 if (file_ptr->ft_desc < 0)
301 return( dberr( S_NOFILE ) );
302 file_ptr->ft_status = OPEN;
305 return( db_status = S_OKAY );
309 /****************************************/
313 /****************************************/
314 /* Close a database file
319 FILE_ENTRY FAR *file_ptr;
321 file_ptr = &file_table[fno];
322 if ( file_ptr->ft_status == OPEN ) {
323 DB_CLOSE( file_ptr->ft_desc );
324 file_ptr->ft_status = CLOSED;
327 return( db_status = S_OKAY );
331 /****************************************/
335 /****************************************/
336 /* Initialize database I/O
341 #define tempbuff Tempbuff.ptr
344 if (debugging_dio_init) {
345 printf (__FILE__"300 dio_init: dbpgtab=%p pgsz=%d largest=%d\n",
346 dbpg_table, (int)page_size, (int)largest_page);
352 if ( dio_pzinit() != S_OKAY ) {
355 if ( page_size > largest_page ) {
356 if ( (tempbuff = ALLOC(&Tempbuff, page_size, "tempbuff")) == NULL )
357 return( dberr(S_NOMEMORY) );
359 MEM_UNLOCK(&Dbpgbuff);
363 largest_page = page_size;
366 if (debugging_dio_init) {
367 printf (__FILE__"323 dio_init: pzinited ok. pgsz=%d largest=%d\n",
368 (int)page_size, (int)largest_page);
374 } /* end if ( dbpg_table ) */
377 /* Macro references must be on one line for some compilers */
378 (int FAR *)ALLOC(&Used_files, (size_ft+1)*sizeof(int), "used_files");
380 /* Macro references must be on one line for some compilers */
382 ALLOC(&Db_lookup, db_pgtab_sz*sizeof(LOOKUP_ENTRY), "db_lookup");
384 /* Macro references must be on one line for some compilers */
386 ALLOC(&Dbpg_table, db_pgtab_sz*sizeof(PAGE_ENTRY), "dbpg_table");
388 if (debugging_dio_init) {
389 printf (__FILE__"345 dio_init: usedfls=%p lookup=%p pgtab=%p\n",
390 used_files, db_lookup, dbpg_table);
394 if ( !used_files || !dbpg_table || !db_lookup )
395 return( dberr(S_NOMEMORY) );
396 byteset(used_files, 0, (size_ft + 1)*sizeof(*used_files));
399 last_dblu.task = NULL;
402 last_dblu.pageno = -1L;
405 /* initialize database cache */
406 cache_init((int)db_pgtab_sz, db_lookup, dbpg_table, (int)page_size);
407 /***cache_init(db_pgtab_sz, db_lookup, dbpg_table, page_size);****/
408 if (db_status != S_OKAY) return(db_status);
412 /* Macro references must be on one line for some compilers */
414 ALLOC(&Ix_lookup, ix_pgtab_sz*sizeof(LOOKUP_ENTRY),"ix_lookup");
416 /* Macro references must be on one line for some compilers */
418 ALLOC(&Ixpg_table, ix_pgtab_sz*sizeof(PAGE_ENTRY), "ixpg_table");
419 if ( !ix_lookup || !ixpg_table )
420 return( dberr(S_NOMEMORY) );
422 cache_init(ix_pgtab_sz, ix_lookup, ixpg_table, IX_PAGESIZE);
423 if (db_status != S_OKAY)
426 if ( (dbpgbuff = ALLOC(&Dbpgbuff, page_size, "dbpgbuff")) == NULL )
427 return( dberr(S_NOMEMORY) );
431 #endif /* NO_TRANS */
437 /* initialize the page zero table and return */
439 if (debugging_dio_init) {
440 puts (__FILE__"390 dio_init: last act is call to dio_pzinit.");
444 return( dio_pzinit() );
449 static void cache_init (pg_cnt, lu_ptr, pg_ptr, pgsize)
451 LOOKUP_ENTRY FAR * lu_ptr;
452 PAGE_ENTRY FAR * pg_ptr;
458 if (debugging_dio_init) {
459 printf (__FILE__"400 cache_init: pgcnt=%d lu=%p pgp=%p pgsz=%d\n",
460 pg_cnt, lu_ptr, pg_ptr, pgsize);
465 for (pg_no = 0; pg_no < pg_cnt; ++pg_no, ++lu_ptr, ++pg_ptr)
471 lu_ptr->pageno = -1L;
472 lu_ptr->pg_slot = pg_no;
474 pg_ptr->lu_slot = pg_no;
475 pg_ptr->recently_used = FALSE;
476 pg_ptr->modified = FALSE;
479 pg_ptr->ovfl_addr = 0L;
481 pg_ptr->buff = ALLOC(&pg_ptr->Buff, pgsize, db_avname);
482 if (pg_ptr->buff == NULL) {
484 if (debugging_dio_init) {
485 printf (__FILE__"428 cache_init: alloc failed pgsz=%d\n",
493 MEM_UNLOCK(&pg_ptr->Buff);
494 } /* end loop on pg_cnt */
499 /****************************************/
503 /****************************************/
504 /* Free the memory allocated for pages
508 register int pgt_lc; /* loop control */
509 register PAGE_ENTRY FAR *pg_ptr;
512 if ( task_count > 1 ) {
516 MEM_UNLOCK(&db_global.Pgzero);
517 FREE(&db_global.Pgzero);
518 MEM_UNLOCK(&Used_files);
520 MEM_UNLOCK(&Db_lookup);
522 for (pgt_lc = db_pgtab_sz, pg_ptr = dbpg_table; --pgt_lc >= 0; ++pg_ptr) {
523 MEM_UNLOCK(&pg_ptr->Buff);
526 MEM_UNLOCK(&Dbpg_table);
530 MEM_UNLOCK(&Ix_lookup);
532 for (pgt_lc = ix_pgtab_sz, pg_ptr = ixpg_table; --pgt_lc >= 0; ++pg_ptr) {
533 MEM_UNLOCK(&pg_ptr->Buff);
536 MEM_UNLOCK(&Ixpg_table);
538 MEM_UNLOCK(&Dbpgbuff);
545 /****************************************/
549 /****************************************/
550 /* Clear pages for a single file.
553 register FILE_NO fno;
555 return( clear_cache(fno, fno+1) );
560 /****************************************/
564 /****************************************/
565 /* Clear all pages for *all* files from I/O buffer
569 return( clear_cache(0, size_ft) );
573 /****************************************/
577 /****************************************/
578 /* Clear database page cache.
579 * Clears all pages for a range of specified files.
580 * Subroutine of dio_clrfile and dio_clear.
582 static int clear_cache(fr_file, to_file )
583 FILE_NO fr_file; /* clear from file "fr_file" */
584 FILE_NO to_file; /* ..to (not thru) file "to_file" */
586 FILE_NO s_file; /* start file to be cleared */
587 FILE_NO e_file; /* end file (+1) to be cleared */
589 LOOKUP_ENTRY FAR *lu_ptr, FAR *lu2_ptr;
591 PAGE_ENTRY FAR *pg_ptr;
592 PGZERO FAR *pgzero_ptr;
593 FILE_ENTRY FAR *file_ptr;
594 int FAR *appl_ptr, FAR *excl_ptr;
598 We only clear pages which are not from static files and are
599 not still locked. The check on app_locks is made to implement
600 the ability to hold locks after the end of a transaction
602 for (s_file = e_file = fr_file, file_ptr = &file_table[e_file],
603 appl_ptr = &app_locks[e_file], excl_ptr = &excl_locks[e_file];
605 ++file_ptr, ++appl_ptr, ++excl_ptr) {
607 for (s_file = e_file = fr_file, file_ptr = &file_table[e_file];
611 if ((e_file < to_file) &&
613 ((dbopen >= 2) || (!*appl_ptr && !*excl_ptr)) &&
615 !(file_ptr->ft_flags & STATIC))
618 if (s_file < e_file) {
619 /* find range of pages to be cleared */
620 dio_findpg(s_file, 0L, NULL, NULL, &lu_ptr);
621 dio_findpg(e_file, 0L, NULL, NULL, &lu2_ptr);
624 last_dblu.task = NULL;
627 last_dblu.pageno = -1L;
630 if (lu_ptr < lu2_ptr) { /* otherwise file has no pages in cache */
631 /* adjust lookup table entries */
632 while ((lu_ptr > db_lookup) && ((--lu_ptr)->file >= 0)) {
636 lu2_ptr->task = lu_ptr->task;
638 lu2_ptr->file = lu_ptr->file;
639 lu2_ptr->pageno = lu_ptr->pageno;
640 /* exchange page slot numbers */
641 pg_slot = lu_ptr->pg_slot;
642 lu_ptr->pg_slot = lu2_ptr->pg_slot;
643 lu2_ptr->pg_slot = pg_slot;
644 dbpg_table[pg_slot].lu_slot = lu2_ptr - db_lookup;
645 dbpg_table[lu_ptr->pg_slot].lu_slot = lu_ptr - db_lookup;
648 if ( lu_ptr->file < 0 )
651 while (lu_ptr < lu2_ptr) {
657 lu_ptr->pageno = -1L;
658 pg_ptr = &dbpg_table[lu_ptr->pg_slot];
659 if ( pg_ptr->modified || pg_ptr->holdcnt ) {
661 pg_ptr->modified = FALSE;
663 pg_ptr->recently_used = FALSE;
666 pg_ptr->ovfl_addr = 0L;
671 /* clear page zeroes and close files */
672 for (i = s_file, pgzero_ptr = &pgzero[i];
675 pgzero_ptr->pz_modified = FALSE;
676 pgzero_ptr->pz_next = 0L;
685 return( db_status = S_OKAY );
686 } /* clear_cache() */
689 /****************************************/
693 /****************************************/
694 /* Flushes entire database I/O cache.
695 * Writes out all modified cache pages to respective files (dio_out),
696 * then writes out page zero (dio_pzflush).
700 register int pgt_lc; /* loop control */
702 PAGE_ENTRY FAR *pg_ptr;
703 LOOKUP_ENTRY FAR *lu_ptr;
706 if (debugging_dio_close) {
707 printf (__FILE__"685 dio_flush: check cache dbpgtab=%p count=%d\n",
708 dbpg_table, (int)db_pgtab_sz);
712 if ( dbpg_table == NULL ) return( db_status = S_OKAY );
714 for (pgt_lc = db_pgtab_sz, pg_ptr = dbpg_table; --pgt_lc >= 0; ++pg_ptr) {
715 if (!pg_ptr->modified) {
717 pg_ptr->ovfl_addr = 0L; /*[612]*/
721 lu_ptr = &db_lookup[pg_ptr->lu_slot];
723 if ( lu_ptr->task != Currtask.v.ptr ) {
728 if ((dboptions & TRLOGGING) && trans_id && !trcommit && use_ovfl) {
729 /* flush to overflow/log file -- before tr commit */
730 if (o_write(pg_ptr, lu_ptr) != S_OKAY) return( db_status );
731 if ( lu_ptr->pageno > o_pages(lu_ptr->file) ) {
732 /* no need to rewrite this page at trcommit time */
734 pg_ptr->modified = FALSE;
739 pg_ptr->ovfl_addr = 0L;
741 /* write directly to database */
744 if (debugging_dio_close) {
745 printf (__FILE__"723 dio_flush: write modified pg#%d @ %p\n",
746 db_pgtab_sz - pgt_lc, pg_ptr);
750 if (dio_out(pg_ptr, lu_ptr) != S_OKAY) return( db_status );
752 if (dio_out(pg_ptr, lu_ptr, 1) != S_OKAY) return( db_status );
755 pg_ptr->modified = FALSE;
760 MEM_LOCK(&pg_ptr->Buff);
761 d_trlog(fno, (int)lu_ptr->pageno, pg_ptr->buff,
762 file_table[fno].ft_pgsize);
763 MEM_UNLOCK(&pg_ptr->Buff);
767 /* store the page zero values in the data file and return */
768 return( dio_pzflush() );
773 /* Set the default file number
775 void dio_setdef( file_no )
778 working_file = file_no;
783 /****************************************/
787 /****************************************/
788 /* Database I/O page get
790 dio_get( page_no, page_ptr, hold )
792 char FAR * FAR *page_ptr;
795 PAGE_ENTRY FAR *pg_ptr;
799 if ( !app_locks[working_file] && !excl_locks[working_file] &&
800 !(file_table[working_file].ft_flags & STATIC) )
801 return( dberr(S_NOTLOCKED) );
804 if ( pgzero[working_file].pz_next == 0L )
805 if ( dio_pzread(working_file) != S_OKAY )
808 if (dio_findpg(working_file, page_no, dbpg_table, &pg_ptr, NULL) == S_OKAY) {
809 MEM_LOCK(&pg_ptr->Buff);
810 *page_ptr = pg_ptr->buff;
811 pg_ptr->recently_used = TRUE;
812 used_files[working_file] = TRUE;
814 if ( ++pg_ptr->holdcnt > 1 )
816 else if ( ! pg_ptr->modified )
825 /****************************************/
829 /****************************************/
830 /* Set modified flag for a page
835 PAGE_ENTRY FAR *pg_ptr;
838 /* ensure overflow data is initialized when exclusive db access */
839 if ((trans_id && (dboptions & TRLOGGING) && use_ovfl) &&
840 (o_fileinit(working_file) != S_OKAY))
845 /* check shared access priviledges */
846 if ( !trans_id && !excl_locks[working_file] )
847 return( dberr(S_NOTRANS) );
848 if ( app_locks[working_file] >= 0 && !excl_locks[working_file] )
849 return( dberr( S_NOTLOCKED ) );
852 if (dio_findpg(working_file, page_no, dbpg_table, &pg_ptr, NULL) == S_OKAY ) {
853 pg_ptr->recently_used = TRUE;
854 used_files[working_file] = TRUE;
855 if ( ! pg_ptr->modified ) {
856 pg_ptr->modified = TRUE;
857 if ( ! pg_ptr->holdcnt )
860 if ( pg_ptr->holdcnt > 0 ) {
862 if ( pg_ptr->holdcnt ) {
865 MEM_UNLOCK(&pg_ptr->Buff);
873 /****************************************/
877 /****************************************/
879 * Merely returns ptr into rec in a page
880 * unless a page swap is necessary.
882 dio_read( dba, recptr, hold )
884 char FAR * FAR *recptr;
890 FILE_ENTRY FAR *file_ptr;
891 PAGE_ENTRY FAR *pg_ptr;
893 file = NUM2INT((FILE_NO)((dba >> FILESHIFT) & FILEMASK), ft_offset);
894 file_ptr = &file_table[file];
896 if ( pgzero[file].pz_next == 0L )
897 if ( dio_pzread(file) != S_OKAY )
902 /* check shared access priviledges */
903 if (!app_locks[file] &&
905 !(file_ptr->ft_flags & STATIC))
906 return( dberr(S_NOTLOCKED) );
909 us1 = ADDRMASK & dba;
910 us2 = (us1 - 1)/file_ptr->ft_slots;
911 if (dio_findpg(file, us2 + 1, dbpg_table, &pg_ptr, NULL) == S_OKAY ) {
912 pg_ptr->recently_used = TRUE;
913 used_files[file] = TRUE;
914 offset = file_ptr->ft_slsize*(int)(us1 - 1 - us2*file_ptr->ft_slots) +
916 MEM_LOCK(&pg_ptr->Buff);
917 *recptr = &pg_ptr->buff[offset];
919 if ( (++pg_ptr->holdcnt == 1) && !pg_ptr->modified) {
928 /****************************************/
932 /****************************************/
933 /* Database I/O write: copies data record into a page slot.
934 * Finds record's page, swapping it into cache if necessary.
935 * Sets page's 'touched' flags, timestamps, etc.
936 * If recptr not NULL, copies rec to page cache.
938 dio_write( dba, recptr, release )
940 CONST char FAR *recptr;
946 FILE_ENTRY FAR *file_ptr;
947 PAGE_ENTRY FAR *pg_ptr;
949 file = NUM2INT((FILE_NO)((dba >> FILESHIFT) & FILEMASK), ft_offset);
952 /* ensure overflow data is initialized when exclusive db access */
953 if ((trans_id && (dboptions & TRLOGGING) && use_ovfl) &&
954 (o_fileinit(file) != S_OKAY))
959 if (!trans_id && !excl_locks[file])
960 return( dberr(S_NOTRANS) );
962 /* check shared access priviledges */
963 if ( app_locks[file] >= 0 && !excl_locks[file] )
964 return( dberr(S_NOTLOCKED) );
967 file_ptr = &file_table[file];
968 us1 = ADDRMASK & dba;
969 us2 = (us1 - 1)/file_ptr->ft_slots;
970 if (dio_findpg(file, us2 + 1, dbpg_table, &pg_ptr, NULL) == S_OKAY ) {
971 pg_ptr->recently_used = TRUE;
972 used_files[file] = TRUE;
973 if ( recptr != NULL ) {
974 offset = file_ptr->ft_slsize*(int)(us1 - 1 - us2*file_ptr->ft_slots) +
976 MEM_LOCK(&pg_ptr->Buff);
977 bytecpy(&pg_ptr->buff[offset], recptr, file_ptr->ft_slsize);
978 MEM_UNLOCK(&pg_ptr->Buff);
980 if ( ! pg_ptr->modified ) {
981 pg_ptr->modified = TRUE;
982 if ( ! pg_ptr->holdcnt )
986 if ( --pg_ptr->holdcnt < 0 )
988 MEM_UNLOCK(&pg_ptr->Buff);
995 /* Release database page hold
1002 PAGE_ENTRY FAR *pg_ptr;
1004 file = NUM2INT((FILE_NO)((dba >> FILESHIFT) & FILEMASK), ft_offset);
1005 us1 = ADDRMASK & dba;
1006 us2 = file_table[file].ft_slots;
1007 if (dio_findpg(file, ((us1 - 1)/us2) + 1, dbpg_table, &pg_ptr,
1009 if (pg_ptr->holdcnt) {
1011 if ( !pg_ptr->holdcnt && !pg_ptr->modified )
1013 MEM_UNLOCK(&pg_ptr->Buff);
1016 return( db_status );
1022 /* Read record lock bit
1028 FILE_NO file; /* file number */
1029 F_ADDR page; /* page number */
1030 F_ADDR sno; /* slot number */
1031 F_ADDR spp; /* slots per page */
1032 F_ADDR offset; /* lseek address - offset from start of file */
1033 FILE_ENTRY FAR *file_ptr;
1035 file = NUM2INT((FILE_NO)((dba >> FILESHIFT) & FILEMASK), ft_offset);
1036 if ( dio_open(file) == S_OKAY ) {
1037 file_ptr = &file_table[file];
1038 sno = ADDRMASK & dba;
1039 spp = file_ptr->ft_slots;
1040 page = (sno - 1)/spp + 1;
1041 offset = PGHDRSIZE + page*file_ptr->ft_pgsize +
1042 (sno - 1 - (page - 1)*spp)*file_ptr->ft_slsize;
1043 DB_LSEEK(file_ptr->ft_desc, offset, 0);
1044 if ( DB_READ(file_ptr->ft_desc, (char FAR *)rid, sizeof(INT))
1050 return( db_status );
1054 /* Write record lock bit
1060 FILE_NO file; /* file number */
1061 F_ADDR page; /* page number */
1062 F_ADDR sno; /* slot number */
1063 F_ADDR spp; /* slots per page */
1064 F_ADDR offset; /* offset from start of page or file */
1065 int clr_in_tx; /* true if called from d_rlbclr in trx */
1066 INT trid; /* [333] working rid */
1067 FILE_ENTRY FAR *file_ptr;
1068 PAGE_ENTRY FAR *pg_ptr;
1070 file = NUM2INT((FILE_NO)((dba >> FILESHIFT) & FILEMASK), ft_offset);
1071 file_ptr = &file_table[file];
1072 sno = ADDRMASK & dba;
1073 spp = file_ptr->ft_slots;
1074 page = ((sno - 1)/spp) + 1;
1075 offset = PGHDRSIZE + (sno - 1 - (page - 1)*spp)*file_ptr->ft_slsize;
1076 clr_in_tx = !(rid & RLBMASK) && trans_id;
1078 if ( dbopen > 1 || (app_locks[file] || excl_locks[file]) ) {
1079 /* file is locked - check if record in cache */
1080 if (dio_findpg(file, page, dbpg_table, &pg_ptr, NULL) == S_OKAY) {
1081 MEM_LOCK(&pg_ptr->Buff);
1082 /* record in cache - update only rlb in rid */
1083 bytecpy(&trid, &pg_ptr->buff[offset], sizeof(INT));
1084 MEM_UNLOCK(&pg_ptr->Buff);
1085 rid = (trid & ~((INT)RLBMASK)) | (rid & RLBMASK);
1086 bytecpy(&pg_ptr->buff[offset], &rid, sizeof(INT));
1088 /* clearing within a transaction requires touching page */
1089 if ( ! pg_ptr->modified ) {
1090 pg_ptr->modified = TRUE;
1091 if ( ! pg_ptr->holdcnt )
1099 if ( ! clr_in_tx ) {
1100 /* update only rlb directly to disk */
1101 if ( dio_open(file) == S_OKAY ) {
1102 offset += page*file_ptr->ft_pgsize;
1104 /* read rid from disk, and set/clear rlb accordingly */
1105 DB_LSEEK(file_ptr->ft_desc, offset, 0);
1106 if ( DB_READ(file_ptr->ft_desc, (char FAR *)&trid, sizeof(INT))
1111 rid = (trid & ~((INT)RLBMASK)) | (rid & RLBMASK);
1113 /* write original rid out with modified rlb */
1114 trid = htons (rid); /* make a copy in trid for byte swap */
1115 DB_LSEEK(file_ptr->ft_desc, offset, 0); /* reseek */
1116 if ( DB_WRITE(file_ptr->ft_desc, (char FAR *)&trid, sizeof(INT)) !=
1121 return( db_status );
1123 #endif /* SINGLE_USER */
1126 /****************************************/
1130 /****************************************/
1131 /* Search a cache for page
1133 dio_findpg(file, page, pg_table, xpg_ptr, xlu_ptr )
1134 FILE_NO file; /* file number = 0..size_ft-1 */
1135 F_ADDR page; /* database page number */
1136 PAGE_ENTRY FAR *pg_table; /* = dbpg_table, ixpg_table, or NULL */
1137 PAGE_ENTRY FAR * FAR *xpg_ptr; /* pointer to page table entry for found page */
1138 LOOKUP_ENTRY FAR * FAR *xlu_ptr;/* pointer to lookup table slot for found page*/
1142 #define tempbuff Tempbuff.ptr
1144 LOOKUP_ENTRY FAR *lookup; /* = db_lookup or ix_lookup */
1145 int pgtab_sz; /* = db_pgtab_sz or ix_pgtab_sz */
1148 register int lu_slot, l, u;
1149 LOOKUP_ENTRY FAR *lu_ptr, FAR *replu_ptr;
1150 PAGE_ENTRY FAR *pg_ptr;
1154 BOOLEAN db_cache; /* TRUE if currently using dbpg_table */
1163 /* check if desired page was last one */
1165 if ((Currtask.v.ptr == last_dblu.task) && (file == last_dblu.file) && (page == last_dblu.pageno)) {
1167 if ((file == last_dblu.file) && (page == last_dblu.pageno)) {
1169 if (xlu_ptr != NULL)
1170 *xlu_ptr = &db_lookup[last_dblu.slot];
1171 if (xpg_ptr != NULL)
1172 *xpg_ptr = &dbpg_table[db_lookup[last_dblu.slot].pg_slot];
1173 return( db_status = S_OKAY );
1176 pgtab_sz = db_pgtab_sz;
1177 #else /* NO_TRANS */
1178 if (db_cache = (!pg_table || (pg_table == dbpg_table))) {
1179 /* check if desired page was last one */
1181 if ((Currtask.v.ptr == last_dblu.task) && (file == last_dblu.file) &&
1182 (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;
1197 pgtab_sz = ix_pgtab_sz;
1199 #endif /* NO_TRANS */
1200 /* perform binary search of sorted lookup table */
1204 lu_ptr = &lookup[lu_slot = (l + u)/2];
1206 if ((cmp = Currtask.v.ptr - lu_ptr->task) == 0)
1208 if ((cmp = file - lu_ptr->file) == 0)
1209 cmp = page - lu_ptr->pageno;
1220 last_dblu.task = lu_ptr->task;
1222 last_dblu.file = lu_ptr->file;
1223 last_dblu.pageno = lu_ptr->pageno;
1224 last_dblu.slot = lu_slot;
1228 if (xlu_ptr != NULL)
1230 if (xpg_ptr != NULL)
1231 *xpg_ptr = &pg_table[lu_ptr->pg_slot];
1232 return( db_status = S_OKAY );
1236 /* null page table indicates that only a lookup was desired */
1239 if (xlu_ptr != NULL)
1241 return( db_status = S_NOTFOUND );
1243 /* page not found - read into cache */
1245 if( !use_ovfl && trans_id && (no_modheld == pgtab_sz) )
1246 return( db_status = S_TRCHANGES );
1248 /* check to see if page is in overflow file */
1250 if ( cache_ovfl && file != ov_file ) {
1251 if ( o_search( file, page, &ovfl_addr ) != S_OKAY )
1252 return( db_status );
1254 /* check for overflow */
1255 if ( db_cache && trans_id && (no_modheld == pgtab_sz) && !cache_ovfl ) {
1258 /* select a page to replace */
1260 lru_ptr = &dbpg_lru_slot;
1262 lru_ptr = &ixpg_lru_slot;
1265 /* select a page to replace */
1266 lru_ptr = &dbpg_lru_slot;
1267 #endif /* NO_TRANS */
1268 for (cnt = 2*pgtab_sz, pg_slot = *lru_ptr, pg_ptr = &pg_table[pg_slot];
1270 ++pg_slot, ++pg_ptr) {
1271 if (pg_slot >= pgtab_sz)
1276 replu_ptr = &lookup[pg_ptr->lu_slot];
1277 if (!pg_ptr->recently_used && (pg_ptr->holdcnt == 0)) {
1279 if (pg_ptr->modified) {
1280 dio_out(pg_ptr, replu_ptr);
1281 pg_ptr->modified = FALSE;
1285 if (pg_ptr->modified) {
1286 /* allow updates outside transactions for single-user mode */
1288 if (!db_cache || (EXCL_OPEN() && !trans_id)) {
1291 MEM_LOCK(&replu_ptr->task->Excl_locks);
1293 if (!db_cache || ((EXCL_OPEN() ||
1295 ( replu_ptr->task == Currtask.v.ptr ) ?
1296 excl_locks[lookup[pg_ptr->lu_slot].file] :
1297 replu_ptr->task->Excl_locks.ptr[replu_ptr->file]) &&
1300 excl_locks[lookup[pg_ptr->lu_slot].file]) && !trans_id)) {
1301 #endif /* MULTI_TASK */
1302 #endif /* SINGLE_USER */
1303 /* ix page swapping occurs here */
1304 dio_out(pg_ptr, replu_ptr, db_cache);
1305 pg_ptr->modified = FALSE;
1306 if ( db_cache ) --no_modheld;
1309 if (!use_ovfl || !cache_ovfl) continue; /* skip modified pages */
1310 /* Write out modified page */
1311 pg_ptr->modified = FALSE;
1312 --no_modheld; /* must be in db cache */
1313 if (o_write(pg_ptr, replu_ptr) != S_OKAY) return( db_status );
1316 MEM_UNLOCK(&replu_ptr->task->Excl_locks);
1319 pg_ptr->ovfl_addr = ovfl_addr;
1320 #endif /* NO_TRANS */
1321 pg_ptr->recently_used = TRUE;
1322 if ((*lru_ptr = (pg_slot + 1)) >= pgtab_sz)
1326 else if ( pg_ptr->holdcnt == 0 )
1327 pg_ptr->recently_used = FALSE;
1330 return( dberr(S_FAULT) );
1332 /* adjust lookup table */
1333 if (replu_ptr < lu_ptr) {
1339 while (replu_ptr < lu_ptr) {
1340 bytecpy(replu_ptr, replu_ptr + 1, sizeof(*replu_ptr));
1341 pg_table[replu_ptr->pg_slot].lu_slot = replu_ptr - lookup;
1345 else if (replu_ptr > lu_ptr) {
1351 while (replu_ptr > lu_ptr) {
1352 bytecpy(replu_ptr, replu_ptr - 1, sizeof(*replu_ptr));
1353 pg_table[replu_ptr->pg_slot].lu_slot = replu_ptr - lookup;
1360 pgsize = file_table[( lu_ptr->file > -1 ) ? lu_ptr->file : file].ft_pgsize;
1362 pgsize = ( db_cache )
1363 ? file_table[( lu_ptr->file > -1 ) ? lu_ptr->file : file].ft_pgsize
1364 : file_table[ov_file].ft_pgsize;
1370 if ( pgsize != file_table[file].ft_pgsize ) {
1371 Tempbuff.ptr = NULL;
1372 tempbuff = ALLOC(&Tempbuff, file_table[file].ft_pgsize, "dbpgbuff");
1374 return( dberr(S_NOMEMORY) );
1376 if ( pg_ptr->buff ) {
1377 MEM_UNLOCK(&pg_ptr->Buff);
1378 FREE(&pg_ptr->Buff);
1380 MEM_UNLOCK(&Tempbuff);
1381 pg_ptr->Buff = Tempbuff;
1383 #endif /* MULTI_TASK */
1386 lu_ptr->task = Currtask.v.ptr;
1388 lu_ptr->file = file;
1389 lu_ptr->pageno = page;
1390 lu_ptr->pg_slot = pg_slot;
1391 pg_ptr->lu_slot = lu_slot;
1392 if (xlu_ptr != NULL)
1394 if (xpg_ptr != NULL)
1398 last_dblu.task = lu_ptr->task;
1400 last_dblu.file = lu_ptr->file;
1401 last_dblu.pageno = lu_ptr->pageno;
1402 last_dblu.slot = lu_slot;
1403 dio_in(pg_ptr, lu_ptr);
1407 last_dblu.task = lu_ptr->task;
1409 last_dblu.file = lu_ptr->file;
1410 last_dblu.pageno = lu_ptr->pageno;
1411 last_dblu.slot = lu_slot;
1413 dio_in(pg_ptr, lu_ptr, db_cache);
1416 return( db_status );
1418 } /* dio_findpg() */
1421 /****************************************/
1425 /****************************************/
1426 /* Writes a page in the cache to file.
1427 * For byte order neutrality:
1428 * Each page is raima header data, then a bunch of slots.
1429 * The first 4 bytes of the page header is the timestamp
1430 * when the page was written, and it's swapped here.
1431 * Each slot is raima record header and user record data.
1432 * The user record data must already have been byte
1433 * swapped if necessary--to vista its just a large char buf.
1434 * The rest of the page header and the record header for each
1435 * slot is byte swapped before the io by calling the
1436 * page swap function.
1439 dio_out(pg_ptr, lu_ptr, db_cache)
1441 dio_out(pg_ptr, lu_ptr)
1443 PAGE_ENTRY FAR *pg_ptr; /* page table entry to be output */
1444 LOOKUP_ENTRY FAR *lu_ptr; /* corresponding lookup table entry */
1446 BOOLEAN db_cache; /* TRUE if pg_ptr is in db page cache */
1449 int desc; /* file descriptor */
1450 int fno; /* file number */
1451 int pgsize; /* size of page */
1452 long addr; /* file address */
1453 time_t host_timestamp;
1454 ULONG netorder_timestamp;
1456 MEM_LOCK(&pg_ptr->Buff);
1458 /* Get the current time in "network" format.
1459 * (Original vista code had it typed as a long.)
1461 time (&host_timestamp);
1462 netorder_timestamp = (ULONG) host_timestamp;
1463 HTONL (netorder_timestamp);
1467 pgsize = file_table[fno].ft_pgsize;
1468 addr = lu_ptr->pageno * (long)pgsize;
1469 memcpy (pg_ptr->buff, &netorder_timestamp, sizeof(ULONG));
1473 pgsize = file_table[fno].ft_pgsize;
1476 pgsize = file_table[ov_file].ft_pgsize;
1478 if ( pg_ptr->ovfl_addr == 0L ) {
1479 /* write to database */
1480 addr = lu_ptr->pageno * (long)pgsize;
1481 memcpy (pg_ptr->buff, &netorder_timestamp, sizeof(ULONG));
1484 /* write to overflow file */
1486 addr = pg_ptr->ovfl_addr;
1489 if ( dio_open(fno) == S_OKAY ) {
1490 swab_page (pg_ptr->buff, &file_table[fno], HTON);
1491 desc = file_table[fno].ft_desc;
1492 DB_LSEEK( desc, addr, 0 );
1493 if (DB_WRITE( desc, pg_ptr->buff, pgsize ) != pgsize) dberr(S_BADWRITE);
1495 MEM_UNLOCK(&pg_ptr->Buff);
1496 return( db_status );
1501 /****************************************/
1505 /****************************************/
1507 /* Read in a page to the buffer
1509 static int dio_in(pg_ptr, lu_ptr)
1510 PAGE_ENTRY FAR *pg_ptr; /* page table entry to be input */
1511 LOOKUP_ENTRY FAR *lu_ptr; /* corresponding to pg_ptr */
1513 /* Read in a page to the buffer
1515 static int dio_in(pg_ptr, lu_ptr, db_cache )
1516 PAGE_ENTRY FAR *pg_ptr; /* page table entry to be input */
1517 LOOKUP_ENTRY FAR *lu_ptr; /* corresponding to pg_ptr */
1518 BOOLEAN db_cache; /* TRUE if pg_ptr in db cache */
1521 int desc; /* file descriptor */
1522 int fno; /* file number */
1523 int pgsize; /* page size */
1524 long addr; /* file address */
1525 PGZERO FAR *pgzero_ptr;
1526 FILE_ENTRY FAR *file_ptr;
1529 file_ptr = &file_table[fno = lu_ptr->file];
1531 pgsize = file_ptr->ft_pgsize;
1532 addr = lu_ptr->pageno*pgsize;
1534 pgsize = db_cache ? file_ptr->ft_pgsize : file_table[ov_file].ft_pgsize;
1536 if (pg_ptr->ovfl_addr == 0L) {
1537 /* read from database file */
1538 /* if !db_cache, overflow address not set on initial read */
1539 addr = db_cache ? lu_ptr->pageno*pgsize :
1540 (pg_ptr->ovfl_addr = lu_ptr->pageno);
1543 /* read from overflow file */
1544 file_ptr = &file_table[fno = ov_file];
1545 addr = pg_ptr->ovfl_addr;
1548 if ( dio_open(fno) == S_OKAY ) {
1549 desc = file_ptr->ft_desc;
1550 DB_LSEEK(desc, addr, 0);
1551 MEM_LOCK(&pg_ptr->Buff);
1552 if ((r = DB_READ( desc, pg_ptr->buff, pgsize )) < pgsize) {
1553 byteset(&pg_ptr->buff[r], '\0', pgsize - r);
1554 DB_LSEEK(desc, addr, 0);
1555 if (DB_WRITE( desc, pg_ptr->buff, pgsize ) != pgsize) {
1556 /* clean up and return out of space */
1557 DB_LSEEK(desc, addr, 0);
1558 DB_WRITE(desc, "", 0);
1559 pgzero_ptr = &pgzero[fno];
1560 pgzero_ptr->pz_next--;
1561 pgzero_ptr->pz_modified = TRUE;
1566 swab_page (pg_ptr->buff, file_ptr, NTOH);
1567 MEM_UNLOCK(&pg_ptr->Buff);
1569 return( db_status );
1573 /***********************************************************************
1574 Page zero handling functions for data and key files
1575 ***********************************************************************/
1577 #ifndef NO_TIMESTAMP
1578 /* Increment and return file timestamp
1580 ULONG dio_pzsetts(fno )
1584 PGZERO FAR *pgzero_ptr;
1586 if ( db_tsrecs || db_tssets ) {
1587 pgzero_ptr = &pgzero[fno];
1588 pgzero_ptr->pz_modified = TRUE;
1589 ts = ++pgzero_ptr->pz_timestamp;
1598 /* Return file timestamp
1600 ULONG dio_pzgetts(fno)
1603 if ( pgzero[fno].pz_next == 0L )
1606 return ( pgzero[fno].pz_timestamp );
1611 /* Initialize page zero table
1613 static int dio_pzinit()
1616 PGZERO FAR *pgzero_ptr;
1619 if (debugging_dio_init) {
1620 printf (__FILE__"1430 dio_pzinit: szft=%d oldsz=%d\n",
1621 (int)size_ft, (int)old_size_ft);
1626 /* Macro references must be on one line for some compilers */
1627 if (ALLOC_TABLE(&db_global.Pgzero, size_ft*sizeof(PGZERO),
1628 old_size_ft*sizeof(PGZERO), "pgzero") != S_OKAY ) {
1630 if (debugging_dio_init) {
1631 printf (__FILE__"1444 pzinit: alloc_table failed, db_status=%d\n",
1636 return( db_status );
1639 /* read in page zeros */
1640 for (i = old_size_ft, pgzero_ptr = pgzero;
1642 ++i, ++pgzero_ptr) {
1643 pgzero_ptr->pz_dchain = 0L;
1644 pgzero_ptr->pz_next = 0L;
1645 pgzero_ptr->pz_timestamp = 0;
1646 pgzero_ptr->pz_modified = FALSE;
1648 return( db_status = S_OKAY );
1649 } /* dio_pzinit() */
1652 /****************************************/
1656 /****************************************/
1657 /* Flush page zero table
1658 * Complement to dio_out which writes all pages except page zero.
1660 static int dio_pzflush()
1664 register PGZERO FAR *pgzero_ptr;
1665 register FILE_ENTRY FAR *file_ptr;
1671 if ( (dboptions & TRLOGGING) && trans_id && !trcommit && use_ovfl ) {
1672 /* flush to overflow/log file -- before tx commit */
1673 for (i = 0, pgzero_ptr = pgzero; i < size_ft; ++i, ++pgzero_ptr) {
1674 if (pgzero_ptr->pz_modified )
1675 if ( o_pzwrite( i ) != S_OKAY ) return( db_status );
1680 /* flush modified page zeroes to database files */
1681 for (i = 0, pgzero_ptr = pgzero, file_ptr = file_table; i < size_ft;
1682 ++i, ++pgzero_ptr, ++file_ptr) {
1683 if ( pgzero_ptr->pz_modified ) {
1684 if ( dio_open(i) != S_OKAY )
1685 return( db_status );
1687 /* The only byte swap operations necessary
1688 * on a page zero are the first 5 LONG integers.
1690 for (j = 0, cptr = (char *) pgzero_ptr;
1691 j < PGZEROSZ/sizeof(LONG);
1692 ++j, cptr += sizeof(LONG)) {
1693 memcpy (&align_LONG, cptr, sizeof(LONG));
1695 memcpy (cptr, &align_LONG, sizeof(LONG));
1697 desc = file_ptr->ft_desc;
1698 DB_LSEEK(desc, 0L, 0);
1699 if (DB_WRITE(desc, (char FAR *)pgzero_ptr, PGZEROSZ) != PGZEROSZ)
1700 return( dberr(S_BADWRITE) );
1701 pgzero_ptr->pz_modified = FALSE;
1704 d_trlog(i, 0, (char FAR *)pgzero_ptr, PGZEROSZ);
1714 return( db_status = S_OKAY );
1715 } /* dio_pzflush() */
1718 /****************************************/
1722 /****************************************/
1723 /* Read a file's page zero
1726 FILE_NO fno; /* file number */
1728 FILE_ENTRY FAR *file_ptr;
1729 PGZERO FAR *pgzero_ptr;
1731 pgzero_ptr = &pgzero[fno];
1732 file_ptr = &file_table[fno];
1734 /* open this file, if not already open */
1736 if (file_ptr->ft_desc < 0) {
1737 pgzero_ptr->pz_dchain = 0;
1738 pgzero_ptr->pz_next = 0;
1739 pgzero_ptr->pz_timestamp = 0;
1740 pgzero_ptr->pz_modified = FALSE;
1741 return( db_status ); /* db_status set by dio_open */
1744 /* seek to and read page zero */
1745 DB_LSEEK(file_ptr->ft_desc, 0L, 0);
1746 if ( DB_READ(file_ptr->ft_desc, (char FAR *)pgzero_ptr, PGZEROSZ)
1748 return( dberr(S_BADREAD) );
1750 NTOHL (pgzero_ptr->pz_dchain);
1751 NTOHL (pgzero_ptr->pz_next);
1752 NTOHL (pgzero_ptr->pz_timestamp);
1753 return( db_status = S_OKAY );
1754 } /* dio_pzread() */
1758 /****************************************/
1762 /****************************************/
1763 /* Allocate new record slot or key node from page zero,
1764 * ie from delete chain if possible.
1765 * Returns memory address of the free slot into 'loc'.
1767 dio_pzalloc(fno, loc )
1768 FILE_NO fno; /* file number */
1769 F_ADDR *loc; /* pointer to allocated location */
1774 PGZERO FAR *pgzero_ptr;
1777 /* check shared access priviledges */
1778 if ( dbopen == 1 && !trans_id && !excl_locks[fno] )
1779 return( dberr(S_NOTRANS) );
1782 pgzero_ptr = &pgzero[fno];
1783 if ( pgzero_ptr->pz_next == 0L )
1784 if ( dio_pzread(fno) != S_OKAY )
1785 RETURN( db_status );
1786 if ( file_table[fno].ft_type == KEY ) {
1787 if ( working_file != fno )
1788 return( dberr(S_NOWORK) );
1789 if ( pgzero_ptr->pz_dchain == NONE || ! (dboptions & DCHAINUSE) ) {
1790 if ( pgzero_ptr->pz_next == MAXRECORDS-1 )
1791 return( dberr(S_RECLIMIT) );
1792 pg = pgzero_ptr->pz_next++;
1795 pg = pgzero_ptr->pz_dchain;
1796 if ( dio_get( pg, (char FAR * FAR *)&ptr, NOPGHOLD ) != S_OKAY )
1797 return( db_status );
1798 /* Get the first key node on the delete chain.
1799 * (sizeof external timestamp set to 4 bytes)
1800 ****** bytecpy(&pgzero_ptr->pz_dchain,
1801 ****** ptr+sizeof(long)+sizeof(INT), sizeof(F_ADDR)); *********
1803 bytecpy (&pgzero_ptr->pz_dchain,
1804 ptr + sizeof(LONG) + sizeof(INT), sizeof(F_ADDR));
1808 if ( ! pgzero_ptr->pz_dchain || ! (dboptions & DCHAINUSE) ) {
1809 if ( pgzero_ptr->pz_next == MAXRECORDS )
1810 return( dberr(S_RECLIMIT) );
1811 pg = pgzero_ptr->pz_next++;
1814 pg = pgzero_ptr->pz_dchain;
1815 dba = ((NUM2EXT(fno, ft_offset) & FILEMASK) << FILESHIFT) | pg;
1816 if ( dio_read(dba, (char FAR * FAR *)&ptr, NOPGHOLD) != S_OKAY )
1817 return( db_status );
1818 bytecpy(&pgzero_ptr->pz_dchain, ptr+sizeof(INT), sizeof(F_ADDR));
1822 pgzero_ptr->pz_modified = TRUE;
1823 return( db_status = S_OKAY );
1824 } /* dio_pzalloc() */
1827 /****************************************/
1831 /****************************************/
1832 /* Delete record slot or key node from page zero
1834 dio_pzdel(fno, loc )
1835 FILE_NO fno; /* file number */
1836 F_ADDR loc; /* location to be freed */
1841 PGZERO FAR *pgzero_ptr;
1844 /* check shared access priviledges */
1845 if ( dbopen == 1 && !trans_id && !excl_locks[fno] )
1846 return( dberr(S_NOTRANS) );
1849 pgzero_ptr = &pgzero[fno];
1850 if ( pgzero_ptr->pz_next == 0L )
1851 if ( dio_pzread(fno) != S_OKAY )
1852 RETURN( db_status );
1853 if ( file_table[fno].ft_type == KEY ) {
1854 if ( working_file != fno )
1855 return( dberr(S_NOWORK) );
1856 if ( dio_get( loc, (char FAR * FAR *)&ptr, PGHOLD ) != S_OKAY )
1857 return( db_status );
1858 /*********************************************
1859 * Delete chain ptr in key node page is in location
1860 * of orphan ptr, bytes 6 - 9, not bytes 4 - 7
1861 * as printed in raima User Guide.
1862 * (sizeof external timestamp set to 4 bytes).
1863 ****** bytecpy(ptr+sizeof(long)+sizeof(INT),
1864 ****** &pgzero_ptr->pz_dchain, sizeof(F_ADDR)); *********
1865 *****************************************/
1866 bytecpy (ptr + sizeof(LONG) + sizeof(INT),
1867 &pgzero_ptr->pz_dchain, sizeof(F_ADDR));
1868 pgzero_ptr->pz_dchain = loc;
1872 dba = ((NUM2EXT(fno, ft_offset) & FILEMASK) << FILESHIFT) | loc;
1873 if ( dio_read( dba, (char FAR * FAR *)&ptr , NOPGHOLD) != S_OKAY )
1874 return( db_status );
1875 bytecpy(&recnum, ptr, sizeof(INT));
1876 recnum = ~recnum; /* indicates deleted record */
1877 bytecpy(ptr, &recnum, sizeof(INT));
1878 bytecpy(ptr+sizeof(INT), &pgzero_ptr->pz_dchain, sizeof(F_ADDR));
1879 pgzero_ptr->pz_dchain = loc;
1880 if ( dio_write(dba, NULL, NOPGFREE) != S_OKAY )
1881 return( db_status );
1883 pgzero_ptr->pz_modified = TRUE;
1884 return( db_status = S_OKAY );
1888 /****************************************/
1892 /****************************************/
1893 /* Return pz_next for file fno
1895 F_ADDR dio_pznext(fno)
1898 if ( pgzero[fno].pz_next == 0L )
1900 return ( pgzero[fno].pz_next );
1903 /****************************************/
1907 /****************************************/
1908 /* Clear page zero cache
1913 register PGZERO FAR *pgzero_ptr;
1915 for (i = 0, pgzero_ptr = pgzero; i < size_ft; i++, pgzero_ptr++) {
1916 if (pgzero_ptr->pz_modified) {
1917 pgzero_ptr->pz_next = 0L;
1918 pgzero_ptr->pz_modified = FALSE;
1923 /* vpp -nOS2 -dUNIX -nBSD -nVANILLA_BSD -nVMS -nMEMLOCK -nWINDOWS -nFAR_ALLOC -f/usr/users/master/config/nonwin dio.c */