📄 dblfcns.c
字号:
/*************************************************************************** * * * db.* * * open source database kernel * * * * Copyright (c) 2000 Centura Software Corporation. All rights reserved. * * * * Use of this software, whether in source code format, or in executable, * * binary object code form, is governed by the CENTURA OPEN SOURCE LICENSE * * which is fully described in the LICENSE.TXT file, included within this * * distribution of source code files. * * * * Except as provided herein, the contents of this file are subject to the * * Centura Open Source Public License Version 1.0 (the "License"); you may * * not use this file except in compliance with the License. A copy of the * * License will be provided to you by Club ITTIA. * * * * Software distributed under the License is distributed on an "AS IS" * * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * * License for the specific language governing rights and limitations * * under the License. * * * * The Original Code is db.linux version 1.0, released February 29, 2000. * * * * The Initial Developer of the Original Code is Centura Software * * Corporation. Portions created by Centura Software Corporation are * * Copyright (C) 1984-2000 Centura Software Corporation. All Rights * * Reserved. * * * * This file contains modifications to the Original Code made by ITTIA. * * This file may only be used in accordance with the ITTIA DB.* V.2 * * License Agreement which is available at WWW.ITTIA.COM. * * * **************************************************************************/#include "db.star.h"#include "rntmint.h"/* Internal function prototypes */static int INTERNAL_FCN bld_lock_tables(DB_TASK *);static int INTERNAL_FCN initses(int, DB_TASK *);static int INTERNAL_FCN termses(int, DB_TASK *);static int INTERNAL_FCN cmpfiles(DB_TCHAR *, DB_TCHAR *);static int alloc_lfpkts (DB_TASK *);/* Constants used by d_open and d_iopen */#define FIRST_OPEN 0#define INCR_OPEN 1/* ====================================================================== Set the lock request timeout value*/int INTERNAL_FCN dtimeout(int secs, DB_TASK *task){ int stat; LM_SETTIME *sto; /* send timeout packet */ if (!task->dbopen) return (dberr(S_DBOPEN)); if (task->dbopen == 1) { if ((sto = psp_lmcAlloc(sizeof(LM_SETTIME))) == NULL) return (dberr(S_NOMEMORY)); sto->queue_timeout = (short) secs; sto->lock_timeout = (short)-1; stat = msg_trans(L_SETTIME, sto, sizeof(LM_SETTIME), NULL, 0, task); if (stat == S_OKAY) task->db_timeout = secs; psp_lmcFree(sto); } return (task->db_status);}/* ====================================================================== Perform the actual database open(s) The global variables task->type, task->db_lockmgr, and task->dbopen are set according to the openmode: openmode task->type task->db_lockmgr task->dbopen -------- ---------- ---------------- ------------ "x" "x" 1 2 "s" "s" 1 1 "o" "x" 0 2*/int INTERNAL_FCN dopen(const DB_TCHAR *dbnames, const DB_TCHAR *openmode, int opentype, const SG *sg, const DB_SCHEMA*sc, DB_TASK *task){ short ii; DB_TCHAR omode; int dbopen_sv = task->dbopen; int hold_db_status; size_t Lp_size = task->lp_size; size_t Fp_size = task->fp_size; short Page_size = task->page_size; short Size_ft = task->size_ft; short Size_rt = task->size_rt; short Size_st = task->size_st; short Size_mt = task->size_mt; short Size_srt = task->size_srt; short Size_fd = task->size_fd; short Size_kt = task->size_kt; if (task->dbopen && opentype == FIRST_OPEN) { diclose(task, ALL_DBS); dbopen_sv = 0; } if (!task->dbopen && opentype == INCR_OPEN) return (dberr(S_DBOPEN)); if (opentype == INCR_OPEN && task->trans_id[0]) return (dberr(S_TRACTIVE)); if (openmode) { if (opentype == FIRST_OPEN) { /* could be set by inifile or cmdline */ omode = (DB_TCHAR) (*openmode ? *openmode : task->type[0]); omode = (DB_TCHAR) (vistupper(omode) ? vtotlower(omode) : omode); switch (omode) { case DB_TEXT('x'): case DB_TEXT('s'): task->db_lockmgr = 1; task->type[0] = omode; break; case DB_TEXT('o'): task->db_lockmgr = 0; task->type[0] = DB_TEXT('x'); break; default: return (dberr(S_BADTYPE)); } } } else task->type[0] = DB_TEXT('x'); task->type[1] = DB_TEXT('\0'); if (opentype == FIRST_OPEN) { /* initialize from ini file */ if (initFromIniFile(task) != S_OKAY) /* must be called before dio_init() */ return task->db_status; if (task->db_lockmgr && !task->lmc) return (dberr(S_NOLOCKCOMM)); /* initialize the country table if "db.star.ctb" exists */ if (ctb_init(task) != S_OKAY) return task->db_status; } else { /* ensure overflow file is closed as it will be reinitilized */ dio_close(task->ov_file, task); } /* initialize multi-db tables */ if (initdbt(dbnames, task) != S_OKAY) goto clean_ret; /* read in schema tables */ if (inittab(task, sg, sc) != S_OKAY) goto clean_ret; if (renfiles(task) != S_OKAY) goto clean_ret; if (task->db_lockmgr) { /* [637] Only alloc task->file_refs for shared open */ if (alloc_table((void **) &task->file_refs, task->size_ft * sizeof(FILE_NO), task->old_size_ft * sizeof(FILE_NO), task) != S_OKAY) goto clean_ret; } for (ii = task->old_size_ft; ii < task->size_ft; ii++) task->sgs[ii] = sg; if (*task->type == DB_TEXT('s')) { /* build application file lock tables */ if (bld_lock_tables(task) != S_OKAY) goto clean_ret; task->dbopen = 1; } else task->dbopen = 2; if (opentype == FIRST_OPEN && !(task->dboptions & NORECOVER) && taf_login(task) != S_OKAY) goto clean_ret_2; if (task->db_lockmgr) initses(opentype, task); else recovery_check(task); if (task->db_status != S_OKAY) goto clean_ret; if (o_setup(task) != S_OKAY) goto clean_ret; if (key_open(task) == S_OKAY) { if (dio_init(task) == S_OKAY) return task->db_status; }clean_ret: /* an error has occured, clean-up the mess w/ taf_logout() */ hold_db_status = task->db_status; if (dbopen_sv == 0) { if (!(task->dboptions & NORECOVER)) taf_logout(task); } task->db_status = hold_db_status;clean_ret_2: /* an error has occured, clean-up the mess w/o taf_logout() */ /* Do not attampt to free tables allocated from heap if there was an error while doing incremental open. There's no way of telling which tables were successfully allocated, so just leave them all alone - they will be freed next time a database is closed. */ hold_db_status = task->db_status; task->dbopen = 0; if (dbopen_sv == 0 || task->old_no_of_dbs == 0) { /* not doing incremental open */ termfree(ALL_DBS, task); } /* restore original sizes */ task->dbopen = dbopen_sv; task->lp_size = Lp_size; task->fp_size = Fp_size; task->page_size = Page_size; task->size_ft = Size_ft; task->size_rt = Size_rt; task->size_st = Size_st; task->size_mt = Size_mt; task->size_srt = Size_srt; task->size_fd = Size_fd; task->size_kt = Size_kt; task->curr_db_table = &task->db_table[task->curr_db]; task->curr_rn_table = &task->rn_table[task->curr_db]; task->no_of_dbs = task->old_no_of_dbs; return (task->db_status = hold_db_status);}/* ====================================================================== Initialize multiple database table entries*/int INTERNAL_FCN initdbt(const DB_TCHAR *dbnames, DB_TASK *task){ DB_TCHAR dbfile[FILENMLEN * 2]; DB_TCHAR *path; DB_TCHAR *name; const DB_TCHAR *cp; register int dbt_lc; /* loop control */ register int i; /* compute number of databases to be opened */ task->old_no_of_dbs = (short) ((!task->db_table) ? 0 : task->no_of_dbs); ++task->no_of_dbs; for (cp = dbnames; *cp; ++cp) { if (*cp == DB_TEXT(';')) ++task->no_of_dbs; } /* allocate task->db_table space */ if (alloc_table((void **) &task->db_table, task->no_of_dbs * sizeof(DB_ENTRY), task->old_no_of_dbs * sizeof(DB_ENTRY), task) != S_OKAY) return task->db_status; if (alloc_table((void **) &task->rn_table, task->no_of_dbs * sizeof(RN_ENTRY), task->old_no_of_dbs * sizeof(RN_ENTRY), task) != S_OKAY) return task->db_status; /* initialize task->db_table entries */ for (dbt_lc = task->no_of_dbs, cp = dbnames, task->curr_db_table = &task->db_table[task->old_no_of_dbs]; --dbt_lc >= task->old_no_of_dbs; ++cp, ++task->curr_db_table) { /* extract database name */ for (i = 0; *cp && *cp != DB_TEXT(';'); ++cp, ++i) { if (i >= FILENMLEN) return dberr(S_NAMELEN); dbfile[i] = *cp; } dbfile[i] = 0; /* make sure database is not already open */ if (ddbnum(dbfile, task) != S_INVDB) return task->db_status; task->db_status = S_OKAY; /* set by ddbnum() */ psp_pathSplit(dbfile, &path, &name); if (path) { vtstrcpy(DB_REF(db_path), path); psp_freeMemory(path, 0); } else vtstrcpy(DB_REF(db_path), DB_TEXT("")); if (name) { vtstrcpy(DB_REF(db_name), name); psp_freeMemory(name, 0); } } return task->db_status;}static DB_TCHAR defDbtafPath[3] = { DB_TEXT('.'), DIRCHAR, DB_TEXT('\0') };/* ====================================================================== Check for possible external recovery*/int INTERNAL_FCN recovery_check(DB_TASK *task){#ifdef MULTI_TAFFILE PSP_DIR dir = NULL; DB_TCHAR *loc = NULL; DB_TCHAR *name; DB_TCHAR *original = NULL;#endif /* MULTI_TAFFILE */ if (task->dboptions & NORECOVER || psp_lmcFlags(task->lmc) & PSP_FLAG_NO_TAF_ACCESS) return S_OKAY;#ifdef MULTI_TAFFILE if (task->dboptions & MULTITAF) { /* There may be multiple TAF files in the TAF directory. Get each TAF file name and copy it into task->dbtaf, then do the recovery check for all log files in that TAF file. At the end, replace the original TAF file name. */ original = psp_strdup(task->dbtaf, 0); psp_pathSplit(task->dbtaf, &name, NULL); if (name == task->dbtaf) { /* If there is no subdir data in the dbtaf path, specify the current directory */ psp_freeMemory(name, 0); name = psp_strdup(defDbtafPath, 0); } dir = psp_pathOpen(name, DB_TEXT("*.taf")); psp_freeMemory(name, 0); if (!dir) { psp_freeMemory(original, 0); return (dberr(S_DBLACCESS)); } loc = psp_pathGetFile(task->dbtaf); } for ( ; ; ) { if (task->dboptions & MULTITAF) { if ((name = psp_pathNext(dir)) == NULL) break; vtstrncpy(loc, name, FILENMLEN - (loc - task->dbtaf)); task->dbtaf[FILENMLEN - 1] = 0; psp_freeMemory(name, 0); }#endif /* MULTI_TAFFILE */ /* get logfile count */ if (!(psp_lmcFlags(task->lmc) & PSP_FLAG_NO_TAF_ACCESS)) { if (taf_access(DEL_LOGFILE, task) == S_OKAY) { taf_release(0, task); /* release so 'throw' in dbautorec isn't catastrophic since */ /* lockmgr holds off other users, tafbuf.cnt will be stable */ if (tafbuf.cnt) { dbautorec(task); /* notify user of recovery */ if (taf_access(DEL_LOGFILE, task) == S_OKAY) { /* perform recovery on each file */ while (tafbuf.cnt) { /* taf_del() will readjust tafbuf.files & cnt; 0 needing recovery */ if (drecover(tafbuf.files[0], task) != S_OKAY) { taf_release(0, task); return (dberr(S_RECFAIL)); } taf_del(tafbuf.files[0], task); } taf_release(0, task); } } } }#ifdef MULTI_TAFFILE if (!(task->dboptions & MULTITAF)) break; } if (task->dboptions & MULTITAF) { psp_pathClose(dir); vtstrcpy(task->dbtaf, original); psp_freeMemory(original, 0); }#endif /* MULTI_TAFFILE */ return task->db_status;}/* ====================================================================== Initial lock manager session*/static int INTERNAL_FCN initses(int opentype, DB_TASK *task){ LM_DBOPEN *send_pkt = NULL; LR_DBOPEN *recv_pkt = NULL; LM_LOGIN *login_pkt = NULL; FILE_NO *fref_ptr = NULL; short *rcv_fref_ptr = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -