summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2013-04-11 21:44:30 +0900
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2013-04-11 23:13:21 +0900
commit4070113ef0fef840a0fdd5104c38fb23cd0008eb (patch)
tree458242805ef6d01dd42f1dce07a2633311277808
parent07d38e31adb7a01a002b0a844a47f5f8ee4fe875 (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.cc34
-rw-r--r--src/Option.h29
-rw-r--r--src/SessionSerializer.cc2
-rw-r--r--src/main.cc18
-rw-r--r--src/option_processing.cc40
-rw-r--r--test/OptionTest.cc30
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