diff options
Diffstat (limited to 'libktorrent/migrate')
-rw-r--r-- | libktorrent/migrate/Makefile.am | 7 | ||||
-rw-r--r-- | libktorrent/migrate/cachemigrate.cpp | 120 | ||||
-rw-r--r-- | libktorrent/migrate/cachemigrate.h | 34 | ||||
-rw-r--r-- | libktorrent/migrate/ccmigrate.cpp | 167 | ||||
-rw-r--r-- | libktorrent/migrate/ccmigrate.h | 36 | ||||
-rw-r--r-- | libktorrent/migrate/migrate.cpp | 75 | ||||
-rw-r--r-- | libktorrent/migrate/migrate.h | 53 |
7 files changed, 492 insertions, 0 deletions
diff --git a/libktorrent/migrate/Makefile.am b/libktorrent/migrate/Makefile.am new file mode 100644 index 0000000..9bb5528 --- /dev/null +++ b/libktorrent/migrate/Makefile.am @@ -0,0 +1,7 @@ +INCLUDES = -I$(srcdir)/.. $(all_includes) +METASOURCES = AUTO +libmigrate_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libmigrate.la +noinst_HEADERS = migrate.h ccmigrate.h cachemigrate.h +libmigrate_la_SOURCES = migrate.cpp ccmigrate.cpp cachemigrate.cpp +KDE_CXXFLAGS = $(USE_EXCEPTIONS) $(USE_RTTI) diff --git a/libktorrent/migrate/cachemigrate.cpp b/libktorrent/migrate/cachemigrate.cpp new file mode 100644 index 0000000..f9b203c --- /dev/null +++ b/libktorrent/migrate/cachemigrate.cpp @@ -0,0 +1,120 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +#include <qstringlist.h> +#include <qfileinfo.h> +#include <util/log.h> +#include <util/fileops.h> +#include <util/functions.h> +#include <torrent/torrent.h> +#include <torrent/globals.h> +#include "cachemigrate.h" + + +namespace bt +{ + + bool IsCacheMigrateNeeded(const Torrent & tor,const QString & cache) + { + // mutli files always need to be migrated + if (tor.isMultiFile()) + return true; + + // a single file and a symlink do not need to be migrated + QFileInfo finfo(cache); + if (finfo.isSymLink()) + return false; + + return true; + } + + static void MigrateSingleCache(const Torrent & tor,const QString & cache,const QString & output_dir) + { + Out() << "Migrating single cache " << cache << " to " << output_dir << endl; + + bt::Move(cache,output_dir + tor.getNameSuggestion()); + bt::SymLink(output_dir + tor.getNameSuggestion(),cache); + } + + static void MakePath(const QString & startdir,const QString & path) + { + QStringList sl = QStringList::split(bt::DirSeparator(),path); + + // create all necessary subdirs + QString ctmp = startdir; + + for (Uint32 i = 0;i < sl.count() - 1;i++) + { + ctmp += sl[i]; + // we need to make the same directory structure in the cache + // as the output dir + if (!bt::Exists(ctmp)) + MakeDir(ctmp); + + ctmp += bt::DirSeparator(); + } + } + + static void MigrateMultiCache(const Torrent & tor,const QString & cache,const QString & output_dir) + { + Out() << "Migrating multi cache " << cache << " to " << output_dir << endl; + // if the cache dir is a symlink, everything is OK + if (QFileInfo(cache).isSymLink()) + return; + + QString cache_dir = cache; + + + // make the output dir if it does not exists + if (!bt::Exists(output_dir + tor.getNameSuggestion())) + bt::MakeDir(output_dir + tor.getNameSuggestion()); + + QString odir = output_dir + tor.getNameSuggestion() + bt::DirSeparator(); + QString cdir = cache; + if (!cdir.endsWith(bt::DirSeparator())) + cdir += bt::DirSeparator(); + + // loop over all files in the cache and see if they are symlinks + for (Uint32 i = 0;i < tor.getNumFiles();i++) + { + const TorrentFile & tf = tor.getFile(i); + QFileInfo fi(cdir + tf.getPath()); + // symlinks are OK + if (fi.isSymLink()) + continue; + // make the path if necessary + MakePath(odir,tf.getPath()); + // no symlink so move to output_dir + bt::Move(cdir + tf.getPath(),odir + tf.getPath()); + bt::SymLink(odir + tf.getPath(),cdir + tf.getPath()); + } + } + + void MigrateCache(const Torrent & tor,const QString & cache,const QString & output_dir) + { + QString odir = output_dir; + if (!odir.endsWith(bt::DirSeparator())) + odir += bt::DirSeparator(); + + if (!tor.isMultiFile()) + MigrateSingleCache(tor,cache,odir); + else + MigrateMultiCache(tor,cache,odir); + } +} diff --git a/libktorrent/migrate/cachemigrate.h b/libktorrent/migrate/cachemigrate.h new file mode 100644 index 0000000..3eea231 --- /dev/null +++ b/libktorrent/migrate/cachemigrate.h @@ -0,0 +1,34 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +#ifndef BTCACHEMIGRATE_H +#define BTCACHEMIGRATE_H + +namespace bt +{ + class Torrent; + + /// See if a cache migrate is needed + bool IsCacheMigrateNeeded(const Torrent & tor,const QString & cache); + + /// Migrate the cache + void MigrateCache(const Torrent & tor,const QString & cache,const QString & output_dir); +} + +#endif diff --git a/libktorrent/migrate/ccmigrate.cpp b/libktorrent/migrate/ccmigrate.cpp new file mode 100644 index 0000000..80153bf --- /dev/null +++ b/libktorrent/migrate/ccmigrate.cpp @@ -0,0 +1,167 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +#include <klocale.h> +#include <util/log.h> +#include <util/file.h> +#include <util/error.h> +#include <util/array.h> +#include <util/bitset.h> +#include <util/fileops.h> +#include <torrent/downloader.h> +#include <torrent/torrent.h> +#include <torrent/globals.h> +#include <torrent/chunkdownload.h> +#include <ktversion.h> +#include "ccmigrate.h" + +namespace bt +{ + bool IsPreMMap(const QString & current_chunks) + { + File fptr; + if (!fptr.open(current_chunks,"rb")) + return false; + + CurrentChunksHeader chdr; + fptr.read(&chdr,sizeof(CurrentChunksHeader)); + if (chdr.magic != CURRENT_CHUNK_MAGIC) + { + // magic number not good, so pre + return true; + } + + if (chdr.major >= 2 || (chdr.major == 1 && chdr.minor >= 2)) + { + // version number is 1.2 or greater + return false; + } + + return false; + } + + static bool MigrateChunk(const Torrent & tor,File & new_cc,File & old_cc) + { + Uint32 ch = 0; + old_cc.read(&ch,sizeof(Uint32)); + + Out() << "Migrating chunk " << ch << endl; + if (ch >= tor.getNumChunks()) + return false; + + // calculate the size + Uint32 csize = 0; + if (ch == tor.getNumChunks() - 1) + { + // ch is the last chunk, so it might have a different size + csize = tor.getFileLength() % tor.getChunkSize(); + if (ch == 0) + csize = tor.getChunkSize(); + } + else + { + csize = tor.getChunkSize(); + } + + // calculate the number of pieces + Uint32 num_pieces = csize / MAX_PIECE_LEN; + if (csize % MAX_PIECE_LEN > 0) + num_pieces++; + + // load the pieces array + Array<bool> pieces(num_pieces); + old_cc.read(pieces,sizeof(bool)*num_pieces); + + // convert bool array to bitset + BitSet pieces_bs(num_pieces); + for (Uint32 i = 0;i < num_pieces;i++) + pieces_bs.set(i,pieces[i]); + + // load the actual data + Array<Uint8> data(csize); + old_cc.read(data,csize); + + // write to the new file + ChunkDownloadHeader hdr; + hdr.index = ch; + hdr.num_bits = num_pieces; + hdr.buffered = 1; // by default we will use buffered chunks + // save the chunk header + new_cc.write(&hdr,sizeof(ChunkDownloadHeader)); + // save the bitset + new_cc.write(pieces_bs.getData(),pieces_bs.getNumBytes()); + new_cc.write(data,csize); + return true; + } + + static void MigrateCC(const Torrent & tor,const QString & current_chunks) + { + Out() << "Migrating current_chunks file " << current_chunks << endl; + // open the old current_chunks file + File old_cc; + if (!old_cc.open(current_chunks,"rb")) + throw Error(i18n("Cannot open file %1 : %2").arg(current_chunks).arg(old_cc.errorString())); + + // open a new file in the /tmp dir + File new_cc; + QString tmp = current_chunks + ".tmp"; + if (!new_cc.open(tmp,"wb")) + throw Error(i18n("Cannot open file %1 : %2").arg(tmp).arg(old_cc.errorString())); + + // read the number of chunks + Uint32 num = 0; + old_cc.read(&num,sizeof(Uint32)); + Out() << "Found " << num << " chunks" << endl; + + // write the new current_chunks header + CurrentChunksHeader hdr; + hdr.magic = CURRENT_CHUNK_MAGIC; + hdr.major = kt::MAJOR; + hdr.minor = kt::MINOR; + hdr.num_chunks = num; + new_cc.write(&hdr,sizeof(CurrentChunksHeader)); + + for (Uint32 i = 0;i < num;i++) + { + if (!MigrateChunk(tor,new_cc,old_cc)) + break; + } + + // migrate done, close both files and move new_cc to old_cc + new_cc.close(); + old_cc.close(); + bt::Delete(current_chunks); + bt::Move(tmp,current_chunks); + } + + void MigrateCurrentChunks(const Torrent & tor,const QString & current_chunks) + { + try + { + MigrateCC(tor,current_chunks); + } + catch (...) + { + // cleanup tmp files upon error + bt::Delete("/tmp/kt_current_chunks",true); + throw; + } + } + +} diff --git a/libktorrent/migrate/ccmigrate.h b/libktorrent/migrate/ccmigrate.h new file mode 100644 index 0000000..890bdfa --- /dev/null +++ b/libktorrent/migrate/ccmigrate.h @@ -0,0 +1,36 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +#ifndef BTCCMIGRATE_H +#define BTCCMIGRATE_H + +namespace bt +{ + class Torrent; + + /// Migrates the current_chunks file to the post-mmap era. + void MigrateCurrentChunks(const Torrent & tor,const QString & current_chunks); + + + /// Test if a current_chunks file is from the pre-mmap period + bool IsPreMMap(const QString & current_chunks); + +} + +#endif diff --git a/libktorrent/migrate/migrate.cpp b/libktorrent/migrate/migrate.cpp new file mode 100644 index 0000000..eddde83 --- /dev/null +++ b/libktorrent/migrate/migrate.cpp @@ -0,0 +1,75 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +#include <kurl.h> +#include <klocale.h> +#include <util/log.h> +#include <util/error.h> +#include <util/fileops.h> +#include <util/functions.h> +#include <torrent/globals.h> +#include "migrate.h" +#include "ccmigrate.h" +#include "cachemigrate.h" + +namespace bt +{ + + Migrate::Migrate() + {} + + + Migrate::~Migrate() + {} + + void Migrate::migrate(const Torrent & tor,const QString & tor_dir,const QString & sdir) + { + // check if directory exists + if (!bt::Exists(tor_dir)) + throw Error(i18n("The directory %1 does not exist").arg(tor_dir)); + + // make sure it ends with a / + QString tdir = tor_dir; + if (!tdir.endsWith(bt::DirSeparator())) + tdir += bt::DirSeparator(); + + // see if the current_chunks file exists + if (bt::Exists(tdir + "current_chunks")) + { + // first see if it isn't a download started by a post-mmap version + if (!IsPreMMap(tdir + "current_chunks")) + { + // it's not pre, so it must be post, so just return + Out() << "No migrate needed" << endl; + return; + } + + MigrateCurrentChunks(tor,tdir + "current_chunks"); + } + + // now we need to migrate t + if (IsCacheMigrateNeeded(tor,tdir + "cache" + bt::DirSeparator())) + { + MigrateCache(tor,tdir + "cache" + bt::DirSeparator(),sdir); + } + } + + + +} diff --git a/libktorrent/migrate/migrate.h b/libktorrent/migrate/migrate.h new file mode 100644 index 0000000..ef862ec --- /dev/null +++ b/libktorrent/migrate/migrate.h @@ -0,0 +1,53 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +#ifndef BTMIGRATE_H +#define BTMIGRATE_H + +namespace bt +{ + class Torrent; + + /** + @author Joris Guisson <joris.guisson@gmail.com> + + Class to migrate old pre-mmap downloads to new ones + */ + class Migrate + { + public: + Migrate(); + virtual ~Migrate(); + + /** + * Migrate a download to the new format. + * @param tor The torrent + * @param tor_dir TorX directory + * @param sdir The save directory + * @throw Error if something goes wrong + */ + void migrate(const Torrent & tor,const QString & tor_dir,const QString & sdir); + private: + bool preMMap(const QString & current_chunks); + void migrateCurrentChunks(const QString & current_chunks); + }; + +} + +#endif |