summaryrefslogtreecommitdiffstats
path: root/libktorrent/migrate
diff options
context:
space:
mode:
Diffstat (limited to 'libktorrent/migrate')
-rw-r--r--libktorrent/migrate/Makefile.am7
-rw-r--r--libktorrent/migrate/cachemigrate.cpp120
-rw-r--r--libktorrent/migrate/cachemigrate.h34
-rw-r--r--libktorrent/migrate/ccmigrate.cpp167
-rw-r--r--libktorrent/migrate/ccmigrate.h36
-rw-r--r--libktorrent/migrate/migrate.cpp75
-rw-r--r--libktorrent/migrate/migrate.h53
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 *
+ * *
+ * 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 *
+ * *
+ * 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 *
+ * *
+ * 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 *
+ * *
+ * 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 *
+ * *
+ * 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 *
+ * *
+ * 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 <[email protected]>
+
+ 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