diff options
Diffstat (limited to 'libktorrent/torrent/cachefile.cpp')
| -rw-r--r-- | libktorrent/torrent/cachefile.cpp | 507 |
1 files changed, 0 insertions, 507 deletions
diff --git a/libktorrent/torrent/cachefile.cpp b/libktorrent/torrent/cachefile.cpp deleted file mode 100644 index fc7cd33..0000000 --- a/libktorrent/torrent/cachefile.cpp +++ /dev/null @@ -1,507 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005 by Joris Guisson * - * joris.guisson@gmail.com * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - ***************************************************************************/ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - - -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <unistd.h> -#include <errno.h> -#include <tqfile.h> -#include <tdeio/netaccess.h> -#include <tdelocale.h> -#include <tdefileitem.h> -#include <util/array.h> -#include <util/fileops.h> -#include <torrent/globals.h> -#include <interfaces/functions.h> -#include <tdeapplication.h> -#include <util/log.h> -#include <util/error.h> -#include "cachefile.h" -#include "preallocationthread.h" -#include "settings.h" - - -// Not all systems have an O_LARGEFILE - Solaris depending -// on command-line defines, FreeBSD never - so in those cases, -// make it a zero bitmask. As long as it's only OR'ed into -// open(2) flags, that's fine. -// -#ifndef O_LARGEFILE -#define O_LARGEFILE (0) -#endif - - - - -namespace bt -{ - - CacheFile::CacheFile() : fd(-1),max_size(0),file_size(0),mutex(true) - { - read_only = false; - } - - - CacheFile::~CacheFile() - { - if (fd != -1) - close(); - } - - void CacheFile::changePath(const TQString & npath) - { - path = npath; - } - - void CacheFile::openFile(Mode mode) - { - int flags = O_LARGEFILE; - - // by default allways try read write - fd = ::open(TQFile::encodeName(path),flags | O_RDWR); - if (fd < 0 && mode == READ) - { - // in case RDWR fails, try readonly if possible - fd = ::open(TQFile::encodeName(path),flags | O_RDONLY); - if (fd >= 0) - read_only = true; - } - - if (fd < 0) - { - throw Error(i18n("Cannot open %1 : %2").arg(path).arg(strerror(errno))); - } - - file_size = FileSize(fd); - } - - void CacheFile::open(const TQString & path,Uint64 size) - { - TQMutexLocker lock(&mutex); - // only set the path and the max size, we only open the file when it is needed - this->path = path; - max_size = size; - } - - void* CacheFile::map(MMappeable* thing,Uint64 off,Uint32 size,Mode mode) - { - TQMutexLocker lock(&mutex); - // reopen the file if necessary - if (fd == -1) - { - // Out() << "Reopening " << path << endl; - openFile(mode); - } - - if (read_only && mode != READ) - { - 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; - return 0; - } - - int mmap_flag = 0; - switch (mode) - { - case READ: - mmap_flag = PROT_READ; - break; - case WRITE: - mmap_flag = PROT_WRITE; - break; - case RW: - mmap_flag = PROT_READ|PROT_WRITE; - break; - } - - if (off + size > file_size) - { - Uint64 to_write = (off + size) - file_size; - // Out() << "Growing file with " << to_write << " bytes" << endl; - growFile(to_write); - } - - Uint32 page_size = sysconf(_SC_PAGESIZE); - if (off % page_size > 0) - { - // off is not a multiple of the page_size - // so we play around a bit - Uint32 diff = (off % page_size); - Uint64 noff = off - diff; - // Out() << "Offsetted mmap : " << diff << endl; -#if HAVE_MMAP64 - char* ptr = (char*)mmap64(0, size + diff, mmap_flag, MAP_SHARED, fd, noff); -#else - char* ptr = (char*)mmap(0, size + diff, mmap_flag, MAP_SHARED, fd, noff); -#endif - if (ptr == MAP_FAILED) - { - Out() << "mmap failed : " << TQString(strerror(errno)) << endl; - return 0; - } - else - { - CacheFile::Entry e; - e.thing = thing; - e.offset = off; - e.diff = diff; - e.ptr = ptr; - e.size = size + diff; - e.mode = mode; - mappings.insert((void*)(ptr + diff),e); - return ptr + diff; - } - } - else - { -#if HAVE_MMAP64 - void* ptr = mmap64(0, size, mmap_flag, MAP_SHARED, fd, off); -#else - void* ptr = mmap(0, size, mmap_flag, MAP_SHARED, fd, off); -#endif - if (ptr == MAP_FAILED) - { - Out() << "mmap failed : " << TQString(strerror(errno)) << endl; - return 0; - } - else - { - CacheFile::Entry e; - e.thing = thing; - e.offset = off; - e.ptr = ptr; - e.diff = 0; - e.size = size; - e.mode = mode; - mappings.insert(ptr,e); - return ptr; - } - } - } - - void CacheFile::growFile(Uint64 to_write) - { - // reopen the file if necessary - if (fd == -1) - { - // Out() << "Reopening " << path << endl; - openFile(RW); - } - - if (read_only) - throw Error(i18n("Cannot open %1 for writing : readonly filesystem").arg(path)); - - // jump to the end of the file - SeekFile(fd,0,SEEK_END); - - if (file_size + to_write > max_size) - { - Out() << "Warning : writing past the end of " << path << endl; - Out() << (file_size + to_write) << " " << max_size << endl; - } - - Uint8 buf[1024]; - memset(buf,0,1024); - Uint64 num = to_write; - // write data until to_write is 0 - while (to_write > 0) - { - int nb = to_write > 1024 ? 1024 : to_write; - int ret = ::write(fd,buf,nb); - if (ret < 0) - throw Error(i18n("Cannot expand file %1 : %2").arg(path).arg(strerror(errno))); - else if (ret != nb) - throw Error(i18n("Cannot expand file %1 : incomplete write").arg(path)); - to_write -= nb; - } - file_size += num; -// - // Out() << TQString("growing %1 = %2").arg(path).arg(kt::BytesToString(file_size)) << endl; - - if (file_size != FileSize(fd)) - { -// Out() << TQString("Homer Simpson %1 %2").arg(file_size).arg(sb.st_size) << endl; - fsync(fd); - if (file_size != FileSize(fd)) - { - throw Error(i18n("Cannot expand file %1").arg(path)); - } - } - } - - void CacheFile::unmap(void* ptr,Uint32 size) - { - int ret = 0; - TQMutexLocker 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) << TQString("Munmap failed with error %1 : %2").arg(errno).arg(strerror(errno)) << endl; - } - } - - void CacheFile::close() - { - TQMutexLocker lock(&mutex); - - if (fd == -1) - return; - - TQMap<void*,Entry>::iterator i = mappings.begin(); - while (i != mappings.end()) - { - int ret = 0; - CacheFile::Entry & e = i.data(); -#if HAVE_MUNMAP64 - if (e.diff > 0) - ret = munmap64((char*)e.ptr - e.diff,e.size); - else - ret = munmap64(e.ptr,e.size); -#else - if (e.diff > 0) - ret = munmap((char*)e.ptr - e.diff,e.size); - else - ret = munmap(e.ptr,e.size); -#endif - e.thing->unmapped(); - - i++; - mappings.erase(e.ptr); - - if (ret < 0) - { - Out(SYS_DIO|LOG_IMPORTANT) << TQString("Munmap failed with error %1 : %2").arg(errno).arg(strerror(errno)) << endl; - } - } - ::close(fd); - fd = -1; - } - - void CacheFile::read(Uint8* buf,Uint32 size,Uint64 off) - { - TQMutexLocker 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::write(const Uint8* buf,Uint32 size,Uint64 off) - { - TQMutexLocker 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() << TQString("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() << TQString("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::closeTemporary() - { - if (fd == -1 || mappings.count() > 0) - return; - - ::close(fd); - fd = -1; - } - - - - void CacheFile::preallocate(PreallocationThread* prealloc) - { - TQMutexLocker 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(); - } - - 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; - } -} |
