/* ** Acquire a reader lock. */ static int getReadLock( os2File *pFile ){ FILELOCK LockArea, UnlockArea; APIRET res; memset(&LockArea, 0, sizeof(LockArea)); memset(&UnlockArea, 0, sizeof(UnlockArea)); LockArea.lOffset = SHARED_FIRST; LockArea.lRange = SHARED_SIZE; UnlockArea.lOffset = 0L; UnlockArea.lRange = 0L; res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); OSTRACE3( "GETREADLOCK %d res=%d\n", pFile->h, res ); return res; }
/* ** Undo a readlock */ static int unlockReadLock( os2File *id ){ FILELOCK LockArea, UnlockArea; APIRET res; memset(&LockArea, 0, sizeof(LockArea)); memset(&UnlockArea, 0, sizeof(UnlockArea)); LockArea.lOffset = 0L; LockArea.lRange = 0L; UnlockArea.lOffset = SHARED_FIRST; UnlockArea.lRange = SHARED_SIZE; res = DosSetFileLocks( id->h, &UnlockArea, &LockArea, 2000L, 1L ); OSTRACE3( "UNLOCK-READLOCK file handle=%d res=%d?\n", id->h, res ); return res; }
int flock(int handle, int mode) { FILELOCK slock, sunlock; APIRET r; slock.lOffset = sunlock.lOffset = 0; if (mode & LOCK_UN) { sunlock.lRange = 0x7fffffff; slock.lRange = 0; } else { slock.lRange = 0x7fffffff; sunlock.lRange = 0; } r = DosSetFileLocks(handle, &sunlock, &slock, (mode & LOCK_NB) ? 0 : 10000, (mode & LOCK_SH) ? 1 : 0); if (r) errno = EWOULDBLOCK; return r ? -1 : 0; }
PRStatus _PR_MD_LOCKFILE(PRInt32 f) { PRInt32 rv; FILELOCK lock, unlock; FILELOCKL lockL, unlockL; lock.lOffset = 0; lockL.lOffset = 0; lock.lRange = 0xffffffff; lockL.lRange = 0xffffffffffffffff; unlock.lOffset = 0; unlock.lRange = 0; unlockL.lOffset = 0; unlockL.lRange = 0; /* * loop trying to DosSetFileLocks(), * pause for a few miliseconds when can't get the lock * and try again */ for( rv = FALSE; rv == FALSE; /* do nothing */ ) { if (isWSEB) { rv = myDosSetFileLocksL( (HFILE) f, &unlockL, &lockL, 0, 0); } else { rv = DosSetFileLocks( (HFILE) f, &unlock, &lock, 0, 0); } if ( rv != NO_ERROR ) { DosSleep( 50 ); /* Sleep() a few milisecs and try again. */ } } /* end for() */ return PR_SUCCESS; } /* end _PR_MD_LOCKFILE() */
PRStatus _PR_MD_UNLOCKFILE(PRInt32 f) { PRInt32 rv; FILELOCK lock, unlock; FILELOCKL lockL, unlockL; lock.lOffset = 0; lockL.lOffset = 0; lock.lRange = 0; lockL.lRange = 0; unlock.lOffset = 0; unlockL.lOffset = 0; unlock.lRange = 0xffffffff; unlockL.lRange = 0xffffffffffffffff; if (isWSEB) { rv = myDosSetFileLocksL( (HFILE) f, &unlockL, &lockL, 0, 0); } else { rv = DosSetFileLocks( (HFILE) f, &unlock, &lock, 0, 0); } if ( rv != NO_ERROR ) { return PR_SUCCESS; } else { return PR_FAILURE; } } /* end _PR_MD_UNLOCKFILE() */
inline APIRET _SetFileLocksL(HFILE hFile, PFILELOCKL pflUnlock, PFILELOCKL pflLock, ULONG timeout, ULONG flags) { if (_DosSetFileLocksL) { APIRET rc; rc = _DosSetFileLocksL( hFile, pflUnlock, pflLock, timeout, flags); /* on FAT/HPFS/LAN a INVALID_PARAMETER is returned, seems that only JFS can handle >2GB ranges. */ if (rc != 87) return rc; /* got INVALID_PARAMETER, fallback to standard call */ } FILELOCK flUnlock = { pflUnlock->lOffset, pflUnlock->lRange }; FILELOCK flLock = { pflLock->lOffset, pflLock->lRange }; return DosSetFileLocks( hFile, &flUnlock, &flLock, timeout, flags); }
/* ** Lock the file with the lock specified by parameter locktype - one ** of the following: ** ** (1) SHARED_LOCK ** (2) RESERVED_LOCK ** (3) PENDING_LOCK ** (4) EXCLUSIVE_LOCK ** ** Sometimes when requesting one lock state, additional lock states ** are inserted in between. The locking might fail on one of the later ** transitions leaving the lock state different from what it started but ** still short of its goal. The following chart shows the allowed ** transitions and the inserted intermediate states: ** ** UNLOCKED -> SHARED ** SHARED -> RESERVED ** SHARED -> (PENDING) -> EXCLUSIVE ** RESERVED -> (PENDING) -> EXCLUSIVE ** PENDING -> EXCLUSIVE ** ** This routine will only increase a lock. The os2Unlock() routine ** erases all locks at once and returns us immediately to locking level 0. ** It is not possible to lower the locking level one step at a time. You ** must go straight to locking level 0. */ static int os2Lock( sqlite3_file *id, int locktype ){ int rc = SQLITE_OK; /* Return code from subroutines */ APIRET res = NO_ERROR; /* Result of an OS/2 lock call */ int newLocktype; /* Set pFile->locktype to this value before exiting */ int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ FILELOCK LockArea, UnlockArea; os2File *pFile = (os2File*)id; memset(&LockArea, 0, sizeof(LockArea)); memset(&UnlockArea, 0, sizeof(UnlockArea)); assert( pFile!=0 ); OSTRACE4( "LOCK %d %d was %d\n", pFile->h, locktype, pFile->locktype ); /* If there is already a lock of this type or more restrictive on the ** os2File, do nothing. Don't use the end_lock: exit path, as ** sqlite3_mutex_enter() hasn't been called yet. */ if( pFile->locktype>=locktype ){ OSTRACE3( "LOCK %d %d ok (already held)\n", pFile->h, locktype ); return SQLITE_OK; } /* Make sure the locking sequence is correct */ assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); assert( locktype!=PENDING_LOCK ); assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of ** the PENDING_LOCK byte is temporary. */ newLocktype = pFile->locktype; if( pFile->locktype==NO_LOCK || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK) ){ LockArea.lOffset = PENDING_BYTE; LockArea.lRange = 1L; UnlockArea.lOffset = 0L; UnlockArea.lRange = 0L; /* wait longer than LOCK_TIMEOUT here not to have to try multiple times */ res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 100L, 0L ); if( res == NO_ERROR ){ gotPendingLock = 1; OSTRACE3( "LOCK %d pending lock boolean set. res=%d\n", pFile->h, res ); } } /* Acquire a shared lock */ if( locktype==SHARED_LOCK && res == NO_ERROR ){ assert( pFile->locktype==NO_LOCK ); res = getReadLock(pFile); if( res == NO_ERROR ){ newLocktype = SHARED_LOCK; } OSTRACE3( "LOCK %d acquire shared lock. res=%d\n", pFile->h, res ); } /* Acquire a RESERVED lock */ if( locktype==RESERVED_LOCK && res == NO_ERROR ){ assert( pFile->locktype==SHARED_LOCK ); LockArea.lOffset = RESERVED_BYTE; LockArea.lRange = 1L; UnlockArea.lOffset = 0L; UnlockArea.lRange = 0L; res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L ); if( res == NO_ERROR ){ newLocktype = RESERVED_LOCK; } OSTRACE3( "LOCK %d acquire reserved lock. res=%d\n", pFile->h, res ); } /* Acquire a PENDING lock */ if( locktype==EXCLUSIVE_LOCK && res == NO_ERROR ){ newLocktype = PENDING_LOCK; gotPendingLock = 0; OSTRACE2( "LOCK %d acquire pending lock. pending lock boolean unset.\n", pFile->h ); } /* Acquire an EXCLUSIVE lock */ if( locktype==EXCLUSIVE_LOCK && res == NO_ERROR ){ assert( pFile->locktype>=SHARED_LOCK ); res = unlockReadLock(pFile); OSTRACE2( "unreadlock = %d\n", res ); LockArea.lOffset = SHARED_FIRST; LockArea.lRange = SHARED_SIZE; UnlockArea.lOffset = 0L; UnlockArea.lRange = 0L; res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L ); if( res == NO_ERROR ){ newLocktype = EXCLUSIVE_LOCK; }else{ OSTRACE2( "OS/2 error-code = %d\n", res ); getReadLock(pFile); } OSTRACE3( "LOCK %d acquire exclusive lock. res=%d\n", pFile->h, res ); } /* If we are holding a PENDING lock that ought to be released, then ** release it now. */ if( gotPendingLock && locktype==SHARED_LOCK ){ int r; LockArea.lOffset = 0L; LockArea.lRange = 0L; UnlockArea.lOffset = PENDING_BYTE; UnlockArea.lRange = 1L; r = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L ); OSTRACE3( "LOCK %d unlocking pending/is shared. r=%d\n", pFile->h, r ); } /* Update the state of the lock has held in the file descriptor then ** return the appropriate result code. */ if( res == NO_ERROR ){ rc = SQLITE_OK; }else{ OSTRACE4( "LOCK FAILED %d trying for %d but got %d\n", pFile->h, locktype, newLocktype ); rc = SQLITE_BUSY; } pFile->locktype = newLocktype; OSTRACE3( "LOCK %d now %d\n", pFile->h, pFile->locktype ); return rc; }
APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, apr_size_t *nbytes) { ULONG rc = 0; ULONG byteswritten; if (!thefile->isopen) { *nbytes = 0; return APR_EBADF; } if (thefile->buffered) { char *pos = (char *)buf; int blocksize; int size = *nbytes; apr_thread_mutex_lock(thefile->mutex); if ( thefile->direction == 0 ) { // Position file pointer for writing at the offset we are logically reading from ULONG offset = thefile->filePtr - thefile->dataRead + thefile->bufpos; if (offset != thefile->filePtr) DosSetFilePtr(thefile->filedes, offset, FILE_BEGIN, &thefile->filePtr ); thefile->bufpos = thefile->dataRead = 0; thefile->direction = 1; } while (rc == 0 && size > 0) { if (thefile->bufpos == thefile->bufsize) // write buffer is full /* XXX bug; - rc is double-transformed os->apr below */ rc = apr_file_flush(thefile); blocksize = size > thefile->bufsize - thefile->bufpos ? thefile->bufsize - thefile->bufpos : size; memcpy(thefile->buffer + thefile->bufpos, pos, blocksize); thefile->bufpos += blocksize; pos += blocksize; size -= blocksize; } apr_thread_mutex_unlock(thefile->mutex); return APR_FROM_OS_ERROR(rc); } else { if (thefile->flags & APR_APPEND) { FILELOCK all = { 0, 0x7fffffff }; ULONG newpos; rc = DosSetFileLocks(thefile->filedes, NULL, &all, -1, 0); if (rc == 0) { rc = DosSetFilePtr(thefile->filedes, 0, FILE_END, &newpos); if (rc == 0) { rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten); } DosSetFileLocks(thefile->filedes, &all, NULL, -1, 0); } } else { rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten); } if (rc) { *nbytes = 0; return APR_FROM_OS_ERROR(rc); } *nbytes = byteswritten; return APR_SUCCESS; } }