1335 lines
35 KiB
C
1335 lines
35 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/*
|
|
* COMPONENT_NAME: austext
|
|
*
|
|
* FUNCTIONS: EXCL_OPEN
|
|
* Pi
|
|
* cache_init
|
|
* clear_cache
|
|
* d_setfiles
|
|
* d_setpages
|
|
* dio_clear
|
|
* dio_close
|
|
* dio_clrfile
|
|
* dio_findpg
|
|
* dio_flush
|
|
* dio_free
|
|
* dio_get
|
|
* dio_in
|
|
* dio_init
|
|
* dio_open
|
|
* dio_out
|
|
* dio_pzalloc
|
|
* dio_pzclr
|
|
* dio_pzdel
|
|
* dio_pzflush
|
|
* dio_pzgetts
|
|
* dio_pzinit
|
|
* dio_pznext
|
|
* dio_pzread
|
|
* dio_pzsetts
|
|
* dio_read
|
|
* dio_release
|
|
* dio_rrlb
|
|
* dio_setdef
|
|
* dio_touch
|
|
* dio_write
|
|
* dio_wrlb
|
|
*
|
|
* ORIGINS: 27, 157
|
|
*
|
|
* This module contains IBM CONFIDENTIAL code. -- (IBM
|
|
* Confidential Restricted when combined with the aggregated
|
|
* modules for this product)
|
|
*
|
|
* OBJECT CODE ONLY SOURCE MATERIALS
|
|
* (C) COPYRIGHT International Business Machines Corp. 1995, 1996
|
|
* All Rights Reserved
|
|
* US Government Users Restricted Rights - Use, duplication or
|
|
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
|
|
*/
|
|
/*------------------------------------------------------------------------
|
|
$XConsortium: dio.c /main/7 1996/11/25 18:48:24 drk $
|
|
dio - Database Input/Output Control Functions
|
|
|
|
Copyright (C) 1984, 1985, 1986, 1987 by Raima Corporation
|
|
------------------------------------------------------------------------*/
|
|
|
|
/* ********************** EDIT HISTORY *******************************
|
|
|
|
SCR DATE INI DESCRIPTION
|
|
----- --------- --- -----------------------------------------------------
|
|
76 16-JUN-88 RSC Clean up so SINGLE_USER produces good code
|
|
240 20-Jun-88 RSC Clean up so NO_TRANS produces good code
|
|
103 24-Jun-88 RSC Improve generation of single user version
|
|
295 01-Jul-88 RSC make cnt_open_files global, to support initial.c mods
|
|
333 05-Jul-88 RSC make wrlb only fiddle with rlb, not entire rid
|
|
115 18-Jul-88 RSC Integrate VAX VMS changes into master code
|
|
366 25-Jul-88 RSC dio_pzread should use dio_open, not DB_OPEN
|
|
04-Aug-88 RTK MULTI_TASK changes
|
|
11-Aug-88 RTK d_setpages and d_setfiles must return immediately if
|
|
another task already has opened a database.
|
|
115 16-Aug-88 RSC Fixup of VMS integration
|
|
423 10-Sep-88 RSC Fixup of multi-task compile problems
|
|
420 15-Sep-88 RTK Encompassed calls to dio_unlock within an ifdef MEMLOCK
|
|
423 15-Sep-88 RSC Also cleared last_dblu in clear_cache
|
|
423 15-Sep-88 RSC Removed '#' from ifdef two lines up - vpp no like!!!!!
|
|
420 16-Sep-88 RTK A couple missing FAR's
|
|
425 05-Oct-88 RSC d_trabort wasn't completely clearing page zero, added
|
|
dio_pzclr to support d_trabort
|
|
433 31-Oct-88 RSC Fix for SCR #423 wasn't quite right - query wouldn't run
|
|
532 06-Jan-89 RSC Fix code so NO_TRANS compiles correctly
|
|
08-Feb-89 RSC Fix from AMCY - clear cache wasn't completely swapping.
|
|
420 13-Feb-89 WLW Cleared last_dblu in clear_cache (only safe thing to do)
|
|
14-Feb-89 RSC Misc fixes
|
|
588 16-Feb-89 RSC remove ifndef SINGLE_USER around CLOSE_FILES
|
|
612 21-Feb-89 RSC always clear ovfl_addr in dbpg_table
|
|
619 09-Mar-89 WLW call o_fileinit from dio_pzgetts, don't call dio_pzsetts
|
|
from dio_pzread.
|
|
05-May-89 WLW Added ".v" tag to Currtask for MULTI_TASKing
|
|
|
|
$Log$
|
|
* Revision 1.2 1995/10/17 19:15:37 miker
|
|
* Changed open mode from hardcoded O_RDWR to global var db_oflag.
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <time.h>
|
|
#include "vista.h"
|
|
#include "dbtype.h"
|
|
#include "dbswab.h"
|
|
|
|
#define DEBUG_DIO
|
|
#ifdef DEBUG_DIO
|
|
int debugging_dio_init = FALSE;
|
|
int debugging_dio_close = FALSE;
|
|
#endif
|
|
|
|
|
|
#define EXCL_OPEN() (TRUE)
|
|
|
|
#define DEFDBPAGES 16 /* default number of database cache pages */
|
|
#define MINDBPAGES 8 /* minimum number of database cache pages */
|
|
|
|
extern BOOLEAN trcommit;
|
|
|
|
int db_pgtab_sz = DEFDBPAGES;
|
|
|
|
LOOKUP_ENTRY_P Db_lookup = POINTER_INIT(); /* database page lookup table */
|
|
PAGE_ENTRY_P Dbpg_table = POINTER_INIT(); /* database page table */
|
|
static struct
|
|
{
|
|
FILE_NO file;
|
|
F_ADDR pageno;
|
|
int slot;
|
|
} last_dblu; /* last found lookup entry in cache */
|
|
|
|
/* maximum number of open files allowed by
|
|
operating system (user settable) */
|
|
/* On VMS systems, max_open_files need to be defined with a globaldef
|
|
instead of just a normal external. This will force this module to be
|
|
included, thus giving a default value to max_open_files. If it were
|
|
just a normal external the VMS linker would not load this module unless
|
|
a reference to a function in it is made and it would leave max_open_files
|
|
with a value of 0. */
|
|
int max_open_files = 8;
|
|
INT_P Used_files = POINTER_INIT(); /* LRU file table */
|
|
int cnt_open_files = 0; /* count of currently open files */
|
|
static int last_file = 0; /* least recently used file */
|
|
|
|
static int dbpg_lru_slot; /* least recently accessed db page */
|
|
static int no_modheld; /* number of modified or held db pages */
|
|
static FILE_NO working_file; /* current key file being processed */
|
|
|
|
static void cache_init(int, LOOKUP_ENTRY *, PAGE_ENTRY *, int);
|
|
static int dio_pzinit(void);
|
|
static int clear_cache(FILE_NO, FILE_NO);
|
|
static int dio_pzflush(void);
|
|
static int dio_in(PAGE_ENTRY *, LOOKUP_ENTRY *);
|
|
|
|
#define used_files Used_files.ptr
|
|
#define db_lookup Db_lookup.ptr
|
|
#define dbpg_table Dbpg_table.ptr
|
|
|
|
|
|
|
|
/* Set the maximum number of open db_VISTA files
|
|
*/
|
|
int
|
|
d_setfiles(int num)
|
|
{
|
|
if ( dbpg_table ) return( dberr(S_DBCLOSE) );
|
|
|
|
if ( num > 0 && num < 256 )
|
|
max_open_files = num;
|
|
|
|
return( db_status = S_OKAY );
|
|
}
|
|
|
|
|
|
/* Set number of virtual memory pages
|
|
*/
|
|
int
|
|
d_setpages(
|
|
int dbpgs, /* # of db cache pages */
|
|
int ixpgs /* # of index cache pages - ignored in single-user version */
|
|
)
|
|
{
|
|
if ( dbpg_table ) return( dberr(S_SETPAGES) );
|
|
|
|
db_pgtab_sz = (dbpgs <= MINDBPAGES) ? MINDBPAGES : dbpgs;
|
|
|
|
return( db_status = S_OKAY );
|
|
}
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_open */
|
|
/* */
|
|
/****************************************/
|
|
/* Open a database file
|
|
*/
|
|
int
|
|
dio_open(FILE_NO fno)
|
|
{
|
|
FILE_ENTRY *file_ptr, *lru_file_ptr;
|
|
int *uf_ptr;
|
|
|
|
file_ptr = &file_table[fno];
|
|
if ( file_ptr->ft_status == CLOSED ) {
|
|
if ( cnt_open_files == max_open_files ) {
|
|
/* find least recently used file */
|
|
uf_ptr = &used_files[last_file];
|
|
lru_file_ptr = &file_table[last_file];
|
|
while (*uf_ptr || (lru_file_ptr->ft_status == CLOSED)) {
|
|
*uf_ptr = FALSE;
|
|
if (++last_file >= size_ft) {
|
|
last_file = 0;
|
|
lru_file_ptr = file_table;
|
|
uf_ptr = used_files;
|
|
}
|
|
else {
|
|
++lru_file_ptr;
|
|
++uf_ptr;
|
|
}
|
|
}
|
|
dio_close(last_file);
|
|
if (++last_file >= size_ft)
|
|
last_file = 0;
|
|
}
|
|
used_files[fno] = TRUE;
|
|
|
|
file_ptr->ft_desc = open_b(file_ptr->ft_name, db_oflag);
|
|
if (file_ptr->ft_desc < 0)
|
|
return( dberr( S_NOFILE ) );
|
|
file_ptr->ft_status = OPEN;
|
|
++cnt_open_files;
|
|
}
|
|
return( db_status = S_OKAY );
|
|
} /* dio_open() */
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_close */
|
|
/* */
|
|
/****************************************/
|
|
/* Close a database file
|
|
*/
|
|
int
|
|
dio_close(FILE_NO fno)
|
|
{
|
|
FILE_ENTRY *file_ptr;
|
|
|
|
file_ptr = &file_table[fno];
|
|
if ( file_ptr->ft_status == OPEN ) {
|
|
DB_CLOSE( file_ptr->ft_desc );
|
|
file_ptr->ft_status = CLOSED;
|
|
--cnt_open_files;
|
|
}
|
|
return( db_status = S_OKAY );
|
|
}
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_init */
|
|
/* */
|
|
/****************************************/
|
|
/* Initialize database I/O
|
|
*/
|
|
int
|
|
dio_init(void)
|
|
{
|
|
CHAR_P Tempbuff;
|
|
#define tempbuff Tempbuff.ptr
|
|
|
|
#ifdef DEBUG_DIO
|
|
if (debugging_dio_init) {
|
|
printf (__FILE__"300 dio_init: dbpgtab=%p pgsz=%d largest=%d\n",
|
|
(void *) dbpg_table, (int)page_size, (int)largest_page);
|
|
fflush(stdout);
|
|
}
|
|
#endif
|
|
|
|
if ( dbpg_table ) {
|
|
if ( dio_pzinit() != S_OKAY ) {
|
|
return( db_status );
|
|
}
|
|
if ( page_size > largest_page ) {
|
|
if ( (tempbuff = ALLOC(&Tempbuff, page_size, "tempbuff")) == NULL )
|
|
return( dberr(S_NOMEMORY) );
|
|
largest_page = page_size;
|
|
}
|
|
#ifdef DEBUG_DIO
|
|
if (debugging_dio_init) {
|
|
printf (__FILE__"323 dio_init: pzinited ok. pgsz=%d largest=%d\n",
|
|
(int)page_size, (int)largest_page);
|
|
fflush(stdout);
|
|
}
|
|
#endif
|
|
|
|
return( S_OKAY );
|
|
} /* end if ( dbpg_table ) */
|
|
|
|
used_files =
|
|
/* Macro references must be on one line for some compilers */
|
|
(int *)ALLOC(&Used_files, (size_ft+1)*sizeof(int), "used_files");
|
|
db_lookup =
|
|
/* Macro references must be on one line for some compilers */
|
|
(LOOKUP_ENTRY *)
|
|
ALLOC(&Db_lookup, db_pgtab_sz*sizeof(LOOKUP_ENTRY), "db_lookup");
|
|
dbpg_table =
|
|
/* Macro references must be on one line for some compilers */
|
|
(PAGE_ENTRY *)
|
|
ALLOC(&Dbpg_table, db_pgtab_sz*sizeof(PAGE_ENTRY), "dbpg_table");
|
|
#ifdef DEBUG_DIO
|
|
if (debugging_dio_init) {
|
|
printf (__FILE__"345 dio_init: usedfls=%p lookup=%p pgtab=%p\n",
|
|
(void *) used_files, (void *) db_lookup, (void *) dbpg_table);
|
|
fflush(stdout);
|
|
}
|
|
#endif
|
|
if ( !used_files || !dbpg_table || !db_lookup )
|
|
return( dberr(S_NOMEMORY) );
|
|
byteset(used_files, 0, (size_ft + 1)*sizeof(*used_files));
|
|
|
|
last_dblu.file = -1;
|
|
last_dblu.pageno = -1L;
|
|
last_dblu.slot = -1;
|
|
|
|
/* initialize database cache */
|
|
cache_init((int)db_pgtab_sz, db_lookup, dbpg_table, (int)page_size);
|
|
/***cache_init(db_pgtab_sz, db_lookup, dbpg_table, page_size);****/
|
|
if (db_status != S_OKAY) return(db_status);
|
|
last_file = 0;
|
|
dbpg_lru_slot = 0;
|
|
no_modheld = 0;
|
|
working_file = NONE;
|
|
|
|
/* initialize the page zero table and return */
|
|
#ifdef DEBUG_DIO
|
|
if (debugging_dio_init) {
|
|
puts (__FILE__"390 dio_init: last act is call to dio_pzinit.");
|
|
fflush(stdout);
|
|
}
|
|
#endif
|
|
return( dio_pzinit() );
|
|
#undef tempbuff
|
|
} /* dio_init() */
|
|
|
|
|
|
static void
|
|
cache_init (int pg_cnt, LOOKUP_ENTRY *lu_ptr, PAGE_ENTRY * pg_ptr, int pgsize)
|
|
{
|
|
int pg_no;
|
|
|
|
#ifdef DEBUG_DIO
|
|
if (debugging_dio_init) {
|
|
printf (__FILE__"400 cache_init: pgcnt=%d lu=%p pgp=%p pgsz=%d\n",
|
|
pg_cnt, (void *) lu_ptr, (void *) pg_ptr, pgsize);
|
|
fflush(stdout);
|
|
}
|
|
#endif
|
|
|
|
for (pg_no = 0; pg_no < pg_cnt; ++pg_no, ++lu_ptr, ++pg_ptr)
|
|
{
|
|
lu_ptr->file = -1;
|
|
lu_ptr->pageno = -1L;
|
|
lu_ptr->pg_slot = pg_no;
|
|
|
|
pg_ptr->lu_slot = pg_no;
|
|
pg_ptr->recently_used = FALSE;
|
|
pg_ptr->modified = FALSE;
|
|
pg_ptr->holdcnt = 0;
|
|
pg_ptr->buff = ALLOC(&pg_ptr->Buff, pgsize, db_avname);
|
|
if (pg_ptr->buff == NULL) {
|
|
#ifdef DEBUG_DIO
|
|
if (debugging_dio_init) {
|
|
printf (__FILE__"428 cache_init: alloc failed pgsz=%d\n",
|
|
pgsize);
|
|
fflush(stdout);
|
|
}
|
|
#endif
|
|
dberr(S_NOMEMORY);
|
|
return;
|
|
}
|
|
MEM_UNLOCK(&pg_ptr->Buff);
|
|
} /* end loop on pg_cnt */
|
|
return;
|
|
} /* cache_init() */
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_free */
|
|
/* */
|
|
/****************************************/
|
|
/* Free the memory allocated for pages
|
|
*/
|
|
void dio_free(void)
|
|
{
|
|
int pgt_lc; /* loop control */
|
|
PAGE_ENTRY *pg_ptr;
|
|
|
|
MEM_UNLOCK(&db_global.Pgzero);
|
|
FREE(&db_global.Pgzero);
|
|
MEM_UNLOCK(&Used_files);
|
|
FREE(&Used_files);
|
|
MEM_UNLOCK(&Db_lookup);
|
|
FREE(&Db_lookup);
|
|
for (pgt_lc = db_pgtab_sz, pg_ptr = dbpg_table; --pgt_lc >= 0; ++pg_ptr) {
|
|
MEM_UNLOCK(&pg_ptr->Buff);
|
|
FREE(&pg_ptr->Buff);
|
|
}
|
|
MEM_UNLOCK(&Dbpg_table);
|
|
FREE(&Dbpg_table);
|
|
} /* dio_free() */
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_clrfile */
|
|
/* */
|
|
/****************************************/
|
|
/* Clear pages for a single file.
|
|
*/
|
|
int
|
|
dio_clrfile(FILE_NO fno)
|
|
{
|
|
return( clear_cache(fno, fno+1) );
|
|
}
|
|
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_clear */
|
|
/* */
|
|
/****************************************/
|
|
/* Clear all pages for *all* files from I/O buffer
|
|
*/
|
|
int
|
|
dio_clear(void)
|
|
{
|
|
return( clear_cache(0, size_ft) );
|
|
}
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* clear_cache */
|
|
/* */
|
|
/****************************************/
|
|
/* Clear database page cache.
|
|
* Clears all pages for a range of specified files.
|
|
* Subroutine of dio_clrfile and dio_clear.
|
|
*/
|
|
static int clear_cache(
|
|
FILE_NO fr_file, /* clear from file "fr_file" */
|
|
FILE_NO to_file /* ..to (not thru) file "to_file" */
|
|
)
|
|
{
|
|
FILE_NO s_file; /* start file to be cleared */
|
|
FILE_NO e_file; /* end file (+1) to be cleared */
|
|
int i;
|
|
LOOKUP_ENTRY *lu_ptr, *lu2_ptr;
|
|
int pg_slot;
|
|
PAGE_ENTRY *pg_ptr;
|
|
PGZERO *pgzero_ptr;
|
|
FILE_ENTRY *file_ptr;
|
|
|
|
for (s_file = e_file = fr_file, file_ptr = &file_table[e_file];
|
|
s_file < to_file;
|
|
++file_ptr) {
|
|
if ((e_file < to_file) &&
|
|
!(file_ptr->ft_flags & STATIC))
|
|
++e_file;
|
|
else {
|
|
if (s_file < e_file) {
|
|
/* find range of pages to be cleared */
|
|
dio_findpg(s_file, 0L, NULL, NULL, &lu_ptr);
|
|
dio_findpg(e_file, 0L, NULL, NULL, &lu2_ptr);
|
|
|
|
last_dblu.file = -1;
|
|
last_dblu.pageno = -1L;
|
|
last_dblu.slot = -1;
|
|
|
|
if (lu_ptr < lu2_ptr) { /* otherwise file has no pages in cache */
|
|
/* adjust lookup table entries */
|
|
while ((lu_ptr > db_lookup) && ((--lu_ptr)->file >= 0)) {
|
|
--lu2_ptr;
|
|
|
|
lu2_ptr->file = lu_ptr->file;
|
|
lu2_ptr->pageno = lu_ptr->pageno;
|
|
/* exchange page slot numbers */
|
|
pg_slot = lu_ptr->pg_slot;
|
|
lu_ptr->pg_slot = lu2_ptr->pg_slot;
|
|
lu2_ptr->pg_slot = pg_slot;
|
|
dbpg_table[pg_slot].lu_slot = lu2_ptr - db_lookup;
|
|
dbpg_table[lu_ptr->pg_slot].lu_slot = lu_ptr - db_lookup;
|
|
}
|
|
|
|
if ( lu_ptr->file < 0 )
|
|
++lu_ptr;
|
|
|
|
while (lu_ptr < lu2_ptr) {
|
|
|
|
lu_ptr->file = -1;
|
|
lu_ptr->pageno = -1L;
|
|
pg_ptr = &dbpg_table[lu_ptr->pg_slot];
|
|
if ( pg_ptr->modified || pg_ptr->holdcnt ) {
|
|
--no_modheld;
|
|
pg_ptr->modified = FALSE;
|
|
}
|
|
pg_ptr->recently_used = FALSE;
|
|
pg_ptr->holdcnt = 0;
|
|
++lu_ptr;
|
|
}
|
|
}
|
|
/* clear page zeroes and close files */
|
|
for (i = s_file, pgzero_ptr = &pgzero[i];
|
|
i < e_file;
|
|
++i, ++pgzero_ptr) {
|
|
pgzero_ptr->pz_modified = FALSE;
|
|
pgzero_ptr->pz_next = 0L;
|
|
#ifdef CLOSE_FILES
|
|
dio_close(i);
|
|
#endif
|
|
}
|
|
}
|
|
s_file = ++e_file;
|
|
}
|
|
}
|
|
return( db_status = S_OKAY );
|
|
} /* clear_cache() */
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_flush */
|
|
/* */
|
|
/****************************************/
|
|
/* Flushes entire database I/O cache.
|
|
* Writes out all modified cache pages to respective files (dio_out),
|
|
* then writes out page zero (dio_pzflush).
|
|
*/
|
|
int dio_flush(void)
|
|
{
|
|
int pgt_lc; /* loop control */
|
|
PAGE_ENTRY *pg_ptr;
|
|
LOOKUP_ENTRY *lu_ptr;
|
|
|
|
#ifdef DEBUG_DIO
|
|
if (debugging_dio_close) {
|
|
printf (__FILE__"685 dio_flush: check cache dbpgtab=%p count=%d\n",
|
|
(void *) dbpg_table, (int)db_pgtab_sz);
|
|
fflush(stdout);
|
|
}
|
|
#endif
|
|
if ( dbpg_table == NULL ) return( db_status = S_OKAY );
|
|
|
|
for (pgt_lc = db_pgtab_sz, pg_ptr = dbpg_table; --pgt_lc >= 0; ++pg_ptr) {
|
|
if (!pg_ptr->modified) {
|
|
continue;
|
|
}
|
|
lu_ptr = &db_lookup[pg_ptr->lu_slot];
|
|
/* write directly to database */
|
|
#ifdef DEBUG_DIO
|
|
if (debugging_dio_close) {
|
|
printf (__FILE__"723 dio_flush: write modified pg#%d @ %p\n",
|
|
db_pgtab_sz - pgt_lc, (void *) pg_ptr);
|
|
fflush(stdout);
|
|
}
|
|
#endif
|
|
if (dio_out(pg_ptr, lu_ptr) != S_OKAY) return( db_status );
|
|
pg_ptr->holdcnt = 0;
|
|
pg_ptr->modified = FALSE;
|
|
--no_modheld;
|
|
}
|
|
/* store the page zero values in the data file and return */
|
|
return( dio_pzflush() );
|
|
} /* dio_flush() */
|
|
|
|
|
|
|
|
/* Set the default file number
|
|
*/
|
|
void dio_setdef(FILE_NO file_no)
|
|
{
|
|
working_file = file_no;
|
|
}
|
|
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_get */
|
|
/* */
|
|
/****************************************/
|
|
/* Database I/O page get
|
|
*/
|
|
int
|
|
dio_get(F_ADDR page_no, char **page_ptr, int hold)
|
|
{
|
|
PAGE_ENTRY *pg_ptr;
|
|
|
|
if ( pgzero[working_file].pz_next == 0L )
|
|
if ( dio_pzread(working_file) != S_OKAY )
|
|
RETURN( db_status );
|
|
|
|
if (dio_findpg(working_file, page_no, dbpg_table, &pg_ptr, NULL) == S_OKAY) {
|
|
MEM_LOCK(&pg_ptr->Buff);
|
|
*page_ptr = pg_ptr->buff;
|
|
pg_ptr->recently_used = TRUE;
|
|
used_files[working_file] = TRUE;
|
|
if ( hold ) {
|
|
if ( ++pg_ptr->holdcnt > 1 )
|
|
dberr(S_SYSERR);
|
|
else if ( ! pg_ptr->modified )
|
|
++no_modheld;
|
|
}
|
|
}
|
|
return( db_status );
|
|
} /* dio_get() */
|
|
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_touch */
|
|
/* */
|
|
/****************************************/
|
|
/* Set modified flag for a page
|
|
*/
|
|
int
|
|
dio_touch(F_ADDR page_no)
|
|
{
|
|
PAGE_ENTRY *pg_ptr;
|
|
|
|
if (dio_findpg(working_file, page_no, dbpg_table, &pg_ptr, NULL) == S_OKAY ) {
|
|
pg_ptr->recently_used = TRUE;
|
|
used_files[working_file] = TRUE;
|
|
if ( ! pg_ptr->modified ) {
|
|
pg_ptr->modified = TRUE;
|
|
if ( ! pg_ptr->holdcnt )
|
|
++no_modheld;
|
|
}
|
|
if ( pg_ptr->holdcnt > 0 ) {
|
|
--pg_ptr->holdcnt;
|
|
if ( pg_ptr->holdcnt ) {
|
|
db_status = S_OKAY;
|
|
}
|
|
MEM_UNLOCK(&pg_ptr->Buff);
|
|
}
|
|
}
|
|
return( db_status );
|
|
} /* dio_touch() */
|
|
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_read */
|
|
/* */
|
|
/****************************************/
|
|
/* Database I/O read
|
|
* Merely returns ptr into rec in a page
|
|
* unless a page swap is necessary.
|
|
*/
|
|
int
|
|
dio_read(DB_ADDR dba, char * *recptr, int hold)
|
|
{
|
|
FILE_NO file;
|
|
int offset;
|
|
F_ADDR us1, us2;
|
|
FILE_ENTRY *file_ptr;
|
|
PAGE_ENTRY *pg_ptr;
|
|
|
|
file = NUM2INT((FILE_NO)((dba >> FILESHIFT) & FILEMASK), ft_offset);
|
|
file_ptr = &file_table[file];
|
|
|
|
if ( pgzero[file].pz_next == 0L )
|
|
if ( dio_pzread(file) != S_OKAY )
|
|
RETURN( db_status );
|
|
|
|
us1 = ADDRMASK & dba;
|
|
us2 = (us1 - 1)/file_ptr->ft_slots;
|
|
if (dio_findpg(file, us2 + 1, dbpg_table, &pg_ptr, NULL) == S_OKAY ) {
|
|
pg_ptr->recently_used = TRUE;
|
|
used_files[file] = TRUE;
|
|
offset = file_ptr->ft_slsize*(int)(us1 - 1 - us2*file_ptr->ft_slots) +
|
|
PGHDRSIZE;
|
|
MEM_LOCK(&pg_ptr->Buff);
|
|
*recptr = &pg_ptr->buff[offset];
|
|
if ( hold ) {
|
|
if ( (++pg_ptr->holdcnt == 1) && !pg_ptr->modified) {
|
|
++no_modheld;
|
|
}
|
|
}
|
|
}
|
|
return( db_status );
|
|
} /* dio_read() */
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_write */
|
|
/* */
|
|
/****************************************/
|
|
/* Database I/O write: copies data record into a page slot.
|
|
* Finds record's page, swapping it into cache if necessary.
|
|
* Sets page's 'touched' flags, timestamps, etc.
|
|
* If recptr not NULL, copies rec to page cache.
|
|
*/
|
|
int
|
|
dio_write(DB_ADDR dba, const char *recptr, int release)
|
|
{
|
|
FILE_NO file;
|
|
F_ADDR us1, us2;
|
|
int offset;
|
|
FILE_ENTRY *file_ptr;
|
|
PAGE_ENTRY *pg_ptr;
|
|
|
|
file = NUM2INT((FILE_NO)((dba >> FILESHIFT) & FILEMASK), ft_offset);
|
|
|
|
file_ptr = &file_table[file];
|
|
us1 = ADDRMASK & dba;
|
|
us2 = (us1 - 1)/file_ptr->ft_slots;
|
|
if (dio_findpg(file, us2 + 1, dbpg_table, &pg_ptr, NULL) == S_OKAY ) {
|
|
pg_ptr->recently_used = TRUE;
|
|
used_files[file] = TRUE;
|
|
if ( recptr != NULL ) {
|
|
offset = file_ptr->ft_slsize*(int)(us1 - 1 - us2*file_ptr->ft_slots) +
|
|
PGHDRSIZE;
|
|
MEM_LOCK(&pg_ptr->Buff);
|
|
bytecpy(&pg_ptr->buff[offset], recptr, file_ptr->ft_slsize);
|
|
MEM_UNLOCK(&pg_ptr->Buff);
|
|
}
|
|
if ( ! pg_ptr->modified ) {
|
|
pg_ptr->modified = TRUE;
|
|
if ( ! pg_ptr->holdcnt )
|
|
++no_modheld;
|
|
}
|
|
if ( release ) {
|
|
if ( --pg_ptr->holdcnt < 0 )
|
|
dberr(S_SYSERR);
|
|
MEM_UNLOCK(&pg_ptr->Buff);
|
|
}
|
|
}
|
|
return( db_status );
|
|
} /* dio_write() */
|
|
|
|
|
|
/* Release database page hold
|
|
*/
|
|
int
|
|
dio_release(DB_ADDR dba)
|
|
{
|
|
FILE_NO file;
|
|
F_ADDR us1, us2;
|
|
PAGE_ENTRY *pg_ptr;
|
|
|
|
file = NUM2INT((FILE_NO)((dba >> FILESHIFT) & FILEMASK), ft_offset);
|
|
us1 = ADDRMASK & dba;
|
|
us2 = file_table[file].ft_slots;
|
|
if (dio_findpg(file, ((us1 - 1)/us2) + 1, dbpg_table, &pg_ptr,
|
|
NULL) == S_OKAY) {
|
|
if (pg_ptr->holdcnt) {
|
|
--pg_ptr->holdcnt;
|
|
if ( !pg_ptr->holdcnt && !pg_ptr->modified )
|
|
--no_modheld;
|
|
MEM_UNLOCK(&pg_ptr->Buff);
|
|
}
|
|
}
|
|
return( db_status );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_findpg */
|
|
/* */
|
|
/****************************************/
|
|
/* Search a cache for page
|
|
*/
|
|
int
|
|
dio_findpg(
|
|
FILE_NO file, /* file number = 0..size_ft-1 */
|
|
F_ADDR page, /* database page number */
|
|
PAGE_ENTRY *pg_table, /* = dbpg_table, ixpg_table, or NULL */
|
|
PAGE_ENTRY * *xpg_ptr, /* pointer to page table entry for found page */
|
|
LOOKUP_ENTRY * *xlu_ptr /* pointer to lookup table slot for found page*/
|
|
)
|
|
{
|
|
LOOKUP_ENTRY *lookup; /* = db_lookup or ix_lookup */
|
|
int pgtab_sz; /* = db_pgtab_sz or ix_pgtab_sz */
|
|
long cmp;
|
|
int cnt;
|
|
int lu_slot, l, u;
|
|
LOOKUP_ENTRY *lu_ptr, *replu_ptr;
|
|
PAGE_ENTRY *pg_ptr;
|
|
int *lru_ptr;
|
|
int pg_slot;
|
|
|
|
|
|
/* check if desired page was last one */
|
|
if ((file == last_dblu.file) && (page == last_dblu.pageno)) {
|
|
if (xlu_ptr != NULL)
|
|
*xlu_ptr = &db_lookup[last_dblu.slot];
|
|
if (xpg_ptr != NULL)
|
|
*xpg_ptr = &dbpg_table[db_lookup[last_dblu.slot].pg_slot];
|
|
return( db_status = S_OKAY );
|
|
}
|
|
lookup = db_lookup;
|
|
pgtab_sz = db_pgtab_sz;
|
|
/* perform binary search of sorted lookup table */
|
|
l = 0;
|
|
u = pgtab_sz - 1;
|
|
while (u >= l) {
|
|
lu_ptr = &lookup[lu_slot = (l + u)/2];
|
|
if ((cmp = file - lu_ptr->file) == 0)
|
|
cmp = page - lu_ptr->pageno;
|
|
if (cmp < 0)
|
|
u = lu_slot - 1;
|
|
else if (cmp > 0)
|
|
l = lu_slot + 1;
|
|
else {
|
|
last_dblu.file = lu_ptr->file;
|
|
last_dblu.pageno = lu_ptr->pageno;
|
|
last_dblu.slot = lu_slot;
|
|
if (xlu_ptr != NULL)
|
|
*xlu_ptr = lu_ptr;
|
|
if (xpg_ptr != NULL)
|
|
*xpg_ptr = &pg_table[lu_ptr->pg_slot];
|
|
return( db_status = S_OKAY );
|
|
}
|
|
}
|
|
if ( ! pg_table ) {
|
|
/* null page table indicates that only a lookup was desired */
|
|
if (cmp > 0)
|
|
++lu_ptr;
|
|
if (xlu_ptr != NULL)
|
|
*xlu_ptr = lu_ptr;
|
|
return( db_status = S_NOTFOUND );
|
|
}
|
|
/* page not found - read into cache */
|
|
/* select a page to replace */
|
|
lru_ptr = &dbpg_lru_slot;
|
|
for (cnt = 2*pgtab_sz, pg_slot = *lru_ptr, pg_ptr = &pg_table[pg_slot];
|
|
--cnt >= 0;
|
|
++pg_slot, ++pg_ptr) {
|
|
if (pg_slot >= pgtab_sz)
|
|
{
|
|
pg_slot = 0;
|
|
pg_ptr = pg_table;
|
|
}
|
|
replu_ptr = &lookup[pg_ptr->lu_slot];
|
|
if (!pg_ptr->recently_used && (pg_ptr->holdcnt == 0)) {
|
|
if (pg_ptr->modified) {
|
|
dio_out(pg_ptr, replu_ptr);
|
|
pg_ptr->modified = FALSE;
|
|
--no_modheld;
|
|
}
|
|
pg_ptr->recently_used = TRUE;
|
|
if ((*lru_ptr = (pg_slot + 1)) >= pgtab_sz)
|
|
*lru_ptr = 0;
|
|
break;
|
|
}
|
|
else if ( pg_ptr->holdcnt == 0 )
|
|
pg_ptr->recently_used = FALSE;
|
|
}
|
|
if (cnt < 0)
|
|
return( dberr(S_FAULT) );
|
|
|
|
/* adjust lookup table */
|
|
if (replu_ptr < lu_ptr) {
|
|
if (cmp < 0)
|
|
{
|
|
--lu_ptr;
|
|
--lu_slot;
|
|
}
|
|
while (replu_ptr < lu_ptr) {
|
|
bytecpy(replu_ptr, replu_ptr + 1, sizeof(*replu_ptr));
|
|
pg_table[replu_ptr->pg_slot].lu_slot = replu_ptr - lookup;
|
|
++replu_ptr;
|
|
}
|
|
}
|
|
else if (replu_ptr > lu_ptr) {
|
|
if (cmp > 0)
|
|
{
|
|
++lu_ptr;
|
|
++lu_slot;
|
|
}
|
|
while (replu_ptr > lu_ptr) {
|
|
bytecpy(replu_ptr, replu_ptr - 1, sizeof(*replu_ptr));
|
|
pg_table[replu_ptr->pg_slot].lu_slot = replu_ptr - lookup;
|
|
--replu_ptr;
|
|
}
|
|
}
|
|
|
|
lu_ptr->file = file;
|
|
lu_ptr->pageno = page;
|
|
lu_ptr->pg_slot = pg_slot;
|
|
pg_ptr->lu_slot = lu_slot;
|
|
if (xlu_ptr != NULL)
|
|
*xlu_ptr = lu_ptr;
|
|
if (xpg_ptr != NULL)
|
|
*xpg_ptr = pg_ptr;
|
|
last_dblu.file = lu_ptr->file;
|
|
last_dblu.pageno = lu_ptr->pageno;
|
|
last_dblu.slot = lu_slot;
|
|
dio_in(pg_ptr, lu_ptr);
|
|
|
|
return( db_status );
|
|
#undef tempbuff
|
|
} /* dio_findpg() */
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_out */
|
|
/* */
|
|
/****************************************/
|
|
/* Writes a page in the cache to file.
|
|
* For byte order neutrality:
|
|
* Each page is raima header data, then a bunch of slots.
|
|
* The first 4 bytes of the page header is the timestamp
|
|
* when the page was written, and it's swapped here.
|
|
* Each slot is raima record header and user record data.
|
|
* The user record data must already have been byte
|
|
* swapped if necessary--to vista its just a large char buf.
|
|
* The rest of the page header and the record header for each
|
|
* slot is byte swapped before the io by calling the
|
|
* page swap function.
|
|
*/
|
|
int
|
|
dio_out(
|
|
PAGE_ENTRY *pg_ptr, /* page table entry to be output */
|
|
LOOKUP_ENTRY *lu_ptr /* corresponding lookup table entry */
|
|
)
|
|
{
|
|
int desc; /* file descriptor */
|
|
int fno; /* file number */
|
|
int pgsize; /* size of page */
|
|
long addr; /* file address */
|
|
time_t host_timestamp;
|
|
ULONG netorder_timestamp;
|
|
|
|
MEM_LOCK(&pg_ptr->Buff);
|
|
|
|
/* Get the current time in "network" format.
|
|
* (Original vista code had it typed as a long.)
|
|
*/
|
|
time (&host_timestamp);
|
|
netorder_timestamp = (ULONG) host_timestamp;
|
|
HTONL (netorder_timestamp);
|
|
|
|
fno = lu_ptr->file;
|
|
pgsize = file_table[fno].ft_pgsize;
|
|
addr = lu_ptr->pageno * (long)pgsize;
|
|
memcpy (pg_ptr->buff, &netorder_timestamp, sizeof(ULONG));
|
|
if ( dio_open(fno) == S_OKAY ) {
|
|
swab_page (pg_ptr->buff, &file_table[fno], HTON);
|
|
desc = file_table[fno].ft_desc;
|
|
DB_LSEEK( desc, (off_t)addr, 0 );
|
|
if (DB_WRITE( desc, pg_ptr->buff, pgsize ) != pgsize) dberr(S_BADWRITE);
|
|
}
|
|
MEM_UNLOCK(&pg_ptr->Buff);
|
|
return( db_status );
|
|
} /* dio_out() */
|
|
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_in */
|
|
/* */
|
|
/****************************************/
|
|
/* Read in a page to the buffer
|
|
*/
|
|
static int dio_in(
|
|
PAGE_ENTRY *pg_ptr, /* page table entry to be input */
|
|
LOOKUP_ENTRY *lu_ptr /* corresponding to pg_ptr */
|
|
)
|
|
{
|
|
int desc; /* file descriptor */
|
|
int fno; /* file number */
|
|
int pgsize; /* page size */
|
|
long addr; /* file address */
|
|
PGZERO *pgzero_ptr;
|
|
FILE_ENTRY *file_ptr;
|
|
int r;
|
|
|
|
file_ptr = &file_table[fno = lu_ptr->file];
|
|
pgsize = file_ptr->ft_pgsize;
|
|
addr = lu_ptr->pageno*pgsize;
|
|
if ( dio_open(fno) == S_OKAY ) {
|
|
desc = file_ptr->ft_desc;
|
|
DB_LSEEK(desc, (off_t)addr, 0);
|
|
MEM_LOCK(&pg_ptr->Buff);
|
|
if ((r = DB_READ( desc, pg_ptr->buff, pgsize )) < pgsize) {
|
|
byteset(&pg_ptr->buff[r], '\0', pgsize - r);
|
|
DB_LSEEK(desc, (off_t)addr, 0);
|
|
if (DB_WRITE( desc, pg_ptr->buff, pgsize ) != pgsize) {
|
|
/* clean up and return out of space */
|
|
DB_LSEEK(desc, (off_t)addr, 0);
|
|
DB_WRITE(desc, "", 0);
|
|
pgzero_ptr = &pgzero[fno];
|
|
pgzero_ptr->pz_next--;
|
|
pgzero_ptr->pz_modified = TRUE;
|
|
dio_pzflush();
|
|
dberr( S_NOSPACE );
|
|
}
|
|
}
|
|
swab_page (pg_ptr->buff, file_ptr, NTOH);
|
|
MEM_UNLOCK(&pg_ptr->Buff);
|
|
}
|
|
return( db_status );
|
|
} /* dio_in() */
|
|
|
|
|
|
/***********************************************************************
|
|
Page zero handling functions for data and key files
|
|
***********************************************************************/
|
|
|
|
|
|
/* Initialize page zero table
|
|
*/
|
|
static int dio_pzinit(void)
|
|
{
|
|
FILE_NO i;
|
|
PGZERO *pgzero_ptr;
|
|
|
|
#ifdef DEBUG_DIO
|
|
if (debugging_dio_init) {
|
|
printf (__FILE__"1430 dio_pzinit: szft=%d oldsz=%d\n",
|
|
(int)size_ft, (int)old_size_ft);
|
|
fflush (stdout);
|
|
}
|
|
#endif
|
|
|
|
/* Macro references must be on one line for some compilers */
|
|
if (ALLOC_TABLE(&db_global.Pgzero, size_ft*sizeof(PGZERO),
|
|
old_size_ft*sizeof(PGZERO), "pgzero") != S_OKAY ) {
|
|
#ifdef DEBUG_DIO
|
|
if (debugging_dio_init) {
|
|
printf (__FILE__"1444 pzinit: alloc_table failed, db_status=%d\n",
|
|
db_status);
|
|
fflush (stdout);
|
|
}
|
|
#endif
|
|
return( db_status );
|
|
}
|
|
|
|
/* read in page zeros */
|
|
for (i = old_size_ft, pgzero_ptr = pgzero;
|
|
i < size_ft;
|
|
++i, ++pgzero_ptr) {
|
|
pgzero_ptr->pz_dchain = 0L;
|
|
pgzero_ptr->pz_next = 0L;
|
|
pgzero_ptr->pz_timestamp = 0;
|
|
pgzero_ptr->pz_modified = FALSE;
|
|
}
|
|
return( db_status = S_OKAY );
|
|
} /* dio_pzinit() */
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_pzflush */
|
|
/* */
|
|
/****************************************/
|
|
/* Flush page zero table
|
|
* Complement to dio_out which writes all pages except page zero.
|
|
*/
|
|
static int dio_pzflush(void)
|
|
{
|
|
FILE_NO i;
|
|
int desc;
|
|
PGZERO *pgzero_ptr;
|
|
FILE_ENTRY *file_ptr;
|
|
LONG align_LONG;
|
|
char *cptr;
|
|
int j;
|
|
|
|
/* flush modified page zeroes to database files */
|
|
for (i = 0, pgzero_ptr = pgzero, file_ptr = file_table; i < size_ft;
|
|
++i, ++pgzero_ptr, ++file_ptr) {
|
|
if ( pgzero_ptr->pz_modified ) {
|
|
if ( dio_open(i) != S_OKAY )
|
|
return( db_status );
|
|
|
|
/* The only byte swap operations necessary
|
|
* on a page zero are the first 5 LONG integers.
|
|
*/
|
|
for (j = 0, cptr = (char *) pgzero_ptr;
|
|
j < PGZEROSZ/sizeof(LONG);
|
|
++j, cptr += sizeof(LONG)) {
|
|
memcpy (&align_LONG, cptr, sizeof(LONG));
|
|
HTONL (align_LONG);
|
|
memcpy (cptr, &align_LONG, sizeof(LONG));
|
|
}
|
|
desc = file_ptr->ft_desc;
|
|
DB_LSEEK(desc, (off_t)0L, 0);
|
|
if (DB_WRITE(desc, (char *)pgzero_ptr, PGZEROSZ) != PGZEROSZ)
|
|
return( dberr(S_BADWRITE) );
|
|
pgzero_ptr->pz_modified = FALSE;
|
|
}
|
|
#ifdef CLOSE_FILES
|
|
dio_close(i);
|
|
#endif
|
|
}
|
|
return( db_status = S_OKAY );
|
|
} /* dio_pzflush() */
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_pzread */
|
|
/* */
|
|
/****************************************/
|
|
/* Read a file's page zero
|
|
*/
|
|
int
|
|
dio_pzread(
|
|
FILE_NO fno /* file number */
|
|
)
|
|
{
|
|
FILE_ENTRY *file_ptr;
|
|
PGZERO *pgzero_ptr;
|
|
|
|
pgzero_ptr = &pgzero[fno];
|
|
file_ptr = &file_table[fno];
|
|
|
|
/* open this file, if not already open */
|
|
dio_open(fno);
|
|
if (file_ptr->ft_desc < 0) {
|
|
pgzero_ptr->pz_dchain = 0;
|
|
pgzero_ptr->pz_next = 0;
|
|
pgzero_ptr->pz_timestamp = 0;
|
|
pgzero_ptr->pz_modified = FALSE;
|
|
return( db_status ); /* db_status set by dio_open */
|
|
}
|
|
|
|
/* seek to and read page zero */
|
|
DB_LSEEK(file_ptr->ft_desc, (off_t)0L, 0);
|
|
if ( DB_READ(file_ptr->ft_desc, (char *)pgzero_ptr, PGZEROSZ)
|
|
!= PGZEROSZ ) {
|
|
return( dberr(S_BADREAD) );
|
|
}
|
|
NTOHL (pgzero_ptr->pz_dchain);
|
|
NTOHL (pgzero_ptr->pz_next);
|
|
NTOHL (pgzero_ptr->pz_timestamp);
|
|
return( db_status = S_OKAY );
|
|
} /* dio_pzread() */
|
|
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_pzalloc */
|
|
/* */
|
|
/****************************************/
|
|
/* Allocate new record slot or key node from page zero,
|
|
* ie from delete chain if possible.
|
|
* Returns memory address of the free slot into 'loc'.
|
|
*/
|
|
int
|
|
dio_pzalloc(
|
|
FILE_NO fno, /* file number */
|
|
F_ADDR *loc /* pointer to allocated location */
|
|
)
|
|
{
|
|
DB_ADDR dba;
|
|
F_ADDR pg;
|
|
char *ptr;
|
|
PGZERO *pgzero_ptr;
|
|
|
|
|
|
pgzero_ptr = &pgzero[fno];
|
|
if ( pgzero_ptr->pz_next == 0L )
|
|
if ( dio_pzread(fno) != S_OKAY )
|
|
RETURN( db_status );
|
|
if ( file_table[fno].ft_type == KEY ) {
|
|
if ( working_file != fno )
|
|
return( dberr(S_NOWORK) );
|
|
if ( pgzero_ptr->pz_dchain == NONE || ! (dboptions & DCHAINUSE) ) {
|
|
if ( pgzero_ptr->pz_next == MAXRECORDS-1 )
|
|
return( dberr(S_RECLIMIT) );
|
|
pg = pgzero_ptr->pz_next++;
|
|
}
|
|
else {
|
|
pg = pgzero_ptr->pz_dchain;
|
|
if ( dio_get( pg, (char * *)&ptr, NOPGHOLD ) != S_OKAY )
|
|
return( db_status );
|
|
/* Get the first key node on the delete chain.
|
|
* (sizeof external timestamp set to 4 bytes)
|
|
****** bytecpy(&pgzero_ptr->pz_dchain,
|
|
****** ptr+sizeof(long)+sizeof(INT), sizeof(F_ADDR)); *********
|
|
*/
|
|
bytecpy (&pgzero_ptr->pz_dchain,
|
|
ptr + sizeof(LONG) + sizeof(INT), sizeof(F_ADDR));
|
|
}
|
|
}
|
|
else {
|
|
if ( ! pgzero_ptr->pz_dchain || ! (dboptions & DCHAINUSE) ) {
|
|
if ( pgzero_ptr->pz_next == MAXRECORDS )
|
|
return( dberr(S_RECLIMIT) );
|
|
pg = pgzero_ptr->pz_next++;
|
|
}
|
|
else {
|
|
pg = pgzero_ptr->pz_dchain;
|
|
dba = ((NUM2EXT(fno, ft_offset) & FILEMASK) << FILESHIFT) | pg;
|
|
if ( dio_read(dba, (char * *)&ptr, NOPGHOLD) != S_OKAY )
|
|
return( db_status );
|
|
bytecpy(&pgzero_ptr->pz_dchain, ptr+sizeof(INT), sizeof(F_ADDR));
|
|
}
|
|
}
|
|
*loc = pg;
|
|
pgzero_ptr->pz_modified = TRUE;
|
|
return( db_status = S_OKAY );
|
|
} /* dio_pzalloc() */
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_pzdel */
|
|
/* */
|
|
/****************************************/
|
|
/* Delete record slot or key node from page zero
|
|
*/
|
|
int
|
|
dio_pzdel(
|
|
FILE_NO fno, /* file number */
|
|
F_ADDR loc /* location to be freed */
|
|
)
|
|
{
|
|
DB_ADDR dba;
|
|
INT recnum;
|
|
char *ptr;
|
|
PGZERO *pgzero_ptr;
|
|
|
|
|
|
pgzero_ptr = &pgzero[fno];
|
|
if ( pgzero_ptr->pz_next == 0L )
|
|
if ( dio_pzread(fno) != S_OKAY )
|
|
RETURN( db_status );
|
|
if ( file_table[fno].ft_type == KEY ) {
|
|
if ( working_file != fno )
|
|
return( dberr(S_NOWORK) );
|
|
if ( dio_get( loc, (char * *)&ptr, PGHOLD ) != S_OKAY )
|
|
return( db_status );
|
|
/*********************************************
|
|
* Delete chain ptr in key node page is in location
|
|
* of orphan ptr, bytes 6 - 9, not bytes 4 - 7
|
|
* as printed in raima User Guide.
|
|
* (sizeof external timestamp set to 4 bytes).
|
|
****** bytecpy(ptr+sizeof(long)+sizeof(INT),
|
|
****** &pgzero_ptr->pz_dchain, sizeof(F_ADDR)); *********
|
|
*****************************************/
|
|
bytecpy (ptr + sizeof(LONG) + sizeof(INT),
|
|
&pgzero_ptr->pz_dchain, sizeof(F_ADDR));
|
|
pgzero_ptr->pz_dchain = loc;
|
|
dio_touch( loc );
|
|
}
|
|
else {
|
|
dba = ((NUM2EXT(fno, ft_offset) & FILEMASK) << FILESHIFT) | loc;
|
|
if ( dio_read( dba, (char * *)&ptr , NOPGHOLD) != S_OKAY )
|
|
return( db_status );
|
|
bytecpy(&recnum, ptr, sizeof(INT));
|
|
recnum = ~recnum; /* indicates deleted record */
|
|
bytecpy(ptr, &recnum, sizeof(INT));
|
|
bytecpy(ptr+sizeof(INT), &pgzero_ptr->pz_dchain, sizeof(F_ADDR));
|
|
pgzero_ptr->pz_dchain = loc;
|
|
if ( dio_write(dba, NULL, NOPGFREE) != S_OKAY )
|
|
return( db_status );
|
|
}
|
|
pgzero_ptr->pz_modified = TRUE;
|
|
return( db_status = S_OKAY );
|
|
} /* dio_pzdel() */
|
|
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_pznext */
|
|
/* */
|
|
/****************************************/
|
|
/* Return pz_next for file fno
|
|
*/
|
|
F_ADDR dio_pznext(FILE_NO fno)
|
|
{
|
|
if ( pgzero[fno].pz_next == 0L )
|
|
dio_pzread(fno);
|
|
return ( pgzero[fno].pz_next );
|
|
}
|
|
|
|
/****************************************/
|
|
/* */
|
|
/* dio_pzclr */
|
|
/* */
|
|
/****************************************/
|
|
/* Clear page zero cache
|
|
*/
|
|
void dio_pzclr(void)
|
|
{
|
|
FILE_NO i;
|
|
PGZERO *pgzero_ptr;
|
|
|
|
for (i = 0, pgzero_ptr = pgzero; i < size_ft; i++, pgzero_ptr++) {
|
|
if (pgzero_ptr->pz_modified) {
|
|
pgzero_ptr->pz_next = 0L;
|
|
pgzero_ptr->pz_modified = FALSE;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
/* vpp -nOS2 -dUNIX -nBSD -nVANILLA_BSD -nVMS -nMEMLOCK -nWINDOWS -nFAR_ALLOC -f/usr/users/master/config/nonwin dio.c */
|