#ifndef _GDL_STORAGE_H_ #define _GDL_STORAGE_H_ #include #include #include #include #include #include "debugdlg.h" using namespace std; // Transfer item status: // // Queued local: command not yet sent to DCTC, but queued by us (the GUI). // Closed: transfer was running, but got closed. // Queued remote: command sent to DCTC, queued by DCTC. // Waiting: download: waiting. upload: starting // Trying, downloading: active status as reported by DCTC. // Uploading: active upload // Closing: user's closed this transfer, it's about to be removed. // enum transfer_status { X_REMOVED=0, X_CLOSED, X_QUEUED_LOCAL, X_QUEUED_REMOTE, X_WAITING, X_TRYING, X_DOWNLOADING, X_UPLOADING, X_CLOSING }; // // Use unsigned long long int to support file sizes > 4 Gb. // typedef unsigned long int ULLINT; // // Class typedef for transfer ranges. // typedef pair ull_pair; // // Some defines and operations on ranges to make my life easier. // #define r_beg(x) (x.first) #define r_end(x) (x.second) #define r_len(x) (x.second-x.first) #define r_min(x,y) (x=y.first : y.second>=x.first))) // Union operation. Undefined for non-overlapping ranges. inline ull_pair combine(const ull_pair &x, const ull_pair &y) { return ull_pair(r_min(x.first, y.first), r_max(x.second, y.second)); } // Implicit join operation. Returns length of joined range. Undefined for non-overlapping ranges. inline ULLINT intersection(const ull_pair &x, const ull_pair &y) { if (x0) { if (time_delta<=MAX_LOOKBACK) { recv_index = (recv_index + time_delta) % MAX_LOOKBACK; recv_prev[recv_index] = recv_delta; recv_last10 = 0; for (int i=0; i0 ? elapsed : 1)); } else { unsigned long int elapsed = (unsigned long int)(last_update_time - start_time); if (elapsed<1) elapsed = 1; if (elapsed>MAX_LOOKBACK) elapsed = MAX_LOOKBACK; return (int)((ULLINT)recv_last10 / (ULLINT)elapsed); } } // Path-stripped file name. QString filename() const { QString f = file_name; int index = f.findRev('\\'); f.remove(0,index+1); return f; } // Path to the file. QString filepath() const { QString f = file_name; int index = f.findRev('\\'); f.remove(index, file_name.length()); // truncate string from index to end, no need to specify exact number of chars to remove return f; } QListViewItem *QLVI() { return qlvi; } void set_QLVI(QListViewItem *q) { qlvi=q; } }; // // This is my storage class for one Group of DownLoads (GDL). // class gdl_item { public: // Static GDL ID counter static int gdl_id_counter; // last update time long timestamp; protected: unsigned int _id; // GDL-ID QString name; // local file name QString target_dir; // target directory where the downloaded file is moved by dc-qt ULLINT size; // local file size ULLINT offset; // offset in file at which this GDL has been attached (file download resumed) ULLINT recv; // num of bytes received so far (including offset) int start_time; // time at which GDL has been started/attached ULLINT recv_last10; // num of bytes received during last 10 seconds list sources; // running downloads list completed; // completed downloads // For convenience, we store a pointer to the QListViewItem that represents // this GDL item. When this gdl_item is deleted, the QListViewItem is // deleted as well. QListViewItem *qlvi; public: // Destructor erases all download and completed items. virtual ~gdl_item() { sources.clear(); completed.clear(); if (qlvi) delete qlvi; } // need only 2 parameters to uniquely identify a GDL gdl_item(const QString &fname, const ULLINT fsize) : timestamp(0), _id(gdl_item::gdl_id_counter), name(fname), size(fsize), offset(0), recv(0), start_time(time(NULL)), recv_last10(0), qlvi(0) { gdl_item::gdl_id_counter += 1; } // Attaching to an existing GDL is like creating a new GDL with all // info given. But since the attached GDL already has an ID, we // have to make sure that we don't create a duplicate later. gdl_item(const int gdl_id, const QString &fname, const ULLINT fsize, const ULLINT foffs, const ULLINT frecv, const int s_time, const ULLINT frecv_last10) : timestamp(0), _id(gdl_id), name(fname), size(fsize), offset(foffs), recv(frecv), start_time(s_time), recv_last10(frecv_last10), qlvi(0) { gdl_item::gdl_id_counter = r_max(gdl_id+1, gdl_item::gdl_id_counter+1); // set ID counter above this GDL's ID. } // This is used to update top-level info for existing GDLs. // GDL ID and file name are already known. File size can (theoretically) change. void update(const long ts, // update timestamp const unsigned int id, const ULLINT fsize, const ULLINT foffs, const ULLINT frecv, const int s_time, const ULLINT frecv_last10, const QString &running_dls, // ddd-part of GLSTC entry const QString &completed_dls); // eee-part of GLSTC entry // This is used to add a new queued download from one source (transfer_item). transfer_item &add_source(const transfer_item &src); // This is used to add/update a running download from one source (transfer_item). void update_source(const QString &src); // This is used to add/update a completed download from one source. void update_completed(const QString &completed); // Removes all outdated sources (timestamp too old). void remove_outdated(long timestamp); // Sets status of all outdated sources to queued. void mark_outdated(long timestamp); // Removes all sources that were marked for removal. void delete_removed(); // GDL ID unsigned int id() { return _id; } // Target directory selectors. Could have made the member public // instead, but choose to implement get/set-methods in case this // changes in the future. void set_target_directory(QString &tgt) { target_dir = tgt; } QString get_target_directory() { return target_dir; } // File name QString filename() const { return name; } // File size ULLINT filesize() const { return size; } // Time (seconds) since this GDL was started/attached. int elapsed_time() const; // This calculates number of bytes already received (DCTC's value is incorrect) ULLINT recv_size() const; // This calculates number of bytes left to receive (DCTC's value is incorrect) ULLINT recv_left() const; // Estimates transfer rate (bytes/s). float ETR() const; // Estimates time left until the completion of this GDL, in seconds. int ETC() const; // Returns a status string QString status_str() const; // Calculates total download progress (in percent). float progress() const; QListViewItem *QLVI() { return qlvi; } void set_QLVI(QListViewItem *q) { qlvi=q; } int num_sources() const { return sources.size(); } list::iterator sources_first() { return sources.begin(); } list::iterator sources_last() { return sources.end(); } list::iterator completed_first() { return completed.begin(); } list::iterator completed_last() { return completed.end(); } }; #endif /* * * $Log: transfer_storage.h,v $ * Revision 1.10 2004/03/07 05:24:12 estrato * fixed a bunch of annoying bugs with transfers * * Revision 1.9 2004/02/27 11:15:02 estrato * fixed autoresuming and attaching to gdls * * Revision 1.8 2004/02/22 12:15:04 estrato * Fixed a couple of issues with connect to running, now works 95 percent * * Revision 1.7 2004/02/18 07:58:42 estrato * download to dir, resume download, bugfixes * * Revision 1.6 2004/01/26 18:49:58 estrato * fixed upload bugs * * Revision 1.5 2003/12/08 04:26:12 estrato * New algorithm for estimating transfer rate * * Revision 1.4 2003/09/29 05:40:53 estrato * Bugfix in transfers where duplicate GDL IDs were generated * * Revision 1.3 2003/08/18 12:19:43 estrato * Old transfer dialog now completely replaced, but some functionality is gone. Will add complete functionality in next commit. * * Revision 1.2 2003/08/16 21:34:19 estrato * New transfer dialog update, almost all internal functions done. Will replaceold transferdlg in next commit. * * Revision 1.1 2003/08/14 23:30:45 estrato * New transfer widget, basic storage and view functionality, no signals connected yet. * * */