📄 lock.cpp
字号:
/*************************************************************************** lock.cpp - description ------------------- begin : Thu Jan 17 2002 copyright : (C) 2002 by email : ***************************************************************************//*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************//* $Id: lock.cpp,v 1.5 2000/11/07 20:31:20 dbryson Exp $ Xbase project source code This file contains the basic Xbase routines for locking Xbase files Copyright (C) 1997 StarTech, Gary A. Kunkel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it 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 this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Mail: Technology Associates, Inc. XBase Project 1455 Deming Way #11 Sparks, NV 89434 USA Email: xbase@techass.com See our website at: xdb.sourceforge.net V 1.0 10/10/97 - Initial release of software V 1.5 1/2/98 - Added memo field support V 1.6a 4/1/98 - Added expression support V 1.6b 4/8/98 - Numeric index keys V 1.7.4b 7/3/98 - Modified Exclusive Lock to conditionally lock memo file V 1.7.4d 10/28/98 - Added OS2/DOS/Windows/NT Locking support, added const*/#ifdef __WIN32__#include "xbconfigw32.h"#else#include "xbconfig.h"#endif#include "xbase.h"#ifdef XB_LOCKING_ON#include <fcntl.h>#include <stdio.h>#ifdef HAVE_SYS_TYPES_H #include <sys/types.h> /* BSDI BSD/OS 3.1 */#endif#ifdef HAVE_SYS_LOCKING_H#include <sys/locking.h>#endif#ifdef HAVE_IO_H#include <io.h>#endif#include "xbexcept.h"#include <errno.h>/*! \file lock.cpp*//************************************************************************///! UnixToDosLockCommand/*! \param WaitOption \param LockType*/#ifndef HAVE_FCNTLxbShort xbDbf::UnixToDosLockCommand( const xbShort WaitOption, const xbShort LockType ) const// this method converts the unix locking commands into as close of // a dos lock command as is possible{ if( LockType == LK_LOCK ) return LK_UNLCK; else if( WaitOption == F_SETLK ) return LK_NBLCK; else return LK_LOCK;}#endif/************************************************************************///! Short description/*! \param WaitOption \param LockType \param LRecNo*/xbShort xbDbf::LockDatabase( const xbShort WaitOption, const xbShort LockType, const xbULong LRecNo ){ /* if WaitOption = F_SETLK - return immediately F_SETLKW - wait until lock function executes if LockType = F_RDLCK - do a read / shared lock F_WRLCK - do a write / exclusive lock F_UNLCK - do an unlock if LRecNo = 0L - lock the dbf header = 1-n - lock appropriate record if locking routines fail, look in errno or do perror() for explanation Nested record locking support added Oct 26, 1998 by Derry Bryson */#ifdef HAVE_FCNTL struct flock fl; fl.l_type = LockType;#else long length; int whence, Cmd; long offset;#endif//fprintf(stderr, "LockDatabase: %s %s CurLockCount=%d\n", LRecNo ? "Record" : "File" ,// LockType == F_RDLCK ? "F_RDLCK" : LockType == F_WRLCK ? "F_WRLCK" : "F_UNLCK",// CurLockCount); if( LRecNo > NoOfRecs ) xb_error(XB_INVALID_RECORD); if( LRecNo == 0L ) { /* ** This is a file lock. The following code (and some below) ** allows nesting of file lock calls by only locking on the ** first lock call (unless upgrading a read lock to a write lock) ** and counting the number of locks to allow unnesting of locks. */ if(CurLockType != -1) { if(LockType != F_UNLCK) { /* ** Allow changing a read lock into a write lock, but ** if a write lock is already held just say success. */ if(CurLockType == F_WRLCK || CurLockType == LockType) {//fprintf(stderr, "LockDatabase: nested lock succeeds\n"); CurLockCount++; return XB_NO_ERROR; } } else { CurLockCount--; /* ** If there are still outstanding locks, just indicate success. */ if(CurLockCount) {//fprintf(stderr, "LockDatabase: nested unlock returns with remaining locks\n"); return XB_NO_ERROR; } } } #ifdef HAVE_FCNTL fl.l_whence = SEEK_SET; fl.l_start = 0L; fl.l_len = 7L;#else whence = SEEK_SET; offset = 0L; length = 7L;#endif }#if 0 /* ** I don't understand why this code is here (hence I have removed it) ** as it causes locks which are never removed - Derry Bryson */ else if ( CurRec ) {#ifdef HAVE_FCNTL fl.l_whence = SEEK_CUR; fl.l_start = (HeaderLen+(RecordLen*(LRecNo-1))) - DbfTell(); fl.l_len = 1L;#else whence = SEEK_CUR; offset = (HeaderLen+(RecordLen*(LRecNo-1))) - DbfTell(); length = 1L;#endif }#endif else /* CurRec = 0 */ { /* ** This is a record lock. The following code (and some below) ** allows nesting of record lock calls by only locking on the ** first lock call (unless upgrading a read lock to a write lock) ** and counting the number of locks to allow unnesting of locks. */ if(CurLockedRecNo) { if(LockType != F_UNLCK) { /* ** Allow changing a read lock into a write lock, but ** if a write lock is already held just say success. */ if(CurRecLockType == F_WRLCK || CurRecLockType == LockType) {//fprintf(stderr, "LockDatabase: nested lock succeeds\n"); CurRecLockCount++; return XB_NO_ERROR; } } else { CurRecLockCount--; /* ** If there are still outstanding locks, just indicate success. */ if(CurRecLockCount) {//fprintf(stderr, "LockDatabase: nested unlock returns with remaining locks\n"); return XB_NO_ERROR; } } } #ifdef HAVE_FCNTL fl.l_whence = SEEK_SET; fl.l_start = HeaderLen + (RecordLen*(LRecNo-1) ); fl.l_len = 1L;#else whence = SEEK_SET; offset = HeaderLen + (RecordLen*(LRecNo-1)); length = 1L;#endif }#ifdef HAVE_FCNTL if(fcntl(fileno(fp), WaitOption, &fl) == -1){//fprintf(stderr, "LockDatabase: failed!\n"); xb_error(XB_LOCK_FAILED)} else { if(LRecNo) /* record lock */ { if(LockType != F_UNLCK) { CurLockedRecNo = LRecNo; CurRecLockType = LockType; CurRecLockCount++; } else if(!CurRecLockCount) { CurLockedRecNo = 0; CurRecLockType = -1; } } else { if(LockType != F_UNLCK) { CurLockType = LockType; CurLockCount++; } else if (!CurLockCount) CurLockType = -1; }//fprintf(stderr, "LockDatabase: success!\n"); return XB_NO_ERROR; }#else if( fseek( fp, offset, whence ) != 0 ) xb_error(XB_SEEK_ERROR); Cmd = UnixToDosLockCommand( WaitOption, LockType ); if( locking( fileno( fp ), Cmd, length ) != 0 ) xb_error(XB_LOCK_FAILED) else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -