Exemple #1
0
QCDiskQueue::Status
QCDiskQueue::Queue::GrowFile(
    QCDiskQueue::FileIdx inFileIdx, 
    off_t inTargetSz)
{
    QCStMutexLocker theLock(mMutex);
    if (! mRunFlag) {
        return Status(kErrorQueueStopped);
    }
    if (inFileIdx < 0 || inFileIdx >= mFileCount || mFdPtr[inFileIdx] < 0) {
        return Status(kErrorFileIdxOutOfRange);
    }
    const int64_t theOldSz = mFileInfoPtr[inFileIdx].mLastBlockIdx * mBlockSize;
    const int64_t theBlkIdx =
        (int64_t(inTargetSz > 0 ? inTargetSz : theOldSz) +  mBlockSize - 1) / mBlockSize;
    if (theBlkIdx >= (int64_t(1) << kBlockBitCount)) {
        return Status(kErrorSpaceAlloc);
    }
    mFileInfoPtr[inFileIdx].mSpaceAllocPendingFlag = inTargetSz > 0 && 
        inTargetSz > theOldSz;
    mFileInfoPtr[inFileIdx].mLastBlockIdx = theBlkIdx;
    
    mFileInfoPtr[inFileIdx].mSpaceAllocPendingFlag = true;
    return Status(kErrorNone);

}
Exemple #2
0
bool ZCnd_boost::Wait(boost::mutex& iMtx, double iTimeout)
	{
	boost::mutex::scoped_lock theLock(iMtx, boost::adopt_lock);

	return condition_variable::timed_wait(
		theLock, boost::posix_time::microseconds(iTimeout * 1e6));
	}
Exemple #3
0
 void Remove(
     QCThread& inThread)
 {
     QCStMutexLocker theLock(mMutex);
     ThreadList::Remove(inThread);
     mCount--;
 }
//**********************************************************************************************
// WCMRAudioDeviceManager::~WCMRAudioDeviceManager
//
//! It clears the device list, releasing each of the device.
//!
//! \param none
//!
//! \return Nothing.
//!
//**********************************************************************************************
WCMRAudioDeviceManager::~WCMRAudioDeviceManager()
{
    AUTO_FUNC_DEBUG;

	std::cout << "API::Destroying AudioDeviceManager " << std::endl;
	try
	{
		// clean up device info list
        {
            wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceInfoVecMutex);
            while( m_DeviceInfoVec.size() )
            {
                DeviceInfo* devInfo = m_DeviceInfoVec.back();
                m_DeviceInfoVec.pop_back();
                delete devInfo;
            }
        }
		delete m_CurrentDevice;

	}
	catch (...)
	{
		//destructors should absorb exceptions, no harm in logging though!!
		DEBUG_MSG ("Exception during destructor");
	}
}
Exemple #5
0
    QCDiskQueue::CloseFileStatus
QCDiskQueue::Queue::CloseFile(
    QCDiskQueue::FileIdx inFileIdx,
    int64_t              inFileSize)
{
    QCStMutexLocker theLock(mMutex);
    if (inFileIdx < 0 || inFileIdx >= mFileCount || mFdPtr[inFileIdx] < 0) {
        return CloseFileStatus(kErrorParameter, 0);
    }
    if (mFilePendingReqCountPtr[inFileIdx] > 0) {
        return CloseFileStatus(kErrorHasPendingRequests, 0);
    }
    int theSysErr = 0;
    const int theFd = mFdPtr[inFileIdx];
    for (int i = inFileIdx + mFileCount; i < mFdCount; i += mFileCount) {
        if (close(mFdPtr[i])) {
            theSysErr = errno ? errno : -1;
        }
        mFdPtr[i] = -1;
    }
    mFdPtr[inFileIdx] = mFreeFdHead;
    mFreeFdHead = -(inFileIdx + kFreeFdOffset);
    theLock.Unlock();
    if (theFd >= 0) {
        if (inFileSize >= 0 && inFileSize < mBlockSize *
                    int64_t(mFileInfoPtr[inFileIdx].mLastBlockIdx) &&
                ftruncate(theFd, (off_t)inFileSize)) {
            theSysErr = errno ? errno : -1;
        }
        if (close(theFd)) {
            theSysErr = errno ? errno : -1;
        }
    }
    return CloseFileStatus(theSysErr ? kErrorClose : kErrorNone, theSysErr);
}
Exemple #6
0
 void Insert(
     QCThread& inThread)
 {
     QCStMutexLocker theLock(mMutex);
     ThreadList::Insert(inThread, ThreadList::GetPrev(mHead));
     mCount++;
 }
Exemple #7
0
 CompletionStatus Wait()
 {
     QCStMutexLocker theLock(mMutex);
     while (! mDoneFlag) {
         mDoneCond.Wait(mMutex);
     }
     return mCompletionStatus;
 }
Exemple #8
0
    QCDiskQueue::OpenFileStatus
QCDiskQueue::Queue::OpenFile(
    const char* inFileNamePtr,
    int64_t     inMaxFileSize,
    bool        inReadOnlyFlag,
    bool        inAllocateFileSpaceFlag,
    bool        inCreateFlag)
{
    QCStMutexLocker theLock(mMutex);
    if (mFreeFdHead == kFreeFdEnd) {
        return OpenFileStatus(-1, kErrorFileIdxOutOfRange, 0);
    }
    const int theIdx = -mFreeFdHead - kFreeFdOffset;
    QCRTASSERT(
        theIdx >= 0 && theIdx < mFileCount && mFdPtr[theIdx] <= kFreeFdEnd);
    mFreeFdHead = mFdPtr[theIdx];
    int theSysErr = 0;
    for (int i = theIdx; i < mFdCount; i += mFileCount) {
        const int theFd = open(inFileNamePtr,
            kOpenCommonFlags | (inCreateFlag ? O_CREAT : 0) |
                (inReadOnlyFlag ? O_RDONLY : O_RDWR),
            S_IRUSR | S_IWUSR);
        if (theFd < 0 || fcntl(theFd, FD_CLOEXEC, 1)) {
            theSysErr = errno ? errno : -1;
            break;
        }
        mFdPtr[i] = theFd;
        if (i >= mFileCount) {
            continue;
        }
        const off_t theSize = lseek(theFd, 0, SEEK_END);
        if (theSize < 0) {
            theSysErr = errno;
            break;
        }
        mFilePendingReqCountPtr[i] = 0;
        const int64_t theBlkIdx =
            (int64_t(inMaxFileSize < 0 ? theSize : inMaxFileSize) +
                mBlockSize - 1) / mBlockSize;
        if (theBlkIdx >= (int64_t(1) << kBlockBitCount)) {
            theSysErr = EOVERFLOW;
            break;
        }
        mFileInfoPtr[i].mLastBlockIdx = theBlkIdx;
        mFileInfoPtr[i].mSpaceAllocPendingFlag = inAllocateFileSpaceFlag &&
            ! inReadOnlyFlag && inMaxFileSize > 0 && theSize < inMaxFileSize;
    }
    if (! theSysErr) {
        return OpenFileStatus(theIdx, kErrorNone, theSysErr);
    }
    for (int i = theIdx; i < mFdCount; i += mFileCount) {
        close(mFdPtr[i]);
        mFdPtr[i] = -1;
    }
    mFdPtr[theIdx] = mFreeFdHead;
    mFreeFdHead = -(theIdx + kFreeFdOffset);
    return OpenFileStatus(-1, kErrorOpen, theSysErr);
}
/*static*/
void VCacheLog::Destroy()
{
	if(s_cacheLog != NULL)
	{
		VTaskLock		theLock(&s_mutex);
		
		delete s_cacheLog;
		s_cacheLog = NULL;
	}
}
Exemple #10
0
 void GetPendingCount(
     int&     outFreeRequestCount,
     int&     outRequestCount,
     int64_t& outReadBlockCount,
     int64_t& outWriteBlockCount)
 {
     QCStMutexLocker theLock(mMutex);
     outFreeRequestCount = mFreeCount;
     outRequestCount     = mPendingCount;
     outReadBlockCount   = mPendingReadBlockCount;
     outWriteBlockCount  = mPendingWriteBlockCount;
 }
/*static*/
VCacheLog * VCacheLog::Get()
{
	if(s_cacheLog == NULL)
	{
		VTaskLock		theLock(&s_mutex);
		if(s_cacheLog == NULL)
		{
			s_cacheLog = new VCacheLog;
		}
	}

	return s_cacheLog;
}
Exemple #12
0
    bool
QCDiskQueue::Queue::Cancel(
    QCDiskQueue::RequestId inRequestId)
{
    QCStMutexLocker theLock(mMutex);
    return (
        mPendingCount > 0 &&
        inRequestId >= kRequestQueueCount &&
        inRequestId < mTotalCount &&
        ! mRequestsPtr[inRequestId].mInFlightFlag &&
        Cancel(mRequestsPtr[inRequestId])
    );
}
Exemple #13
0
QCDiskQueue::Status
QCDiskQueue::Queue::UnReserveFileSpace(QCDiskQueue::FileIdx inFileIdx, 
    off_t inStartOffset, off_t inLen)
{
    QCStMutexLocker theLock(mMutex);
    if (! mRunFlag) {
        return Status(kErrorQueueStopped);
    }
    if (inFileIdx < 0 || inFileIdx >= mFileCount || mFdPtr[inFileIdx] < 0) {
        return Status(kErrorFileIdxOutOfRange);
    }
    QCUtils::UnReserveFileSpace(mFdPtr[inFileIdx], inStartOffset, inLen);
    return Status(kErrorNone);
}
Exemple #14
0
    QCDiskQueue::Status
QCDiskQueue::Queue::AllocateFileSpace(
    QCDiskQueue::FileIdx inFileIdx)
{
    QCStMutexLocker theLock(mMutex);
    if (! mRunFlag) {
        return Status(kErrorQueueStopped);
    }
    if (inFileIdx < 0 || inFileIdx >= mFileCount || mFdPtr[inFileIdx] < 0) {
        return Status(kErrorFileIdxOutOfRange);
    }
    mFileInfoPtr[inFileIdx].mSpaceAllocPendingFlag = true;
    return Status(kErrorNone);
}
WTErr WCMRAudioDeviceManager::GetDeviceInfoByName(const std::string & nameToMatch, DeviceInfo & devInfo) const
{
    wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceInfoVecMutex);
	DeviceInfoVecConstIter iter = m_DeviceInfoVec.begin();
	for (; iter != m_DeviceInfoVec.end(); ++iter)
	{
		if (nameToMatch == (*iter)->m_DeviceName)
        {
			devInfo = *(*iter);
            return eNoErr;
        }
	}

	return eRMResNotFound;
}
Exemple #16
0
 virtual bool Done(
     RequestId      inRequestId,
     FileIdx        inFileIdx,
     BlockIdx       inStartBlockIdx,
     InputIterator& inBufferItr,
     int            inBufferCount,
     Error          inCompletionCode,
     int            inSysErrorCode,
     int64_t        inIoByteCount)
 {
     QCStMutexLocker theLock(mMutex);
     mDoneFlag = true;
     mCompletionStatus =
         CompletionStatus(inCompletionCode, inSysErrorCode, inIoByteCount);
     CopyBufs(&inBufferItr, inBufferCount);
     mDoneCond.Notify();
     return true;
 }
Exemple #17
0
    QCDiskQueue::EnqueueStatus
QCDiskQueue::Queue::Sync(
    QCDiskQueue::FileIdx       inFileIdx,
    QCDiskQueue::IoCompletion* inIoCompletionPtr,
    QCDiskQueue::Time          inTimeWaitNanoSec)
{
    QCStMutexLocker theLock(mMutex);
    if (! mRunFlag) {
        return EnqueueStatus(kRequestIdNone, kErrorQueueStopped);
    }
    if (inFileIdx < 0 || inFileIdx >= mFileCount || mFdPtr[inFileIdx] < 0) {
        return EnqueueStatus(kRequestIdNone, kErrorFileIdxOutOfRange);
    }
    Request* theReqPtr;
    if (! (theReqPtr = Get(0))) {
        QCStValueIncrementor<int> theIncr(mReqWaitersCount, 1);
        if (inTimeWaitNanoSec < 0) {
            mFreeReqCond.Wait(mMutex);
        } else if (inTimeWaitNanoSec == 0 ||
                ! mFreeReqCond.Wait(mMutex, inTimeWaitNanoSec)) {
            if (inTimeWaitNanoSec != 0) {
                theLock.Detach();
            }
            return EnqueueStatus(kRequestIdNone, kErrorOutOfRequests);
        }
    }
    QCASSERT(theReqPtr);
    // FIXME: implement real io barrier, for now just queue empty read request.
    Request& theReq = *theReqPtr;
    theReq.mReqType         = kReqTypeRead;
    theReq.mBufferCount     = 0;
    theReq.mFileIdx         = inFileIdx;
    theReq.mBlockIdx        = 0;
    theReq.mIoCompletionPtr = inIoCompletionPtr;
    char** const theBufsPtr = GetBuffersPtr(theReq);
    theBufsPtr[0] = 0;
    return EnqueueStatus(kErrorNone);
}
Exemple #18
0
    /* virtual */ void
QCDiskQueue::Queue::Run(
    int inThreadIndex)
{
    QCStMutexLocker theLock(mMutex);
    QCASSERT(inThreadIndex >= 0 && inThreadIndex < mThreadCount);
    int* const          theFdPtr    = mFdPtr +
        mFdCount / mThreadCount * inThreadIndex;
    struct iovec* const theIoVecPtr = mIoVecPtr +
        mIoVecPerThreadCount * inThreadIndex;
    while (mRunFlag) {
        Request* theReqPtr;
        while (! (theReqPtr = Dequeue()) && mRunFlag) {
            mWorkCond.Wait(mMutex);
        }
        if (mRunFlag) {
            QCASSERT(theReqPtr);
            Process(*theReqPtr, theFdPtr, theIoVecPtr);
        } else if (theReqPtr) {
            Cancel(*theReqPtr);
        }
    }
}
Exemple #19
0
    QCDiskQueue::IoCompletion*
QCDiskQueue::Queue::CancelOrSetCompletionIfInFlight(
    QCDiskQueue::RequestId     inRequestId,
    QCDiskQueue::IoCompletion* inCompletionIfInFlightPtr)
{
    QCStMutexLocker theLock(mMutex);
    if (mPendingCount <= 0 ||
            inRequestId < kRequestQueueCount ||
            inRequestId >= mTotalCount) {
        return 0;
    }
    Request& theReq = mRequestsPtr[inRequestId];
    if (theReq.mReqType == kReqTypeNone) {
        // Completion is already running, or done.
        return theReq.mIoCompletionPtr;
    }
    if (! theReq.mInFlightFlag) {
        IoCompletion* const theIoCompletionPtr = theReq.mIoCompletionPtr;
        return (Cancel(theReq) ? theIoCompletionPtr : 0);
    }
    // In flight, change io completion.
    theReq.mIoCompletionPtr = inCompletionIfInFlightPtr;
    return inCompletionIfInFlightPtr;
}
Exemple #20
0
 void Stop()
 {
     QCStMutexLocker theLock(mMutex);
     StopSelf();
 }
const DeviceInfoVec WCMRAudioDeviceManager::DeviceInfoList() const
{
    wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceInfoVecMutex);
	return m_DeviceInfoVec;
}
Exemple #22
0
 int GetThreadCount()
 {
     QCStMutexLocker theLock(mMutex);
     return mCount;
 }
Exemple #23
0
void ZCnd_boost::Wait(boost::mutex& iMtx)
	{
	boost::mutex::scoped_lock theLock(iMtx, boost::adopt_lock);
	condition_variable::wait(theLock);
	}
Exemple #24
0
    void
QCDiskQueue::Queue::Process(
    Request&      inReq,
    int*          inFdPtr,
    struct iovec* inIoVecPtr)
{
    QCASSERT(mMutex.IsOwned());
    QCASSERT(mIoVecPerThreadCount > 0 && mBufferPoolPtr);
    QCRTASSERT(//mFileInfoPtr[inReq.mFileIdx].mLastBlockIdx >= 0 &&
        inReq.mBlockIdx + inReq.mBufferCount <=
        uint64_t(mFileInfoPtr[inReq.mFileIdx].mLastBlockIdx));

    const int     theFd        = inFdPtr[inReq.mFileIdx];
    char** const  theBufPtr    = GetBuffersPtr(inReq);
    const off_t   theOffset    = (off_t)inReq.mBlockIdx * mBlockSize;
    const bool    theReadFlag  = inReq.mReqType == kReqTypeRead;
    const int64_t theAllocSize = (inReq.mReqType == kReqTypeWrite &&
        mFileInfoPtr[inReq.mFileIdx].mSpaceAllocPendingFlag) ?
            mFileInfoPtr[inReq.mFileIdx].mLastBlockIdx * mBlockSize : 0;
    QCASSERT((theReadFlag || inReq.mReqType == kReqTypeWrite) && theFd >= 0);
    inReq.mInFlightFlag = true;

    QCStMutexUnlocker theUnlock(mMutex);

    Error theError    = kErrorNone;
    int   theSysError = 0;
    if (theAllocSize > 0) {
        // Theoretically space allocation can be simultaneously invoked from
        // more than one io thread. This is to ensure that allocation always
        // happen before the first write.
        // OS can deal with concurrent allocations.
        const int64_t theResv = QCUtils::ReserveFileSpace(theFd, theAllocSize);
        if (theResv < 0) {
            theError = kErrorSpaceAlloc;
            theSysError = int(-theResv);
        }
        if (theResv > 0 && ftruncate(theFd, theAllocSize)) {
            theError = kErrorSpaceAlloc;
            theSysError = errno;
        }
        if (theError == kErrorNone) {
            QCStMutexLocker theLock(mMutex);
            mFileInfoPtr[inReq.mFileIdx].mSpaceAllocPendingFlag = false;
        }
    }

    const bool theGetBufFlag = ! theBufPtr[0];
    if (theError == kErrorNone && theGetBufFlag) {
        QCASSERT(theReadFlag);
        BuffersIterator theIt(*this, inReq, inReq.mBufferCount);
        // Allocate buffers for read request.
        if (! mBufferPoolPtr->Get(theIt, inReq.mBufferCount,
                QCIoBufferPool::kRefillReqIdRead)) {
            theError = kErrorOutOfBuffers;
        }
    }
    if (theError == kErrorNone &&
            lseek(theFd, theOffset, SEEK_SET) != theOffset) {
        theError    = kErrorSeek;
        theSysError = errno;
    }
    BuffersIterator theItr(*this, inReq, inReq.mBufferCount);
    int             theBufCnt    = inReq.mBufferCount;
    int64_t         theIoByteCnt = 0;
    while (theBufCnt > 0 && theError == kErrorNone) {
        ssize_t theIoBytes  = 0;
        int     theIoVecCnt = 0;
        char*   thePtr;
        while (theIoVecCnt < mIoVecPerThreadCount && (thePtr = theItr.Get())) {
            inIoVecPtr[theIoVecCnt  ].iov_base = thePtr;
            inIoVecPtr[theIoVecCnt++].iov_len  = mBlockSize;
            theIoBytes += mBlockSize;
            theBufCnt--;
        }
        QCRTASSERT(theIoVecCnt > 0);
        if (theReadFlag) {
            const ssize_t theNRd = readv(theFd, inIoVecPtr, theIoVecCnt);
            if (theNRd < 0) {
                theError = kErrorRead;
                theSysError = theNRd < 0 ? errno : 0;
                break;
            }
            theIoByteCnt += theNRd;
            if (theNRd < theIoBytes) {
                if (theGetBufFlag) {
                    // Short read -- release extra buffers.
                    mBufferPoolPtr->Put(theItr, theBufCnt);
                    inReq.mBufferCount -= theBufCnt;
                    int i = (theNRd + mBlockSize - 1) / mBlockSize;
                    inReq.mBufferCount -= theIoVecCnt - i;
                    while (i < theIoVecCnt) {
                        mBufferPoolPtr->Put((char*)inIoVecPtr[i++].iov_base);
                    }
                }
                break;
            }
        } else {
            const ssize_t theNWr = writev(theFd, inIoVecPtr, theIoVecCnt);
            if (theNWr > 0) {
                theIoByteCnt += theNWr;
            }
            if (theNWr != theIoBytes) {
                theError = kErrorWrite;
                theSysError = errno;
                break;
            }
        }
    }
    if (theGetBufFlag && theError != kErrorNone && theBufPtr[0]) {
        BuffersIterator theIt(*this, inReq, inReq.mBufferCount);
        mBufferPoolPtr->Put(theIt, inReq.mBufferCount);
        theBufPtr[0] = 0;
    }
    theUnlock.Lock();
    RequestComplete(inReq, theError, theSysError, theIoByteCnt, theGetBufFlag);
}
Exemple #25
0
    int
QCDiskQueue::Queue::Start(
    int             inThreadCount,
    int             inMaxQueueDepth,
    int             inMaxBuffersPerRequestCount,
    int             inFileCount,
    const char**    inFileNamesPtr,
    QCIoBufferPool& inBufferPool)
{
    QCStMutexLocker theLock(mMutex);
    StopSelf();
    if (inFileCount <= 0 || inThreadCount <= 0 ||
            inThreadCount <= 0 || inMaxQueueDepth <= 0 ||
            inMaxBuffersPerRequestCount <= 0) {
        return 0;
    }
    if (inFileCount >= (1 << kFileIndexBitCount)) {
        return EINVAL;
    }
    mBufferPoolPtr = &inBufferPool;
#ifdef IOV_MAX
    const int kMaxIoVecCount = IOV_MAX;
#else
    const int kMaxIoVecCount = 1 << 10;
#endif
    mIoVecPerThreadCount = inMaxBuffersPerRequestCount;
    if (mIoVecPerThreadCount > kMaxIoVecCount) {
        mIoVecPerThreadCount = kMaxIoVecCount;
    }
    mFileCount = inFileCount;
    mIoVecPtr = new struct iovec[mIoVecPerThreadCount * inThreadCount];
    mBlockSize = inBufferPool.GetBufferSize();
    const int theFdCount = inThreadCount * mFileCount;
    mFdPtr = new int[theFdCount];
    mFilePendingReqCountPtr = new unsigned int[mFileCount];
    mFileInfoPtr = new FileInfo[mFileCount];
    mFreeFdHead = kFreeFdEnd;
    for (mFdCount = 0; mFdCount < theFdCount; ) {
        int theError = 0;
        for (int i = 0; i < mFileCount; i++) {
            int& theFd = mFdPtr[mFdCount];
            theFd = inFileNamesPtr ?
                open(inFileNamesPtr[i], kOpenCommonFlags | O_RDWR) : -1;
            if (theFd < 0 && inFileNamesPtr) {
                theError = errno;
                break;
            }
            if (theFd >= 0 && fcntl(theFd, FD_CLOEXEC, 1)) {
                theError = errno;
                break;
            }
            if (++mFdCount > mFileCount) {
                continue;
            }
            const off_t theSize = theFd >= 0 ? lseek(theFd, 0, SEEK_END) : 0;
            if (theSize < 0) {
                theError = errno;
                break;
            }
            mFilePendingReqCountPtr[i] = 0;
            // Allow last partial block.
            const int64_t theBlkIdx =
                (int64_t(theSize) + mBlockSize - 1) / mBlockSize;
            if (theBlkIdx >= (int64_t(1) << kBlockBitCount)) {
                theError = EOVERFLOW;
                break;
            }
            mFileInfoPtr[i].mLastBlockIdx          = theBlkIdx;
            mFileInfoPtr[i].mSpaceAllocPendingFlag = false;
            if (theFd < 0) {
                theFd = mFreeFdHead;
                mFreeFdHead = -(i + kFreeFdOffset);
            }
        }
        if (theError) {
            StopSelf();
            return theError;
        }
    }
    mBuffersPtr = new char*[inMaxQueueDepth * inMaxBuffersPerRequestCount];
    mRequestBufferCount = inMaxBuffersPerRequestCount;
    const int theReqCnt = kRequestQueueCount + inMaxQueueDepth;
    mRequestsPtr = new Request[theReqCnt];
    // Init list heads: kFreeQueueIdx kIoQueueIdx.
    for (mTotalCount = 0; mTotalCount < kRequestQueueCount; mTotalCount++) {
        Init(mRequestsPtr[mTotalCount]);
    }
    // Make free list.
    for (; mTotalCount < theReqCnt; mTotalCount++) {
        Request& theReq = mRequestsPtr[mTotalCount];
        Init(theReq);
        Put(theReq);
    }
    mThreadsPtr = new IoThread[inThreadCount];
    mRunFlag    = true;
    const int         kStackSize = 32 << 10;
    const char* const kNamePtr   = "IO";
    for (mThreadCount = 0; mThreadCount < inThreadCount; mThreadCount++) {
        const int theRet = mThreadsPtr[mThreadCount].Start(
            *this, mThreadCount, kStackSize, kNamePtr);
        if (theRet != 0) {
            StopSelf();
            return theRet;
        }
    }
    return 0;
}
Exemple #26
0
    QCDiskQueue::EnqueueStatus
QCDiskQueue::Queue::Enqueue(
    QCDiskQueue::ReqType        inReqType,
    QCDiskQueue::FileIdx        inFileIdx,
    QCDiskQueue::BlockIdx       inBlockIdx,
    QCDiskQueue::InputIterator* inBufferIteratorPtr,
    int                         inBufferCount,
    QCDiskQueue::IoCompletion*  inIoCompletionPtr,
    QCDiskQueue::Time           inTimeWaitNanoSec)
{
    if ((inReqType != kReqTypeRead && inReqType != kReqTypeWrite) ||
            inBufferCount <= 0 ||
            inBufferCount > (mRequestBufferCount *
                (mTotalCount - kRequestQueueCount)) ||
            (! inBufferIteratorPtr && inReqType == kReqTypeWrite)) {
        return EnqueueStatus(kRequestIdNone, kErrorParameter);
    }
    QCStMutexLocker theLock(mMutex);
    if (! mRunFlag) {
        return EnqueueStatus(kRequestIdNone, kErrorQueueStopped);
    }
    if (inFileIdx < 0 || inFileIdx >= mFileCount || mFdPtr[inFileIdx] < 0) {
        return EnqueueStatus(kRequestIdNone, kErrorFileIdxOutOfRange);
    }
    if (inBlockIdx < 0 ||
            inBlockIdx + (inBufferIteratorPtr ? 0 : inBufferCount) >
            int64_t(mFileInfoPtr[inFileIdx].mLastBlockIdx)) {
        return EnqueueStatus(kRequestIdNone, kErrorBlockIdxOutOfRange);
    }
    Request* theReqPtr;
    while (! (theReqPtr = Get(inBufferCount))) {
        QCStValueIncrementor<int> theIncr(mReqWaitersCount, 1);
        if (inTimeWaitNanoSec < 0) {
            mFreeReqCond.Wait(mMutex);
        } else if (inTimeWaitNanoSec == 0 ||
                ! mFreeReqCond.Wait(mMutex, inTimeWaitNanoSec)) {
            if (inTimeWaitNanoSec != 0) {
                theLock.Detach();
            }
            return EnqueueStatus(kRequestIdNone, kErrorOutOfRequests);
        }
    }
    QCASSERT(theReqPtr);
    Request& theReq = *theReqPtr;
    theReq.mReqType         = inReqType;
    theReq.mBufferCount     = 0;
    theReq.mFileIdx         = inFileIdx;
    theReq.mBlockIdx        = inBlockIdx;
    theReq.mIoCompletionPtr = inIoCompletionPtr;
    if (inBufferIteratorPtr) {
        BuffersIterator theItr(*this, theReq, inBufferCount);
        for (int i = 0; i < inBufferCount; i++) {
            char* const thePtr = inBufferIteratorPtr->Get();
            if (! thePtr) {
                break;
            }
            theItr.Put(thePtr);
            theReq.mBufferCount++;
        }
        if (theReq.mBufferCount < inBufferCount) {
            // Free unused requests if any.
            TrimRequestList(theReq, theReq.mBufferCount);
        }
    } else if (inReqType == kReqTypeRead) {
        // Defer buffer allocation.
        GetBuffersPtr(theReq)[0] = 0;
        theReq.mBufferCount = inBufferCount;
    }
    if (theReq.mBlockIdx + theReq.mBufferCount >
            uint64_t(mFileInfoPtr[theReq.mFileIdx].mLastBlockIdx)) {
        Put(theReq);
        return EnqueueStatus(kRequestIdNone, kErrorBlockIdxOutOfRange);
    }
    if (theReq.mBufferCount <= 0) {
        Put(theReq);
        return EnqueueStatus(kRequestIdNone, kErrorBlockCountOutOfRange);
    }
    Enqueue(theReq);
    mWorkCond.Notify();
    return GetRequestId(theReq);
}