void CARBON_GUI::msgOut(char *txt) { ItemCount nLines=0; SInt32 sLines; Handle oldText = NULL; TXNOffset start = 0; TXNOffset end = 0; TXNDataType dType; UniChar *p; int off = 0; statusLock(); if(txt && statusText) { TXNGetLineCount(statusText,&nLines); if(nLines > CGUI_STATUS_MAX_LINES) { TXNControlTag iControlTags[1] = { kTXNAutoScrollBehaviorTag }; TXNControlData iControlData[1] = { kTXNAutoScrollNever }; //kTXNAutoScrollWhenInsertionVisible }; err = TXNSetTXNObjectControls(statusText,false,1,iControlTags,iControlData); TXNTypeAttributes attr = { kTXNTextEncodingAttribute,kTXNTextEncodingAttributeSize,{0} }; //TXNGetIndexedRunInfoFromRange(statusText,0,kTXNStartOffset,kTXNEndOffset,&start,&end,&dType,1,&attr); if(TXNGetData(statusText,kTXNStartOffset,kTXNEndOffset,&oldText) != noErr) msg->error("Can't get status text buffer!! (%d)\n"); end = TXNDataSize(statusText); p = (UniChar *)*oldText; while(*((*oldText)+off) != '\n' && off < end) { off++; } p++; off++; //off = 256; TXNSetData(statusText,kTXNTextData,"",0,kTXNStartOffset,off/sizeof(UniChar)); /* if(end > off) TXNSetData(statusText,kTXNUnicodeTextData,(*oldText)+off,end-off,kTXNStartOffset,kTXNEndOffset); */ //err = TXNScroll(statusText,kTXNScrollUnitsInLines,kTXNScrollUnitsInLines,&nLines,&nCols); } TXNSetData(statusText,kTXNTextData,"[*] ",4,kTXNEndOffset,kTXNEndOffset); TXNSetData(statusText,kTXNTextData,txt,strlen(txt),kTXNEndOffset,kTXNEndOffset); TXNSetData(statusText,kTXNTextData,"\n",1,kTXNEndOffset,kTXNEndOffset); } if(oldText) DisposeHandle(oldText); statusUnlock(); }
// returning uint64_t(-1) means error uint64_t ChunkBuffer::fill() { UniqueLock statusLock(&this->statusMutex); while (this->status != ReadyToFill) { pthread_cond_wait(&this->statusCondVar, &this->statusMutex); } if (S3QueryIsAbortInProgress() || this->isError()) { this->setSharedError(true); this->status = ReadyToRead; pthread_cond_signal(&this->statusCondVar); return -1; } uint64_t offset = this->curFileOffset; uint64_t leftLen = this->chunkDataSize; uint64_t readLen = 0; if (leftLen != 0) { try { readLen = this->s3Interface->fetchData(offset, this->chunkData, leftLen, this->s3Url); if (readLen != leftLen) { S3DEBUG("Failed to fetch expected data from S3"); this->setSharedError(true, S3PartialResponseError(leftLen, readLen)); } else { S3DEBUG("Got %" PRIu64 " bytes from S3", readLen); } } catch (S3Exception& e) { S3DEBUG("Failed to fetch expected data from S3"); this->setSharedError(true); } } if (offset + leftLen >= offsetMgr.getKeySize()) { readLen = 0; // Nothing to read, EOF S3DEBUG("Reached the end of file"); this->eof = true; } this->status = ReadyToRead; pthread_cond_signal(&this->statusCondVar); return (this->isError()) ? -1 : readLen; }
// ret < len means EMPTY // that's why it checks if leftLen is larger than *or equal to* len below[1], provides a chance ret // is 0, which is smaller than len. Otherwise, other functions won't know when to read next buffer. uint64_t ChunkBuffer::read(char* buf, uint64_t len) { // GPDB abort signal stops s3_import(), this check is not needed if s3_import() every time calls // ChunkBuffer->Read() only once, otherwise(as we did in downstreamReader->read() for // decompression feature before), first call sets buffer to ReadyToFill, second call hangs. S3_CHECK_OR_DIE(!S3QueryIsAbortInProgress(), S3QueryAbort, ""); UniqueLock statusLock(&this->statusMutex); while (this->status != ReadyToRead) { pthread_cond_wait(&this->statusCondVar, &this->statusMutex); } // Error is shared between all chunks. if (this->isError()) { return 0; } uint64_t leftLen = this->chunkDataSize - this->curChunkOffset; uint64_t lenToRead = std::min(len, leftLen); if (lenToRead != 0) { memcpy(buf, this->chunkData.data() + this->curChunkOffset, lenToRead); } if (len <= leftLen) { // [1] this->curChunkOffset += lenToRead; // not empty } else { // empty, reset everything this->curChunkOffset = 0; if (!this->isEOF()) { // Release chunkData memory to reduce consumption. this->chunkData.release(); this->status = ReadyToFill; Range range = this->offsetMgr.getNextOffset(); this->curFileOffset = range.offset; this->chunkDataSize = range.length; pthread_cond_signal(&this->statusCondVar); } } return lenToRead; }
void WorkerPool::interruptRange(std::size_t inBegin, std::size_t inCount) { LockMany<Mutex> locker; // // Lock all workers. // for (std::size_t idx = inBegin; idx != inBegin + inCount; ++idx) { Worker & worker = *mWorkers[idx]; locker.lock(worker.mQueueMutex); // Keep queue locked for now. } // // Clear queues and interrupt the work. // for (std::size_t idx = inBegin; idx != inBegin + inCount; ++idx) { Worker & worker = *mWorkers[idx]; worker.mQueue.clear(); worker.interrupt(false); // NOTE: don't wait here, because that would be wasteful. } // // Wait until all workers are ready. // for (std::size_t idx = inBegin; idx != inBegin + inCount; ++idx) { Worker & worker = *mWorkers[idx]; ScopedLock statusLock(worker.mStatusMutex); if (worker.mStatus == WorkerStatus_Working) { worker.mStatusCondition.wait(statusLock); } } }