void Win32AsyncFile::appendReq(Request * request){ const char * buf = request->par.append.buf; Uint32 size = Uint32(request->par.append.size); m_write_wo_sync += size; DWORD dwWritten = 0; while(size > 0){ if(!WriteFile(hFile, buf, size, &dwWritten, 0)){ request->error = GetLastError(); return ; } buf += dwWritten; size -= dwWritten; } if((m_auto_sync_freq && m_write_wo_sync > m_auto_sync_freq) || m_always_sync) { syncReq(request); } }
void AsyncFile::closeReq(Request * request) { if (m_open_flags & ( FsOpenReq::OM_WRITEONLY | FsOpenReq::OM_READWRITE | FsOpenReq::OM_APPEND )) { syncReq(request); } #ifdef NDB_WIN32 if(!CloseHandle(hFile)) { request->error = GetLastError(); } hFile = INVALID_HANDLE_VALUE; #else if (-1 == ::close(theFd)) { #ifndef DBUG_OFF if (theFd == -1) { DEBUG(ndbout_c("close on fd = -1")); abort(); } #endif request->error = errno; } theFd = -1; #endif }
void AsyncFile::writeReq( Request * request) { int page_num = 0; bool write_not_complete = true; while(write_not_complete) { int totsize = 0; off_t offset = request->par.readWrite.pages[page_num].offset; char* bufptr = theWriteBuffer; write_not_complete = false; if (request->par.readWrite.numberOfPages > 1) { off_t page_offset = offset; // Multiple page write, copy to buffer for one write for(int i=page_num; i < request->par.readWrite.numberOfPages; i++) { memcpy(bufptr, request->par.readWrite.pages[i].buf, request->par.readWrite.pages[i].size); bufptr += request->par.readWrite.pages[i].size; totsize += request->par.readWrite.pages[i].size; if (((i + 1) < request->par.readWrite.numberOfPages)) { // There are more pages to write // Check that offsets are consequtive off_t tmp = page_offset + request->par.readWrite.pages[i].size; if (tmp != request->par.readWrite.pages[i+1].offset) { // Next page is not aligned with previous, not allowed DEBUG(ndbout_c("Page offsets are not aligned")); request->error = EINVAL; return; } if ((unsigned)(totsize + request->par.readWrite.pages[i+1].size) > (unsigned)theWriteBufferSize) { // We are not finished and the buffer is full write_not_complete = true; // Start again with next page page_num = i + 1; break; } } page_offset += request->par.readWrite.pages[i].size; } bufptr = theWriteBuffer; } else { // One page write, write page directly bufptr = request->par.readWrite.pages[0].buf; totsize = request->par.readWrite.pages[0].size; } int err = writeBuffer(bufptr, totsize, offset); if(err != 0){ request->error = err; return; } } // while(write_not_complete) if(m_auto_sync_freq && m_write_wo_sync > m_auto_sync_freq){ syncReq(request); } }
void Win32AsyncFile::closeReq(Request * request) { if (m_open_flags & ( FsOpenReq::OM_WRITEONLY | FsOpenReq::OM_READWRITE | FsOpenReq::OM_APPEND )) { syncReq(request); } if(!CloseHandle(hFile)) { request->error = GetLastError(); } hFile = INVALID_HANDLE_VALUE; }
void AsyncFile::appendReq(Request * request){ const char * buf = request->par.append.buf; Uint32 size = request->par.append.size; m_write_wo_sync += size; #ifdef NDB_WIN32 DWORD dwWritten = 0; while(size > 0){ if(!WriteFile(hFile, buf, size, &dwWritten, 0)){ request->error = GetLastError(); return ; } buf += dwWritten; size -= dwWritten; } #else while(size > 0){ const int n = write(theFd, buf, size); if(n == -1 && errno == EINTR){ continue; } if(n == -1){ request->error = errno; return; } if(n == 0){ DEBUG(ndbout_c("append with n=0")); abort(); } size -= n; buf += n; } #endif if(m_auto_sync_freq && m_write_wo_sync > m_auto_sync_freq){ syncReq(request); } }
void AsyncFile::closeReq(Request * request) { syncReq(request); #ifdef NDB_WIN32 if(!CloseHandle(hFile)) { request->error = GetLastError(); } hFile = INVALID_HANDLE_VALUE; #else if (-1 == ::close(theFd)) { #ifndef DBUG_OFF if (theFd == -1) abort(); #endif request->error = errno; } theFd = -1; #endif }
void AsyncFile::appendReq(Request * request){ const char * buf = request->par.append.buf; Uint32 size = request->par.append.size; m_syncCount += size; #ifdef NDB_WIN32 DWORD dwWritten = 0; while(size > 0){ if(!WriteFile(hFile, buf, size, &dwWritten, 0)){ request->error = GetLastError(); return ; } buf += dwWritten; size -= dwWritten; } #else while(size > 0){ const int n = write(theFd, buf, size); if(n == -1 && errno == EINTR){ continue; } if(n == -1){ request->error = errno; return; } if(n == 0){ abort(); } size -= n; buf += n; } #endif if(m_syncFrequency != 0 && m_syncCount > m_syncFrequency){ syncReq(request); } }
void AsyncFile::run() { Request *request; // Create theMemoryChannel in the thread that will wait for it NdbMutex_Lock(theStartMutexPtr); theMemoryChannelPtr = new MemoryChannel<Request>(); theStartFlag = true; // Create write buffer for bigger writes theWriteBufferSize = WRITEBUFFERSIZE; theWriteBufferUnaligned = (char *) ndbd_malloc(theWriteBufferSize + NDB_O_DIRECT_WRITE_ALIGNMENT-1); theWriteBuffer = (char *) (((UintPtr)theWriteBufferUnaligned + NDB_O_DIRECT_WRITE_ALIGNMENT - 1) & ~(UintPtr)(NDB_O_DIRECT_WRITE_ALIGNMENT - 1)); NdbMutex_Unlock(theStartMutexPtr); NdbCondition_Signal(theStartConditionPtr); if (!theWriteBuffer) { DEBUG(ndbout_c("AsyncFile::writeReq, Failed allocating write buffer")); return; }//if while (1) { request = theMemoryChannelPtr->readChannel(); if (!request) { DEBUG(ndbout_c("Nothing read from Memory Channel in AsyncFile")); endReq(); return; }//if m_current_request= request; switch (request->action) { case Request:: open: openReq(request); break; case Request:: close: closeReq(request); break; case Request:: closeRemove: closeReq(request); removeReq(request); break; case Request:: readPartial: case Request:: read: readReq(request); break; case Request:: readv: readvReq(request); break; case Request:: write: writeReq(request); break; case Request:: writev: writevReq(request); break; case Request:: writeSync: writeReq(request); syncReq(request); break; case Request:: writevSync: writevReq(request); syncReq(request); break; case Request:: sync: syncReq(request); break; case Request:: append: appendReq(request); break; case Request:: append_synch: appendReq(request); syncReq(request); break; case Request::rmrf: rmrfReq(request, (char*)theFileName.c_str(), request->par.rmrf.own_directory); break; case Request:: end: if (theFd > 0) closeReq(request); endReq(); return; default: DEBUG(ndbout_c("Invalid Request")); abort(); break; }//switch m_last_request= request; m_current_request= 0; // No need to signal as ndbfs only uses tryRead theReportTo->writeChannelNoSignal(request); }//while }//AsyncFile::run()
NS_IMETHODIMP nsDNSService::Resolve(const nsACString &hostname, PRUint32 flags, nsIDNSRecord **result) { // grab reference to global host resolver and IDN service. beware // simultaneous shutdown!! nsRefPtr<nsHostResolver> res; nsCOMPtr<nsIIDNService> idn; { nsAutoLock lock(mLock); res = mResolver; idn = mIDN; } NS_ENSURE_TRUE(res, NS_ERROR_OFFLINE); const nsACString *hostPtr = &hostname; nsresult rv; nsCAutoString hostACE; if (idn && !IsASCII(hostname)) { if (NS_SUCCEEDED(idn->ConvertUTF8toACE(hostname, hostACE))) hostPtr = &hostACE; } // // sync resolve: since the host resolver only works asynchronously, we need // to use a mutex and a condvar to wait for the result. however, since the // result may be in the resolvers cache, we might get called back recursively // on the same thread. so, our mutex needs to be re-entrant. inotherwords, // we need to use a monitor! ;-) // PRMonitor *mon = PR_NewMonitor(); if (!mon) return NS_ERROR_OUT_OF_MEMORY; PR_EnterMonitor(mon); nsDNSSyncRequest syncReq(mon); PRUint16 af = GetAFForLookup(*hostPtr); rv = res->ResolveHost(PromiseFlatCString(*hostPtr).get(), flags, af, &syncReq); if (NS_SUCCEEDED(rv)) { // wait for result while (!syncReq.mDone) PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT); if (NS_FAILED(syncReq.mStatus)) rv = syncReq.mStatus; else { NS_ASSERTION(syncReq.mHostRecord, "no host record"); nsDNSRecord *rec = new nsDNSRecord(syncReq.mHostRecord); if (!rec) rv = NS_ERROR_OUT_OF_MEMORY; else NS_ADDREF(*result = rec); } } PR_ExitMonitor(mon); PR_DestroyMonitor(mon); return rv; }