void CacheFile::read(Uint8* buf,Uint32 size,Uint64 off) { QMutexLocker lock(&mutex); bool close_again = false; // reopen the file if necessary if (fd == -1) { // Out() << "Reopening " << path << endl; openFile(READ); close_again = true; } if (off >= file_size || off >= max_size) { throw Error(i18n("Error : Reading past the end of the file %1").arg(path)); } // jump to right position SeekFile(fd,(Int64)off,SEEK_SET); if ((Uint32)::read(fd,buf,size) != size) { if (close_again) closeTemporary(); throw Error(i18n("Error reading from %1").arg(path)); } if (close_again) closeTemporary(); }
void CacheFile::read(Uint8* buf,Uint32 size,Uint64 off) { QMutexLocker lock(&mutex); bool close_again = false; // reopen the file if necessary if (!fptr) { // Out(SYS_DIO|LOG_DEBUG) << "Reopening " << path << endl; openFile(READ); close_again = true; } if (off >= file_size || off >= max_size) { throw Error(i18n("Error: Reading past the end of the file %1",path)); } // jump to right position if (!fptr->seek(off)) throw Error(i18n("Failed to seek file %1: %2",path,fptr->errorString())); Uint32 sz = 0; if ((sz = fptr->read((char*)buf,size)) != size) { if (close_again) closeTemporary(); throw Error(i18n("Error reading from %1",path)); } if (close_again) closeTemporary(); }
void CacheFile::preallocate(PreallocationThread* prealloc) { QMutexLocker lock(&mutex); if (FileSize(path) == max_size) { Out(SYS_GEN|LOG_NOTICE) << "File " << path << " already big enough" << endl; return; } Out(SYS_GEN|LOG_NOTICE) << "Preallocating file " << path << " (" << max_size << " bytes)" << endl; bool close_again = false; if (fd == -1) { openFile(RW); close_again = true; } if (read_only) { if (close_again) closeTemporary(); throw Error(i18n("Cannot open %1 for writing : readonly filesystem").arg(path)); } try { bool res = false; #ifdef HAVE_XFS_XFS_H if( (! res) && Settings::fullDiskPrealloc() && (Settings::fullDiskPreallocMethod() == 1) ) { res = XfsPreallocate(fd, max_size); } #endif if(! res) { bt::TruncateFile(fd,max_size,!Settings::fullDiskPrealloc()); } } catch (bt::Error & e) { // first attempt failed, must be fat so try that if (!FatPreallocate(fd,max_size)) { if (close_again) closeTemporary(); throw Error(i18n("Cannot preallocate diskspace : %1").arg(strerror(errno))); } } file_size = FileSize(fd); Out(SYS_GEN|LOG_DEBUG) << "file_size = " << file_size << endl; if (close_again) closeTemporary(); }
void CacheFile::preallocate(PreallocationThread* prealloc) { QMutexLocker lock(&mutex); if (FileSize(path) == max_size) { Out(SYS_GEN|LOG_NOTICE) << "File " << path << " already big enough" << endl; return; } Out(SYS_GEN|LOG_NOTICE) << "Preallocating file " << path << " (" << max_size << " bytes)" << endl; bool close_again = false; if (!fptr) { openFile(RW); close_again = true; } int fd = fptr->handle(); if (read_only) { if (close_again) closeTemporary(); throw Error(i18n("Cannot open %1 for writing: readonly filesystem",path)); } try { bool res = false; #ifdef HAVE_XFS_XFS_H if(Cache::preallocateFully()) { res = XfsPreallocate(fd, max_size); } #endif if(! res) { bt::TruncateFile(fd,max_size,!Cache::preallocateFully()); } } catch (bt::Error & e) { throw Error(i18n("Cannot preallocate diskspace: %1",strerror(errno))); } file_size = FileSize(fd); prealloc->written(file_size); Out(SYS_GEN|LOG_DEBUG) << "file_size = " << file_size << endl; if (close_again) closeTemporary(); }
void CacheFile::unmap(void* ptr,Uint32 size) { int ret = 0; QMutexLocker lock(&mutex); #ifdef Q_OS_WIN if (!fptr) return; if (mappings.contains(ptr)) { CacheFile::Entry & e = mappings[ptr]; if (!fptr->unmap((uchar*)e.ptr)) Out(SYS_DIO|LOG_IMPORTANT) << QString("Unmap failed : %1").arg(fptr->errorString()) << endl; mappings.remove(ptr); // no mappings, close temporary if (mappings.count() == 0) closeTemporary(); } #else // see if it wasn't an offsetted mapping if (mappings.contains(ptr)) { CacheFile::Entry & e = mappings[ptr]; #ifdef HAVE_MUNMAP64 ret = munmap64(e.ptr,e.size); #else ret = munmap(e.ptr,e.size); #endif if (ret < 0) Out(SYS_DIO|LOG_IMPORTANT) << QString("Munmap failed with error %1 : %2").arg(errno).arg(strerror(errno)) << endl; mappings.remove(ptr); // no mappings, close temporary if (mappings.count() == 0) closeTemporary(); } #endif }
void CacheFile::write(const Uint8* buf,Uint32 size,Uint64 off) { QMutexLocker lock(&mutex); bool close_again = false; // reopen the file if necessary if (fd == -1) { // Out() << "Reopening " << path << endl; openFile(RW); close_again = true; } if (read_only) throw Error(i18n("Cannot open %1 for writing : readonly filesystem").arg(path)); if (off + size > max_size) { Out() << "Warning : writing past the end of " << path << endl; Out() << (off + size) << " " << max_size << endl; } if (file_size < off) { //Out() << QString("Writing %1 bytes at %2").arg(size).arg(off) << endl; growFile(off - file_size); } // jump to right position SeekFile(fd,(Int64)off,SEEK_SET); int ret = ::write(fd,buf,size); if (close_again) closeTemporary(); if (ret == -1) throw Error(i18n("Error writing to %1 : %2").arg(path).arg(strerror(errno))); else if ((Uint32)ret != size) { Out() << QString("Incomplete write of %1 bytes, should be %2").arg(ret).arg(size) << endl; throw Error(i18n("Error writing to %1").arg(path)); } if (off + size > file_size) file_size = off + size; }
void CacheFile::write(const Uint8* buf,Uint32 size,Uint64 off) { QMutexLocker lock(&mutex); bool close_again = false; // reopen the file if necessary if (!fptr) { // Out(SYS_DIO|LOG_DEBUG) << "Reopening " << path << endl; openFile(RW); close_again = true; } if (read_only) throw Error(i18n("Cannot open %1 for writing: readonly filesystem",path)); if (off + size > max_size) { Out(SYS_DIO|LOG_DEBUG) << "Warning : writing past the end of " << path << endl; Out(SYS_DIO|LOG_DEBUG) << (off + size) << " " << max_size << endl; throw Error(i18n("Attempting to write beyond the maximum size of %1",path)); } if (file_size < off) { //Out(SYS_DIO|LOG_DEBUG) << QString("Writing %1 bytes at %2").arg(size).arg(off) << endl; growFile(off - file_size); } // jump to right position if (!fptr->seek(off)) throw Error(i18n("Failed to seek file %1: %2",path,fptr->errorString())); if (fptr->write((const char*)buf,size) != size) { throw Error(i18n("Failed to write to file %1: %2",path,fptr->errorString())); } if (close_again) closeTemporary(); if (off + size > file_size) file_size = off + size; }
Uint64 CacheFile::diskUsage() { Uint64 ret = 0; bool close_again = false; if (fd == -1) { openFile(READ); close_again = true; } struct stat sb; if (fstat(fd,&sb) == 0) { ret = (Uint64)sb.st_blocks * 512; } // Out(SYS_GEN|LOG_NOTICE) << "CF: " << path << " is taking up " << ret << " bytes" << endl; if (close_again) closeTemporary(); return ret; }
void CacheFile::unmap(void* ptr,Uint32 size) { int ret = 0; QMutexLocker lock(&mutex); // see if it wasn't an offsetted mapping if (mappings.contains(ptr)) { CacheFile::Entry & e = mappings[ptr]; #if HAVE_MUNMAP64 if (e.diff > 0) ret = munmap64((char*)ptr - e.diff,e.size); else ret = munmap64(ptr,e.size); #else if (e.diff > 0) ret = munmap((char*)ptr - e.diff,e.size); else ret = munmap(ptr,e.size); #endif mappings.erase(ptr); // no mappings, close temporary if (mappings.count() == 0) closeTemporary(); } else { #if HAVE_MUNMAP64 ret = munmap64(ptr,size); #else ret = munmap(ptr,size); #endif } if (ret < 0) { Out(SYS_DIO|LOG_IMPORTANT) << QString("Munmap failed with error %1 : %2").arg(errno).arg(strerror(errno)) << endl; } }