📄 dio.c
字号:
/* ====================================================================== Return a pointer to the buffer of a requested page*/int EXTERNAL_FCN dio_getpg( FILE_NO file, /* file table index */ F_ADDR page, /* page in file */ short pg_tag, PAGE_ENTRY **last_lu, /* the last looked-up page */ PAGE_ENTRY **xpg_ptr, DB_TASK *task){ PAGE_TABLE *pgtab = (file == task->ov_file) ? &task->cache->ix_pgtab : &task->cache->db_pgtab; PAGE_TAG *tag_ptr; PAGE_ENTRY *pg_ptr; short pgsize; int retcode; F_ADDR ovfl_addr; retcode = task->db_status; tag_ptr = &task->cache->tag_table[pg_tag]; if (tag_ptr->lookups > LONG_MAX) { /* prevent roll-over while keeping proportions */ tag_ptr->lookups >>= 1; tag_ptr->hits >>= 1; } tag_ptr->lookups++; STAT_lookups(file, task);#ifdef DB_DEBUG if (task->db_debug & LOCK_CHECK) { /* make sure that a locked file has not been modified by someone else */ if (file != task->ov_file && !(task->file_table[file].ft_flags & STATIC) && task->dbopen == 1 && (task->app_locks[file] || task->excl_locks[file])) { if (task->pgzero[file].pz_next) { if (dio_open(file, task) != S_OKAY) return (task->db_status); if (task->pgzero[file].file_mtime != psp_fileModTime(task->file_table[file].ft_desc)) retcode = dberr(SYS_FILEMODIFIED); if (retcode) return (task->db_status = retcode); } } }#endif /* DB_DEBUG */ /* look in the cache */ if (dio_findpg(file, page, last_lu, xpg_ptr, task) == S_OKAY) { /* found the page in the cache */#ifdef DB_DEBUG if (task->db_debug & LOCK_CHECK) { /* make sure that a locked page gotten from the cache has not been modified by someone else in the meantime */ if (file != task->ov_file && !(task->file_table[file].ft_flags & STATIC) && task->dbopen == 1 && (task->app_locks[file] || task->excl_locks[file])) { const SG *sg; long ptime = 0L; off_t addr = task->file_table[file].ft_pgsize * (off_t)page; if ((sg = task->sgs[file]) != NULL) { off_t begin; off_t off; size_t size; block_parms(addr, sizeof(long), &begin, &size, &off, sg); dio_readfile(file, begin, task->enc_buff, size, 0, NULL, task); (*sg->dec)(sg->data, task->enc_buff, size); memcpy(&ptime, (char *) task->enc_buff + off, sizeof(long)); } else dio_readfile(file, addr, &ptime, 4, 0, NULL, task); if (memcmp((*xpg_ptr)->buff, (char *)&ptime, 4) != 0) return (dberr(SYS_FILEMODIFIED)); } }#endif /* DB_DEBUG */ tag_ptr->hits++; STAT_hits(file, task); return (task->db_status); } if (task->db_status == S_NOTFOUND) task->db_status = S_OKAY; /* page not found -- start of process to read into cache */ /* #1 -- search the page table for a page not recently used */ if (dio_findlru(file, page, pg_tag, &pg_ptr, task) != S_OKAY) return (task->db_status);#ifdef DB_DEBUG if (pg_ptr < pgtab->pg_table || pg_ptr >= pgtab->pg_table + pgtab->pgtab_sz) return (dberr(SYS_INVPAGE));#endif /* #2 -- write page if dirty */ if (pg_ptr->modified) { FILE_ENTRY *file_ptr = &task->file_table[pg_ptr->file]; if (pg_ptr->file == task->ov_file || file_ptr->ft_flags & TEMPORARY || (!task->trans_id[0] && (task->dbopen >= 2 || task->excl_locks[pg_ptr->file])) || !(task->dboptions & TRLOGGING)) { /* ix page swapping occurs here; also data/key pages when (in one-user/exclusive mode or has exclusive locks) and (without transactions). */ retcode = dio_out(pg_ptr, task); if (pg_ptr->file != task->ov_file) { /* this will cause the file to be committed at d_close */ file_ptr->ft_flags |= NEEDS_COMMIT; } } else { retcode = o_write(pg_ptr, task); if (retcode == S_OKAY) task->cache_ovfl = TRUE; } if (retcode == S_OKAY) pg_ptr->modified = FALSE; } /* #3 -- remove the found page from the hash_table old bucket */ if (retcode == S_OKAY && pg_ptr->file != -1) retcode = dio_clrpage(pg_ptr, task); if (retcode != S_OKAY) goto ret_dbstatus; /* old page has now been swapped out, bring in new page */ /* #4 -- resize the page buffer if necessary */ pgsize = task->file_table[file].ft_pgsize; if (!task->cache->prealloc) { if ((pgsize != pg_ptr->buff_size) || (pg_ptr->buff == NULL)) { /* The realloc for a smaller page allows for the cache to shrink when the db needing the larger pages is d_iclose()-ed. If this is not done, the d_iopen() would make the cache grow without the possibility of it ever shrinking. */ char *tempbuff = psp_cGetMemory(pgsize, 0); if (! tempbuff) return (dberr(S_NOMEMORY)); if (pg_ptr->buff) psp_freeMemory(pg_ptr->buff, 0); pg_ptr->buff = tempbuff;#ifdef DBSTAT STAT_mem_alloc(pgtab, pgsize - pg_ptr->buff_size);#endif } } pg_ptr->buff_size = pgsize; /* #5 -- check to see if page is in overflow file */ ovfl_addr = 0L; if (file == task->ov_file) { ovfl_addr = page; } else if (task->cache_ovfl) { retcode = o_search(file, page, &ovfl_addr, task); if (retcode != S_OKAY) goto ret_dbstatus; /* o_search failed, exit function */ } /* #6 -- this is now the one we are looking for, setup for dio_in() */ pg_ptr->file = file; pg_ptr->pageno = page; pg_ptr->ovfl_addr = ovfl_addr; /* #7 -- read the page from disk */ if ((retcode = dio_in(pg_ptr, task)) == S_OKAY) { /* #8 -- add pg_ptr into hash_table in new bucket, front of the chain */ dio_rehash(pg_ptr, task); pg_ptr->tag = pg_tag; if (file != task->ov_file) { pg_ptr->n_pg = task->pgzero[file].pg_ptr; task->pgzero[file].pg_ptr = pg_ptr; if (pg_ptr->n_pg) pg_ptr->n_pg->p_pg = pg_ptr; } ++task->cache->tag_table[pg_tag].num_pages; STAT_pages(file, 1, task); if (last_lu) *last_lu = pg_ptr; if (xpg_ptr) *xpg_ptr = pg_ptr; }#ifdef DB_DEBUG if (task->db_debug & CACHE_CHECK) { if (check_cache(DB_TEXT("after dio_getpg"), task) != S_OKAY) retcode = task->db_status; }#endifret_dbstatus: return (task->db_status = retcode);}/* ======================================================================*/int INTERNAL_FCN dio_out( PAGE_ENTRY *pg_ptr, /* page table entry to be output */ DB_TASK *task){ FILE_NO fno; /* file number */ short pgsize; /* size of page */ off_t addr; /* file address */ long curr_time; void *buff; const SG *sg;#ifdef DB_DEBUG DB_ADDR page_id;#endif if (task->dboptions & READONLY) return (dberr(S_READONLY)); if (pg_ptr->buff == NULL) return (dberr(S_INVPTR)); fno = pg_ptr->file; pgsize = task->file_table[fno].ft_pgsize;#ifdef DB_DEBUG if (pg_ptr->buff_size != pgsize) return (dberr(SYS_INVPGSIZE));#endif if (pg_ptr->ovfl_addr == 0L) { /* write to database file */ if (pg_ptr->pageno == 0) return (dberr(SYS_PZACCESS));#ifdef DB_DEBUG if (task->db_debug & PAGE_CHECK) { ENCODE_DBA(min(fno, 255), pg_ptr->pageno, &page_id); if (memcmp(pg_ptr->buff, &page_id, sizeof(DB_ADDR)) != 0) return (dberr(SYS_BADPAGE)); } else if (task->db_debug & LOCK_CHECK) { /* make sure that a locked page has not been modified by someone else in the meantime */ if (fno != task->ov_file && !(task->file_table[fno].ft_flags & STATIC) && task->dbopen == 1 && (task->app_locks[fno] || task->excl_locks[fno])) { long ptime = 0L; addr = pgsize * (off_t)pg_ptr->pageno; if ((sg = task->sgs[fno]) != NULL) { off_t begin; off_t off; size_t size; block_parms(addr, sizeof(long), &begin, &size, &off, sg); dio_readfile(fno, begin, task->enc_buff, size, 0, NULL, task); (*sg->dec)(sg->data, task->enc_buff, size); memcpy(&ptime, (char *) task->enc_buff, sizeof(long)); } else { dio_readfile(fno, addr, &ptime, sizeof(long), 0, NULL, task); } if (memcmp(pg_ptr->buff, &ptime, 4) != 0) return (dberr(SYS_FILEMODIFIED)); } }#endif /* DB_DEBUG */ curr_time = psp_timeSecs(); /* get the current time */ memcpy(pg_ptr->buff, &curr_time, sizeof(time_t)); addr = pgsize * (off_t)pg_ptr->pageno; } else { /* write to overflow file */ fno = task->ov_file; addr = pg_ptr->ovfl_addr; } if ((sg = task->sgs[pg_ptr->file]) != NULL) { buff = task->enc_buff; memcpy(buff, pg_ptr->buff, pgsize); (*sg->enc)(sg->data, buff, pgsize); } else buff = pg_ptr->buff; dio_writefile(fno, addr, buff, pgsize, 0, task);#ifdef DB_DEBUG if (task->db_debug & PAGE_CHECK) { if (fno != task->ov_file) { /* put page id back in header */ memcpy(pg_ptr->buff, &page_id, sizeof(DB_ADDR)); } }#endif if (task->db_status == S_OKAY) { if (fno != task->ov_file) STAT_pg_write(fno, pgsize, task); else STAT_log_write(pgsize, task); } return (task->db_status);}/* ====================================================================== Read in a page to the buffer*/int INTERNAL_FCN dio_in( PAGE_ENTRY *pg_ptr, DB_TASK *task){ FILE_NO fno; /* file number */ short pgsize; /* page size */ off_t addr; /* file address */ int extended; DB_ULONG extend = EXTENDFILES; const SG *sg; if (pg_ptr->buff == NULL) return (dberr(S_INVPTR)); fno = pg_ptr->file; pgsize = task->file_table[fno].ft_pgsize; if (pg_ptr->buff_size != pgsize) return (dberr(SYS_INVPGSIZE)); if (pg_ptr->ovfl_addr == 0L) { /* read from database file */ if (pg_ptr->pageno == 0) return (dberr(SYS_PZACCESS)); addr = pgsize * (off_t)pg_ptr->pageno; /* suppress file extend logic if called from dbCheck */ if (task->dboptions & NORECOVER) extend = 0;#ifdef DB_DEBUG else { /* suppress file extend logic if not at end of file */ if (pg_ptr->pageno < dio_pages(fno, task)) extend = 0; }#endif } else { /* read from overflow file */ fno = task->ov_file; addr = pg_ptr->ovfl_addr; } if ((sg = task->sgs[fno]) != NULL) { dio_readfile(fno, addr, task->enc_buff, pgsize, extend, &extended, task); (*sg->dec)(sg->data, task->enc_buff, pgsize); memcpy(pg_ptr->buff, task->enc_buff, pgsize); } else { dio_readfile(fno, addr, pg_ptr->buff, pgsize, extend, &extended, task); }#ifdef DB_DEBUG if (extended && !extend && !(task->dboptions & NORECOVER)) { /* report the error if not dbCheck */ return (dberr(SYS_INVEXTEND)); } if (task->db_status == S_OKAY && (task->db_debug & PAGE_CHECK)) { if (fno != task->ov_file) { DB_ADDR page_id; ENCODE_DBA(min(fno, 255), pg_ptr->pageno, &page_id); memcpy(pg_ptr->buff, &page_id, sizeof(DB_ADDR)); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -