taffcns.c
来自「db.* (pronounced dee-be star) is an adva」· C语言 代码 · 共 544 行 · 第 1/2 页
C
544 行
/*************************************************************************** * * * 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. * * * **************************************************************************//*-------------------------------------------------------------------------- This module contains the functions which access and manipulate the Transaction Activity File. The name of a transaction log file is written to the TAF just before a commit and removed following the commit in order to provide for external recovery in the event that the lock manager fails. Access to the TAF must be synchronized so that only one process has control of it at a time. The lock manager cannot be used for this synchronization because if it is active then the TAF is not needed. Thus, some outside resource must be used to lock the TAF for exclusive access. Function "locking" (or "lockf" on Unix) is called to gain exclusive access to the TAF. This function is available in MS-DOS 3+, and Unix System V and BSD (as "lockf"). If it is not available for your particular network or operating system then you will need to modify the call to locking to that which is available on your system. Alternatively, you can compile this module with constant PORTABLE defined. This will use a zero-length file "dblfg" as a semaphore on the TAF. If the file exists then the TAF is not being used. If it doesn't exist then the TAF is being used. This technique has been used in earlier versions of db.*. It's not ideal but it does work. We used function "locking" instead of simply opening the file exclusively because on PC-NETWORK a sharing violation occurs if a program attempts to exclusively open a file which is already exlusively opened by another program. We could accept this if all it did was return a status code but, for some reason, the sharing violation is reported to the user (similar to a floppy disk error).--------------------------------------------------------------------------*/#include "db.star.h"#ifndef O_SYNC#define O_SYNC 0x0000#endif/* maximum number of attempts to gain access TAF */#define MAXTRIES 100/* buffer containing TAF file */TAFFILE tafbuf;#define LOCK_LEN sizeof(tafbuf)static DB_TCHAR * INTERNAL_FCN dblfg_name(DB_TASK *);static int INTERNAL_FCN taf_lock(DB_TASK *);static void INTERNAL_FCN taf_unlock(DB_TASK *);/***************************************************************************/int INTERNAL_FCN taf_login(DB_TASK *task){ int stat;#ifdef MULTI_TAFFILE if (task->dboptions & MULTITAF) { if (task->dbuserid[0]) { vtstrcpy(psp_pathGetFile(task->dbtaf), task->dbuserid); vtstrcat(task->dbtaf, DB_TEXT(".taf")); } else if (task->dbopen == 1) return (dberr(S_DBLACCESS)); }#endif /* MULTI_TAFFILE */#if 0 /* create the taf if necessary */ if ((stat = taf_open(task)) != S_OKAY) return (task->db_status = stat); taf_close(task); /* taf must be closed before access */#endif /* TAF exists at this point */ stat = taf_access(DEL_LOGFILE, task); if (stat != S_OKAY) return (task->db_status = stat); if (tafbuf.user_count == 0) { tafbuf.unicode = DBSTAR_UNICODE_FLAG; vtstrcpy(tafbuf.lmc_type, task->lmc_type); if (task->lockmgrn) vtstrcpy(tafbuf.lockmgrn, task->lockmgrn); else tafbuf.lockmgrn[0] = DB_TEXT('\0'); } else { /* The LMC transport type, the lock manager name, and the unicode setting must all match between this task and the TAF file. */ if (vtstrcmp(tafbuf.lmc_type, task->lmc_type) != 0 || (task->lockmgrn && vtstrcmp(tafbuf.lockmgrn, task->lockmgrn)) || (!task->lockmgrn && tafbuf.lockmgrn[0] != DB_TEXT('\0')) || tafbuf.unicode != DBSTAR_UNICODE_FLAG) goto ret_err; } ++tafbuf.user_count; stat = taf_release(0, task); return (task->db_status);ret_err: taf_unlock(task); taf_close(task); return (dberr(S_TAFSYNC));}/***************************************************************************/int INTERNAL_FCN taf_logout(DB_TASK *task){ int stat;#if 0 if (task->lockMgrComm == LMC_GENERAL && task->lmc_avail(task) != S_OKAY) { /* assume that if the DBL is not accessable, neither is the TAF */ taf_close(task); return task->db_status; }#endif stat = taf_access(DEL_LOGFILE, task); if (stat != S_OKAY) return (task->db_status = stat); if (vtstrcmp(tafbuf.lmc_type, task->lmc_type) != 0 || (task->lockmgrn && vtstrcmp(tafbuf.lockmgrn,task->lockmgrn) != 0) || (!task->lockmgrn && tafbuf.lockmgrn[0] != DB_TEXT('\0')) || tafbuf.unicode != DBSTAR_UNICODE_FLAG) goto ret_err; if (tafbuf.user_count > 0) --tafbuf.user_count; taf_release(0, task); taf_close(task); return (task->db_status);ret_err: taf_unlock(task); taf_close(task); return (dberr(S_TAFSYNC));}/***************************************************************************/static void INTERNAL_FCN taf_unlock(DB_TASK *task){ PSP_FH lfn; /* one user mode does not require locks */ if (!task->db_lockmgr) return; /* Free the lock */ if (task->dboptions & PORTABLE) { if (psp_lmcFlags(task->lmc) & PSP_FLAG_TAF_CLOSE) taf_close(task); /* close file before releasing it */ else commit_file(task->lfn, task); /* create lock file guard file */ lfn = open_b(dblfg_name(task), O_CREAT | O_SYNC, PSP_FLAG_SYNC, task); if (lfn != NULL) psp_fileClose(lfn); } else { commit_file(task->lfn, task); /* need the file handle here */ psp_fileUnlock(task->lfn); if (psp_lmcFlags(task->lmc) & PSP_FLAG_TAF_CLOSE) taf_close(task); /* close file before releasing it */ }}/***************************************************************************/static int INTERNAL_FCN taf_lock(DB_TASK *task){ int not_locked; /* one user mode does not require locks */ if (!task->db_lockmgr) return 0; if (task->dboptions & PORTABLE) { not_locked = psp_fileRemove(dblfg_name(task)); if (psp_errno() == EACCES) dberr(S_EACCESS); } else not_locked = psp_fileLock(task->lfn); return not_locked;}/* ====================================================================== Open Transaction Activity File*/int INTERNAL_FCN taf_open(DB_TASK *task){ unsigned long rd_opt, fopt; /* even with READONLY option set, attempt to creat log file */ rd_opt = task->dboptions & READONLY; /* Do not re-open an open file */ if (task->lfn) return (task->db_status); task->dboptions &= ~READONLY; /* try to create */ /* only open with the O_SYNC option when SYNCFILES is on */ if (task->dboptions & SYNCFILES) fopt = O_RDWR | O_SYNC; else fopt = O_RDWR; if ((task->lfn = open_b(task->dbtaf, fopt, PSP_FLAG_SYNC, task)) == NULL) { if (psp_errno() == ENOENT)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?