📄 dio.c
字号:
#endif if (task->db_status == S_OKAY) { if (fno != task->ov_file) { if (extended) { STAT_pg_write(fno, pgsize, task); STAT_new_page(fno, task); } else STAT_pg_read(fno, pgsize, task); } else STAT_log_read(pgsize, task); } return (task->db_status);}/*---------------------------------------------------------------------//----------------------------------------------------------------------/ Page zero handling functions for data and key files/----------------------------------------------------------------------//---------------------------------------------------------------------*//* ====================================================================== Initialize page zero table*/int EXTERNAL_FCN dio_pzinit(DB_TASK *task){ register FILE_NO i; PGZERO *pgzero_ptr; size_t size; size_t old; size = task->size_ft * sizeof(PGZERO); old = task->old_size_ft * sizeof(PGZERO); if (alloc_table((void **) &task->pgzero, size, old, task) != S_OKAY) return (task->db_status); /* read in page zeros */ for (i = task->old_size_ft, pgzero_ptr = &task->pgzero[task->old_size_ft]; i < task->size_ft; ++i, ++pgzero_ptr) memset(pgzero_ptr, '\0', sizeof(PGZERO)); return (task->db_status);}/* ====================================================================== Free the memory allocated for page zeros*/static void INTERNAL_FCN dio_pzfree(int dbn, DB_TASK *task){ int low, high, total; if (dbn == ALL_DBS) { low = 0; high = task->size_ft; total = task->size_ft; } else { low = task->db_table[dbn].ft_offset; high = low + task->db_table[dbn].Size_ft; total = task->size_ft; } if (task->pgzero) { free_table((void **) &task->pgzero, low, high, total, sizeof(PGZERO), task); }}/* ====================================================================== Increment and return file timestamp*/DB_ULONG INTERNAL_FCN dio_pzsetts(FILE_NO fno, DB_TASK *task){ DB_ULONG ts; PGZERO *pgzero_ptr; if (task->db_tsrecs || task->db_tssets) { if ((task->pgzero[fno].pz_next == (F_ADDR) 0 && dio_pzread(fno, task) != S_OKAY)#ifdef DB_DEBUG || dio_pzcheck(fno, task) != S_OKAY#endif ) return 0L; pgzero_ptr = &task->pgzero[fno]; if (++pgzero_ptr->pz_timestamp == 0L) pgzero_ptr->pz_timestamp = 1L; pgzero_ptr->pz_modified = TRUE; task->file_table[fno].ft_flags |= TS_IS_CURRENT; ts = pgzero_ptr->pz_timestamp; } else { ts = 0L; } return (ts);}/* ====================================================================== Return file timestamp*/DB_ULONG INTERNAL_FCN dio_pzgetts(FILE_NO fno, DB_TASK *task){ PGZERO *pgzero_ptr; pgzero_ptr = &task->pgzero[fno]; if ((task->pgzero[fno].pz_next == (F_ADDR) 0 && dio_pzread(fno, task) != S_OKAY)#ifdef DB_DEBUG || dio_pzcheck(fno, task) != S_OKAY#endif ) return 0L; if (task->trans_id[0]) o_fileinit(fno, task); if (! (task->file_table[fno].ft_flags & TS_IS_CURRENT)) dio_pzsetts(fno, task); return (pgzero_ptr->pz_timestamp);}/* ====================================================================== Flush page zero table*/static int INTERNAL_FCN dio_pzflush(DB_TASK *task){ register FILE_NO i; register PGZERO *pgzero_ptr; register FILE_ENTRY *file_ptr; void *buff; const SG *sg; if ((task->dboptions & TRLOGGING) && task->trans_id[0] && (! task->trcommit)) { /* flush to overflow/log file -- before tx commit */ for (i = 0, pgzero_ptr = task->pgzero, file_ptr = task->file_table; i < task->size_ft; ++i, ++pgzero_ptr, ++file_ptr) { if (pgzero_ptr->pz_modified && !(file_ptr->ft_flags & TEMPORARY)) {#ifdef DB_DEBUG if (dio_pzcheck(i, task) != S_OKAY) return (task->db_status);#endif if (o_pzwrite(i, task) != S_OKAY) return (task->db_status); } } } else { /* flush modified page zeroes to database files */ for (i = 0, pgzero_ptr = task->pgzero, file_ptr = task->file_table; i < task->size_ft; ++i, ++pgzero_ptr, ++file_ptr) { if (pgzero_ptr->pz_modified && !(file_ptr->ft_flags & TEMPORARY)) {#ifdef DB_DEBUG if (dio_pzcheck(i, task) != S_OKAY) return (task->db_status);#endif if ((sg = task->sgs[i]) != NULL) { buff = task->enc_buff; memcpy(buff, pgzero_ptr, PGZEROSZ); (*sg->enc)(sg->data, buff, PGZEROSZ); } else buff = pgzero_ptr; if (dio_writefile(i, 0L, buff, PGZEROSZ, 0, task) != S_OKAY) return (task->db_status); STAT_pz_write(i, PGZEROSZ, task); pgzero_ptr->pz_modified = FALSE; if (task->trlog_flag) dtrlog(i, 0L, (char *) pgzero_ptr, PGZEROSZ, task); /* Since the file is getting committed immediately, there is no need to set the NEEDS_COMMIT flag. */ commit_file(task->file_table[i].ft_desc, task); task->file_table[i].ft_flags &= ~(NEEDS_COMMIT | TS_IS_CURRENT); } } } return (task->db_status);}/* ====================================================================== Read a file's page zero*/int EXTERNAL_FCN dio_pzread(FILE_NO fno, DB_TASK *task){ PGZERO *pgzero_ptr = &task->pgzero[fno]; const SG *sg; PSP_FH desc; if (dio_open(fno, task) != S_OKAY) return task->db_status; desc = task->file_table[fno].ft_desc; if (psp_fileSeekRead(desc, 0, pgzero_ptr, PGZEROSZ) < (int) PGZEROSZ) { dberr(S_BADREAD); pgzero_ptr->pz_dchain = (F_ADDR) 0; pgzero_ptr->pz_next = (F_ADDR) 0; pgzero_ptr->pz_timestamp = 0L; pgzero_ptr->pz_modified = FALSE; task->file_table[fno].ft_flags &= (~TS_IS_CURRENT); goto exit; } if ((sg = task->sgs[fno]) != NULL) (*sg->dec)(sg->data, pgzero_ptr, PGZEROSZ); STAT_pz_read(fno, PGZEROSZ, task);#ifdef DB_DEBUG if (task->db_debug & PZVERIFY) { pgzero_ptr->file_size = psp_fileLength(task->file_table[fno].ft_desc); if (pgzero_ptr->file_size != -1L) { long pz_file_size; FILE_ENTRY *file_ptr = &task->file_table[fno]; /* round the size down to the nearest page boundary */ pgzero_ptr->file_size -= (pgzero_ptr->file_size % file_ptr->ft_pgsize); /* calculate the size that we'd expect from pz_next */ pz_file_size = pgzero_ptr->pz_next - 1; /* number of slots */ pz_file_size += file_ptr->ft_slots - 1; /* round up to next page */ pz_file_size /= file_ptr->ft_slots; /* number of pages */ pz_file_size++; /* add 1 for page 0 */ pz_file_size *= file_ptr->ft_pgsize; /* number of bytes */ /* The actual file size may be larger than we would expect from pz_next, as there may be some newly created records that were written to the end of the file before a transaction was aborted. The actual size should not be less than the value calculated from pz_next, but it seems that psp_fileLength sometimes returns a value that is not current, so allow some error. */ if (pz_file_size > pgzero_ptr->file_size) { if ((pz_file_size - pgzero_ptr->file_size) > (32 * file_ptr->ft_pgsize)) { /* more than 32 pages - pznext probably corrupted */ return (dberr(SYS_PZNEXT)); } /* assume value returned by psp_fileLength is wrong */ pgzero_ptr->file_size = pz_file_size; } } }#endifexit:#ifdef DB_DEBUG if (task->db_debug & LOCK_CHECK) pgzero_ptr->file_mtime = psp_fileModTime(desc);#endif return (task->db_status);}/* ====================================================================== Allocate new record slot or key node from page zero*/int EXTERNAL_FCN dio_pzalloc( FILE_NO fno, /* file number */ F_ADDR *loc, /* pointer to allocated location */ DB_TASK *task){ DB_ADDR dba; DB_ULONG pg; char *ptr; PGZERO *pgzero_ptr; /* check shared access privileges */ if ((task->dbopen == 1) && !task->trans_id[0] && !task->excl_locks[fno]) return (dberr(S_NOTRANS)); pgzero_ptr = &task->pgzero[fno]; if ((pgzero_ptr->pz_next == (F_ADDR) 0 && dio_pzread(fno, task) != S_OKAY)#ifdef DB_DEBUG || dio_pzcheck(fno, task) != S_OKAY#endif ) return (task->db_status); if (task->trans_id[0] && o_fileinit(fno, task) != S_OKAY) return (task->db_status); if (task->file_table[fno].ft_type == KEY) { if ((pgzero_ptr->pz_dchain == DCH_NONE) || (! (task->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(fno, pg, &ptr, NOPGHOLD, task) != S_OKAY) return (task->db_status); memcpy(&pgzero_ptr->pz_dchain, ptr + sizeof(long) + sizeof(short), sizeof(F_ADDR)); if (dio_unget(fno, pg, NOPGFREE, task) != S_OKAY) return (task->db_status); } } else { if ((! pgzero_ptr->pz_dchain) || (! (task->dboptions & DCHAINUSE))) { if (pgzero_ptr->pz_next >= MAXRECORDS) return (dberr(S_RECLIMIT)); pg = pgzero_ptr->pz_next++; } else { pg = pgzero_ptr->pz_dchain; ENCODE_DBA(NUM2EXT(fno, ft_offset), pg, &dba); if (dio_read(dba, (char **) &ptr, NOPGHOLD, task) != S_OKAY) return (task->db_status); memcpy(&pgzero_ptr->pz_dchain, ptr + sizeof(short), sizeof(F_ADDR)); if (dio_release(dba, NOPGFREE, task) != S_OKAY) return (task->db_status); } } *loc = pg; pgzero_ptr->pz_modified = TRUE; return (task->db_status);}/* ====================================================================== Delete record slot or key node from page zero*/int EXTERNAL_FCN dio_pzdel( FILE_NO fno, /* file number */ F_ADDR loc, /* location to be freed */ DB_TASK *task){ DB_ADDR dba; short recnum; char *ptr; PGZERO *pgzero_ptr; /* check shared access privileges */ if ((task->dbopen == 1) && !task->trans_id[0] && !task->excl_locks[fno]) return (dberr(S_NOTRANS)); pgzero_ptr = &task->pgzero[fno]; if ((pgzero_ptr->pz_next == (F_ADDR) 0 && dio_pzread(fno, task) != S_OKAY)#ifdef DB_DEBUG || dio_pzcheck(fno, task) != S_OKAY#endif ) return (task->db_status); if (task->file_table[fno].ft_type == KEY) { if (dio_get(fno, loc, &ptr, PGHOLD, task) != S_OKAY) return (task->db_status); memcpy(ptr + sizeof(long) + sizeof(short), &pgzero_ptr->pz_dchain, sizeof(F_ADDR)); pgzero_ptr->pz_dchain = loc; if (dio_touch(fno, loc, PGFREE, task) != S_OKAY) return (task->db_status); } else { ENCODE_DBA(NUM2EXT(fno, ft_offset), loc, &dba); if (dio_read(dba, &ptr, PGHOLD, task) != S_OKAY) return (task->db_status); memcpy(&recnum, ptr, sizeof(short)); recnum &= ~RLBMASK; /* in case the RLB is set [624] */ recnum = (short) ~recnum; /* indicates deleted record */ memcpy(ptr, &recnum, sizeof(short)); memcpy(ptr + sizeof(short), &pgzero_ptr->pz_dchain, sizeof(F_ADDR)); pgzero_ptr->pz_dchain = loc; if (dio_write(dba, PGFREE, task) != S_OKAY) return (task->db_status); } pgzero_ptr->pz_modified = TRUE; return (task->db_status);}/* =====
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -