diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2013-04-11 21:44:30 +0900 |
|---|---|---|
| committer | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2013-04-11 23:13:21 +0900 |
| commit | 4070113ef0fef840a0fdd5104c38fb23cd0008eb (patch) | |
| tree | 458242805ef6d01dd42f1dce07a2633311277808 | |
| parent | 07d38e31adb7a01a002b0a844a47f5f8ee4fe875 (diff) | |
Save options directly specified for download in --save-session
This change makes --save-session save only options specified for
download, more specifically, options in command-line, -i file and via
RPC. The other options from conf file and default values are not
saved. This will drastically decrease the size of session file.
| -rw-r--r-- | src/Option.cc | 34 | ||||
| -rw-r--r-- | src/Option.h | 29 | ||||
| -rw-r--r-- | src/SessionSerializer.cc | 2 | ||||
| -rw-r--r-- | src/main.cc | 18 | ||||
| -rw-r--r-- | src/option_processing.cc | 40 | ||||
| -rw-r--r-- | test/OptionTest.cc | 30 |
6 files changed, 119 insertions, 34 deletions
diff --git a/src/Option.cc b/src/Option.cc index 652c9233..f86060d7 100644 --- a/src/Option.cc +++ b/src/Option.cc @@ -51,7 +51,8 @@ Option::~Option() {} Option::Option(const Option& option) : table_(option.table_), - use_(option.use_) + use_(option.use_), + parent_(option.parent_) {} Option& Option::operator=(const Option& option) @@ -59,6 +60,7 @@ Option& Option::operator=(const Option& option) if(this != &option) { table_ = option.table_; use_ = option.use_; + parent_ = option.parent_; } return *this; } @@ -86,17 +88,33 @@ void Option::put(const Pref* pref, const std::string& value) { bool Option::defined(const Pref* pref) const { + return bitfield::test(use_, use_.size()*8, pref->i) || + (parent_ && parent_->defined(pref)); +} + +bool Option::definedLocal(const Pref* pref) const +{ return bitfield::test(use_, use_.size()*8, pref->i); } bool Option::blank(const Pref* pref) const { - return !defined(pref) || table_[pref->i].empty(); + if(bitfield::test(use_, use_.size()*8, pref->i)) { + return table_[pref->i].empty(); + } else { + return !parent_ || parent_->blank(pref); + } } const std::string& Option::get(const Pref* pref) const { - return table_[pref->i]; + if(bitfield::test(use_, use_.size()*8, pref->i)) { + return table_[pref->i]; + } else if(parent_) { + return parent_->get(pref); + } else { + return A2STR::NIL; + } } int32_t Option::getAsInt(const Pref* pref) const { @@ -153,4 +171,14 @@ void Option::merge(const Option& option) } } +void Option::setParent(const SharedHandle<Option>& parent) +{ + parent_ = parent; +} + +const SharedHandle<Option>& Option::getParent() const +{ + return parent_; +} + } // namespace aria2 diff --git a/src/Option.h b/src/Option.h index 51640b2b..c90703e4 100644 --- a/src/Option.h +++ b/src/Option.h @@ -40,6 +40,8 @@ #include <string> #include <vector> +#include "SharedHandle.h" + namespace aria2 { struct Pref; @@ -48,6 +50,7 @@ class Option { private: std::vector<std::string> table_; std::vector<unsigned char> use_; + SharedHandle<Option> parent_; public: Option(); ~Option(); @@ -55,29 +58,41 @@ public: Option& operator=(const Option& option); void put(const Pref* pref, const std::string& value); - // Returns true if name is defined. Otherwise returns false. - // Note that even if the value is a empty string, this method returns true. + // Returns true if name is defined. Otherwise returns false. Note + // that even if the value is a empty string, this method returns + // true. If option is not defined in this object and parent_ is not + // NULL, lookup parent_ to check |pref| is defined. bool defined(const Pref* pref) const; + // Just like defined(), but this function does not lookup parent_. + bool definedLocal(const Pref* pref) const; // Returns true if name is not defined or the value is a empty string. // Otherwise returns false. bool blank(const Pref* pref) const; + // Returns option value for |pref|. If the |pref| is not defined in + // this object, parent_ is looked up. const std::string& get(const Pref* pref) const; int32_t getAsInt(const Pref* pref) const; int64_t getAsLLInt(const Pref* pref) const; bool getAsBool(const Pref* pref) const; double getAsDouble(const Pref* pref) const; - + // Removes |pref| from this object. This function does not modify + // parent_. void remove(const Pref* pref); - + // Removes all option values from this object. This function does + // not modify parent_. void clear(); - + // Returns the option value table of this object. It does not + // contain option values in parent_ and so forth. const std::vector<std::string>& getTable() const { return table_; } - - // Copy option values defined in option to this option. + // Copy option values defined in option to this option. parent_ is + // left unmodified for this object. void merge(const Option& option); + // Sets parent Option object for this object. + void setParent(const SharedHandle<Option>& parent); + const SharedHandle<Option>& getParent() const; }; } // namespace aria2 diff --git a/src/SessionSerializer.cc b/src/SessionSerializer.cc index 990b8ef5..5de35709 100644 --- a/src/SessionSerializer.cc +++ b/src/SessionSerializer.cc @@ -112,7 +112,7 @@ bool writeOption(BufferedFile& fp, const SharedHandle<Option>& op) for(size_t i = 1, len = option::countOption(); i < len; ++i) { const Pref* pref = option::i2p(i); const OptionHandler* h = oparser->find(pref); - if(h && h->getInitialOption() && op->defined(pref)) { + if(h && h->getInitialOption() && op->definedLocal(pref)) { if(h->getCumulative()) { const std::string& val = op->get(pref); std::vector<std::string> v; diff --git a/src/main.cc b/src/main.cc index ed59f886..c58300f3 100644 --- a/src/main.cc +++ b/src/main.cc @@ -272,14 +272,16 @@ error_code::Value main(int argc, char* argv[]) // command-line. If they are left, because op is used as a template // for new RequestGroup(such as created in RPC command), they causes // unintentional effect. - op->remove(PREF_OUT); - op->remove(PREF_FORCE_SEQUENTIAL); - op->remove(PREF_INPUT_FILE); - op->remove(PREF_INDEX_OUT); - op->remove(PREF_SELECT_FILE); - op->remove(PREF_PAUSE); - op->remove(PREF_CHECKSUM); - op->remove(PREF_GID); + for(SharedHandle<Option> i = op; i; i = i->getParent()) { + i->remove(PREF_OUT); + i->remove(PREF_FORCE_SEQUENTIAL); + i->remove(PREF_INPUT_FILE); + i->remove(PREF_INDEX_OUT); + i->remove(PREF_SELECT_FILE); + i->remove(PREF_PAUSE); + i->remove(PREF_CHECKSUM); + i->remove(PREF_GID); + } if(!op->getAsBool(PREF_ENABLE_RPC) && requestGroups.empty() && !uriListParser) { global::cout()->printf("%s\n", MSG_NO_FILES_TO_DOWNLOAD); diff --git a/src/option_processing.cc b/src/option_processing.cc index fac8dd0c..98ea844f 100644 --- a/src/option_processing.cc +++ b/src/option_processing.cc @@ -175,6 +175,20 @@ void showCandidates } // namespace +#ifdef __MINGW32__ +namespace { +void optionNativeToUtf8(Option& op) +{ + for(size_t i = 1, len = option::countOption(); i < len; ++i) { + const Pref* pref = option::i2p(i); + if(op.definedLocal(pref) && !util::isUtf8(op.get(pref))) { + op.put(pref, nativeToUtf8(op.get(pref))); + } + } +} +} // namespace +#endif // __MINGW32__ + void option_processing(Option& op, std::vector<std::string>& uris, int argc, char* argv[]) { @@ -213,9 +227,8 @@ void option_processing(Option& op, std::vector<std::string>& uris, exit(error_code::FINISHED); } } - - oparser->parseDefaultValues(op); - + SharedHandle<Option> confOption(new Option()); + oparser->parseDefaultValues(*confOption); if(!noConf) { std::string cfname = ucfname.empty() ? @@ -230,7 +243,7 @@ void option_processing(Option& op, std::vector<std::string>& uris, } } try { - oparser->parse(op, ss); + oparser->parse(*confOption, ss); } catch(OptionHandlerException& e) { global::cerr()->printf(_("Parse error in %s"), cfname.c_str()); global::cerr()->printf("\n%s", e.stackTrace().c_str()); @@ -254,24 +267,21 @@ void option_processing(Option& op, std::vector<std::string>& uris, } } // Override configuration with environment variables. - overrideWithEnv(op, oparser, PREF_HTTP_PROXY, "http_proxy"); - overrideWithEnv(op, oparser, PREF_HTTPS_PROXY, "https_proxy"); - overrideWithEnv(op, oparser, PREF_FTP_PROXY, "ftp_proxy"); - overrideWithEnv(op, oparser, PREF_ALL_PROXY, "all_proxy"); - overrideWithEnv(op, oparser, PREF_NO_PROXY, "no_proxy"); + overrideWithEnv(*confOption, oparser, PREF_HTTP_PROXY, "http_proxy"); + overrideWithEnv(*confOption, oparser, PREF_HTTPS_PROXY, "https_proxy"); + overrideWithEnv(*confOption, oparser, PREF_FTP_PROXY, "ftp_proxy"); + overrideWithEnv(*confOption, oparser, PREF_ALL_PROXY, "all_proxy"); + overrideWithEnv(*confOption, oparser, PREF_NO_PROXY, "no_proxy"); // we must clear eof bit and seek to the beginning of the buffer. cmdstream.clear(); cmdstream.seekg(0, std::ios::beg); // finaly let's parse and store command-iine options. + op.setParent(confOption); oparser->parse(op, cmdstream); #ifdef __MINGW32__ - for(size_t i = 1, len = option::countOption(); i < len; ++i) { - const Pref* pref = option::i2p(i); - if(op.defined(pref) && !util::isUtf8(op.get(pref))) { - op.put(pref, nativeToUtf8(op.get(pref))); - } - } + optionNativeToUtf8(op); + optionNativeToUtf8(*confOption); #endif // __MINGW32__ } catch(OptionHandlerException& e) { global::cerr()->printf("%s", e.stackTrace().c_str()); diff --git a/test/OptionTest.cc b/test/OptionTest.cc index 29cb4c41..f33a4a6f 100644 --- a/test/OptionTest.cc +++ b/test/OptionTest.cc @@ -17,6 +17,7 @@ class OptionTest:public CppUnit::TestFixture { CPPUNIT_TEST(testDefined); CPPUNIT_TEST(testBlank); CPPUNIT_TEST(testMerge); + CPPUNIT_TEST(testParent); CPPUNIT_TEST_SUITE_END(); private: @@ -30,6 +31,7 @@ public: void testDefined(); void testBlank(); void testMerge(); + void testParent(); }; @@ -93,4 +95,32 @@ void OptionTest::testMerge() CPPUNIT_ASSERT(!dest.defined(PREF_OUT)); } +void OptionTest::testParent() +{ + Option child; + SharedHandle<Option> parent(new Option()); + parent->put(PREF_TIMEOUT, "100"); + child.put(PREF_DIR, "foo"); + CPPUNIT_ASSERT(!child.defined(PREF_TIMEOUT)); + CPPUNIT_ASSERT(!child.definedLocal(PREF_TIMEOUT)); + child.setParent(parent); + CPPUNIT_ASSERT(child.defined(PREF_TIMEOUT)); + CPPUNIT_ASSERT_EQUAL(std::string("100"), child.get(PREF_TIMEOUT)); + CPPUNIT_ASSERT_EQUAL((int32_t)100, child.getAsInt(PREF_TIMEOUT)); + CPPUNIT_ASSERT(!child.definedLocal(PREF_TIMEOUT)); + // blank + CPPUNIT_ASSERT(!child.blank(PREF_DIR)); + child.put(PREF_DIR, ""); + CPPUNIT_ASSERT(child.blank(PREF_DIR)); + CPPUNIT_ASSERT(!child.blank(PREF_TIMEOUT)); + // override + child.put(PREF_TIMEOUT, "200"); + CPPUNIT_ASSERT(child.defined(PREF_TIMEOUT)); + CPPUNIT_ASSERT(child.definedLocal(PREF_TIMEOUT)); + CPPUNIT_ASSERT_EQUAL(std::string("200"), child.get(PREF_TIMEOUT)); + child.remove(PREF_TIMEOUT); + CPPUNIT_ASSERT(child.defined(PREF_TIMEOUT)); + CPPUNIT_ASSERT(!child.definedLocal(PREF_TIMEOUT)); +} + } // namespace aria2 |
