extern jlib_decl offset_t checked_lseeki64( int handle, offset_t offset, int origin ) { offset_t ret=_lseeki64(handle,offset,origin); if (ret==(offset_t)-1) throw makeErrnoException("checked_lseeki64"); return ret; }
bool init(HANDLE hfile,offset_t _ofs, size32_t size #ifdef WIN32 ,HANDLE hmap #endif ) { ofs = _ofs; maxsize = VMPAGEROUND(size); assertex(maxsize==size); freelist.ofs = 0; freelist.size = maxsize; freelist.next = NULL; #ifdef WIN32 LARGE_INTEGER li; li.QuadPart = _ofs; base = (byte *) MapViewOfFile(hmap, FILE_MAP_READ|FILE_MAP_WRITE, li.HighPart, li.LowPart, size); #else offset_t savedPos = lseek(hfile,0,SEEK_CUR); offset_t length = lseek(hfile,0,SEEK_END); lseek(hfile,savedPos,SEEK_SET); if (length<ofs+maxsize) { if (0 != ftruncate(hfile,ofs+maxsize)) throw makeErrnoException(errno, "CVMSectionAllocator truncate"); } base = (byte *)mmap(NULL, maxsize, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_NORESERVE, hfile, _ofs); if (base == (byte *)MAP_FAILED) base = NULL; // memset(base,0xdd,maxsize); #endif return base!=NULL; }
extern jlib_decl size32_t checked_write( int handle, const void *buffer, size32_t count ) { int ret=_write(handle,buffer,count); if ((size32_t)ret != count) { throw makeErrnoException((ret==-1)?errno:DISK_FULL_EXCEPTION_CODE, "checked_write"); } return (size32_t)ret; }
extern jlib_decl size32_t checked_read(int file, void *buffer, size32_t len) { if (0==len) return 0; unsigned attempts = 0; size32_t ret = 0; unsigned __int64 startCycles = get_cycles_now(); loop { ssize_t readNow = _read(file, buffer, len); if (readNow == (ssize_t)-1) { switch (errno) { case EINTR: readNow = 0; break; default: if (attempts < ioRetryCount) { attempts++; StringBuffer callStr("read"); callStr.append("[errno=").append(errno); unsigned __int64 elapsedMs = cycle_to_nanosec(get_cycles_now() - startCycles)/1000000; callStr.append(", took=").append(elapsedMs); callStr.append(", attempt=").append(attempts).append("](handle="); callStr.append(file).append(", len=").append(len).append(")"); PROGLOG("%s", callStr.str()); readNow = 0; break; } throw makeErrnoException(errno, "checked_read"); } } else if (!readNow) break; ret += readNow; if (readNow == (ssize_t)len) break; buffer = ((char *) buffer) + readNow; len -= readNow; } return ret; }
extern jlib_decl size32_t checked_pread(int file, void *buffer, size32_t len, offset_t pos) { if (0==len) return 0; #ifdef WIN32 if (atomicsupported) { HANDLE hFile = (HANDLE)_get_osfhandle(file); DWORD rread; OVERLAPPED overlapped; memset(&overlapped, 0, sizeof(overlapped)); overlapped.Offset = (DWORD) pos; overlapped.OffsetHigh = (DWORD)(pos>>32); if (ReadFile(hFile, buffer, len, &rread, &overlapped)) return rread; int err = (int)GetLastError(); if (err == ERROR_HANDLE_EOF) return 0; if (err == ERROR_INVALID_PARAMETER) // Win98 etc atomicsupported = false; else throw makeOsException(GetLastError(), "checked_pread"); } { CriticalBlock blk(atomicsection); checked_lseeki64(file, pos, FILE_BEGIN); return checked_read(file, buffer, len); } #else size32_t ret = 0; unsigned attempts = 0; unsigned __int64 startCycles = get_cycles_now(); loop { ssize_t readNow = ::pread(file, buffer, len, pos); if (readNow == (ssize_t)-1) { switch (errno) { case EINTR: readNow = 0; break; default: if (attempts < ioRetryCount) { attempts++; StringBuffer callStr("pread"); callStr.append("[errno=").append(errno); unsigned __int64 elapsedMs = cycle_to_nanosec(get_cycles_now() - startCycles)/1000000; callStr.append(", took=").append(elapsedMs); callStr.append(", attempt=").append(attempts).append("](handle="); callStr.append(file).append(", pos=").append(pos).append(", len=").append(len).append(")"); PROGLOG("%s", callStr.str()); readNow = 0; break; } throw makeErrnoException(errno, "checked_pread"); } } else if (!readNow) break; ret += readNow; if (readNow == (ssize_t)len) break; pos += readNow; buffer = ((char *) buffer) + readNow; len -= readNow; } return ret; #endif }