Esempio n. 1
0
        public virtual RC Unlock(LOCK locktype)
        {
            Debug.Assert(locktype <= LOCK.SHARED);
#if DEBUG
            SysEx.OSTRACE("UNLOCK {0} to {1} was {2}({3})", S.GetHashCode(), locktype, this.Locktype, SharedLockByte);
#endif
            var rc   = RC.OK;
            var type = this.Locktype;
            if (type >= LOCK.EXCLUSIVE)
            {
                lockingStrategy.UnlockFile(this, SHARED_FIRST, SHARED_SIZE);
                if (locktype == LOCK.SHARED && getReadLock() == 0)
                {
                    // This should never happen.  We should always be able to reacquire the read lock
                    rc = winLogError(RC.IOERR_UNLOCK, "winUnlock", Path);
                }
            }
            if (type >= LOCK.RESERVED)
            {
                try { lockingStrategy.UnlockFile(this, RESERVED_BYTE, 1); }
                catch (Exception) { }
            }
            if (locktype == LOCK.NO && type >= LOCK.SHARED)
            {
                unlockReadLock();
            }
            if (type >= LOCK.PENDING)
            {
                try { lockingStrategy.UnlockFile(this, PENDING_BYTE, 1); }
                catch (Exception) { }
            }
            this.Locktype = locktype;
            return(rc);
        }
Esempio n. 2
0
        public virtual RC CheckReservedLock(ref int pResOut)
        {
            int rc;

            if (Locktype >= LOCK.RESERVED)
            {
                rc = 1;
#if DEBUG
                SysEx.OSTRACE("TEST WR-LOCK {0} {1} (local)", S.Name, rc);
#endif
            }
            else
            {
                try
                {
                    lockingStrategy.LockFile(this, RESERVED_BYTE, 1);
                    lockingStrategy.UnlockFile(this, RESERVED_BYTE, 1);
                    rc = 1;
                }
                catch (IOException) { rc = 0; }
                rc = 1 - rc;
#if DEBUG
                SysEx.OSTRACE("TEST WR-LOCK {0} {1} (remote)", S.GetHashCode(), rc);
#endif
            }
            pResOut = rc;
            return(RC.OK);
        }
Esempio n. 3
0
        public virtual RC Read(byte[] buffer, int amount, long offset)
        {
            if (buffer == null)
            {
                buffer = new byte[amount];
            }
#if DEBUG
            SysEx.OSTRACE("READ {0} lock={1}", S.GetHashCode(), Locktype);
#endif
            if (!S.CanRead)
            {
                return(RC.IOERR_READ);
            }
            if (seekWinFile(offset) != 0)
            {
                return(RC.FULL);
            }
            int nRead; // Number of bytes actually read from file
            try { nRead = S.Read(buffer, 0, amount); }
            catch (Exception) { LastErrno = (uint)Marshal.GetLastWin32Error(); return(winLogError(RC.IOERR_READ, "winRead", Path)); }
            if (nRead < amount)
            {
                // Unread parts of the buffer must be zero-filled
                Array.Clear(buffer, (int)nRead, (int)(amount - nRead));
                return(RC.IOERR_SHORT_READ);
            }
            return(RC.OK);
        }
Esempio n. 4
0
        public virtual RC Sync(SYNC flags)
        {
            // Check that one of SQLITE_SYNC_NORMAL or FULL was passed
            Debug.Assert(((int)flags & 0x0F) == (int)SYNC.NORMAL || ((int)flags & 0x0F) == (int)SYNC.FULL);
            SysEx.OSTRACE("SYNC {0} lock={1}", S.GetHashCode(), Locktype);
#if SQLITE_NO_SYNC
            return(SQLITE.OK);
#else
            S.Flush();
            return(RC.OK);
#endif
        }
Esempio n. 5
0
        public virtual RC Close()
        {
            Debug.Assert(Shm == null);
#if DEBUG
            SysEx.OSTRACE("CLOSE {0} ({1})", S.GetHashCode(), S.Name);
#endif
            bool rc;
            int  cnt = 0;
            do
            {
                S.Close();
                rc = true;
            } while (!rc && ++cnt < MX_CLOSE_ATTEMPT);
            return(rc ? RC.OK : winLogError(RC.IOERR_CLOSE, "winClose", Path));
        }
Esempio n. 6
0
        public virtual RC Truncate(long size)
        {
            var rc = RC.OK;

#if DEBUG
            SysEx.OSTRACE("TRUNCATE {0} {1,11}", S.Name, size);
#endif
            // If the user has configured a chunk-size for this file, truncate the file so that it consists of an integer number of chunks (i.e. the
            // actual file size after the operation may be larger than the requested size).
            if (Chunk != 0)
            {
                size = ((size + Chunk - 1) / Chunk) * Chunk;
            }
            try { S.SetLength(size); rc = RC.OK; }
            catch (IOException e) { LastErrno = (uint)Marshal.GetLastWin32Error(); rc = winLogError(RC.IOERR_TRUNCATE, "winTruncate2", Path); }
            SysEx.OSTRACE("TRUNCATE {0} {1,%11} {2}", S.GetHashCode(), size, rc == RC.OK ? "ok" : "failed");
            return(rc);
        }
Esempio n. 7
0
        public virtual RC Write(byte[] buffer, int amount, long offset)
        {
            Debug.Assert(amount > 0);
#if DEBUG
            SysEx.OSTRACE("WRITE {0} lock={1}", S.GetHashCode(), Locktype);
#endif
            var  rc    = seekWinFile(offset);
            long wrote = S.Position;
            try
            {
                Debug.Assert(buffer.Length >= amount);
                S.Write(buffer, 0, amount);
                rc    = 1;
                wrote = S.Position - wrote;
            }
            catch (IOException) { return(RC.READONLY); }
            if (rc == 0 || amount > (int)wrote)
            {
                LastErrno = (uint)Marshal.GetLastWin32Error();
                return(LastErrno == ERROR_HANDLE_DISK_FULL || LastErrno == ERROR_DISK_FULL ? RC.FULL : winLogError(RC.IOERR_WRITE, "winWrite", Path));
            }
            return(RC.OK);
        }
Esempio n. 8
0
        public virtual RC Lock(LOCK locktype)
        {
#if DEBUG
            SysEx.OSTRACE("LOCK {0} {1} was {2}({3})", S.GetHashCode(), locktype, this.Locktype, SharedLockByte);
#endif
            // If there is already a lock of this type or more restrictive on the OsFile, do nothing. Don't use the end_lock: exit path, as sqlite3OsEnterMutex() hasn't been called yet.
            if (this.Locktype >= locktype)
            {
                return(RC.OK);
            }
            // Make sure the locking sequence is correct
            Debug.Assert(this.Locktype != LOCK.NO || locktype == LOCK.SHARED);
            Debug.Assert(locktype != LOCK.PENDING);
            Debug.Assert(locktype != LOCK.RESERVED || this.Locktype == LOCK.SHARED);
            // 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.
            uint error          = 0;
            var  res            = 1;     // Result of a windows lock call
            var  gotPendingLock = false; // True if we acquired a PENDING lock this time
            var  newLocktype    = this.Locktype;
            if (this.Locktype == LOCK.NO || (locktype == LOCK.EXCLUSIVE && this.Locktype == LOCK.RESERVED))
            {
                res = 0;
                var cnt = 3;
                while (cnt-- > 0 && res == 0)
                {
                    try { lockingStrategy.LockFile(this, PENDING_BYTE, 1); res = 1; }
                    catch (Exception)
                    {
                        // Try 3 times to get the pending lock.  The pending lock might be held by another reader process who will release it momentarily.
#if DEBUG
                        SysEx.OSTRACE("could not get a PENDING lock. cnt={0}", cnt);
#endif
                        Thread.Sleep(1);
                    }
                }
                gotPendingLock = (res != 0);
                if (0 == res)
                {
                    error = (uint)Marshal.GetLastWin32Error();
                }
            }
            // Acquire a shared lock
            if (locktype == LOCK.SHARED && res != 0)
            {
                Debug.Assert(this.Locktype == LOCK.NO);
                res = getReadLock();
                if (res != 0)
                {
                    newLocktype = LOCK.SHARED;
                }
                else
                {
                    error = (uint)Marshal.GetLastWin32Error();
                }
            }
            // Acquire a RESERVED lock
            if (locktype == LOCK.RESERVED && res != 0)
            {
                Debug.Assert(this.Locktype == LOCK.SHARED);
                try { lockingStrategy.LockFile(this, RESERVED_BYTE, 1); newLocktype = LOCK.RESERVED; res = 1; }
                catch (Exception) { res = 0; error = (uint)Marshal.GetLastWin32Error(); }
                if (res != 0)
                {
                    newLocktype = LOCK.RESERVED;
                }
                else
                {
                    error = (uint)Marshal.GetLastWin32Error();
                }
            }
            // Acquire a PENDING lock
            if (locktype == LOCK.EXCLUSIVE && res != 0)
            {
                newLocktype    = LOCK.PENDING;
                gotPendingLock = false;
            }
            // Acquire an EXCLUSIVE lock
            if (locktype == LOCK.EXCLUSIVE && res != 0)
            {
                Debug.Assert(this.Locktype >= LOCK.SHARED);
                res = unlockReadLock();
#if DEBUG
                SysEx.OSTRACE("unreadlock = {0}", res);
#endif
                try { lockingStrategy.LockFile(this, SHARED_FIRST, SHARED_SIZE); newLocktype = LOCK.EXCLUSIVE; res = 1; }
                catch (Exception) { res = 0; }
                if (res != 0)
                {
                    newLocktype = LOCK.EXCLUSIVE;
                }
                else
                {
                    error = (uint)Marshal.GetLastWin32Error();
#if DEBUG
                    SysEx.OSTRACE("error-code = {0}", error);
#endif
                    getReadLock();
                }
            }
            // If we are holding a PENDING lock that ought to be released, then release it now.
            if (gotPendingLock && locktype == LOCK.SHARED)
            {
                lockingStrategy.UnlockFile(this, PENDING_BYTE, 1);
            }
            // Update the state of the lock has held in the file descriptor then return the appropriate result code.
            var rc = RC.OK;
            if (res != 0)
            {
                rc = RC.OK;
            }
            else
            {
#if DEBUG
                SysEx.OSTRACE("LOCK FAILED {0} trying for {1} but got {2}", S.GetHashCode(), locktype, newLocktype);
#endif
                LastErrno = error;
                rc        = RC.BUSY;
            }
            this.Locktype = newLocktype;
            return(rc);
        }