From 3b550ece9880fee417f7de1030941ef514093489 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sun, 10 Oct 2010 02:22:57 +0000 Subject: [PATCH] don't save settings that are set to the default value --- CMakeLists.txt | 1 + ChangeLog | 2 + Jamfile | 1 + include/libtorrent/Makefile.am | 1 + include/libtorrent/assert.hpp | 2 + include/libtorrent/bencode.hpp | 2 + include/libtorrent/session_settings.hpp | 2 + include/libtorrent/settings.hpp | 62 ++++++++++++ src/Makefile.am | 1 + src/session_impl.cpp | 108 +++++---------------- src/settings.cpp | 124 ++++++++++++++++++++++++ test/test_primitives.cpp | 12 ++- 12 files changed, 232 insertions(+), 86 deletions(-) create mode 100644 include/libtorrent/settings.hpp create mode 100644 src/settings.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d68e0674a..890fadfab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,7 @@ set(sources puff session session_impl + settings socket_io socket_type socks5_stream diff --git a/ChangeLog b/ChangeLog index 0810832e0..3a00e7baf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,5 @@ + * settings that are not changed from the default values are not saved + in the session state * made seeding choking algorithm configurable * deprecated setters for max connections, max half-open, upload and download rates and unchoke slots. These are now set through session_settings diff --git a/Jamfile b/Jamfile index ceb91ff49..602513fe8 100755 --- a/Jamfile +++ b/Jamfile @@ -385,6 +385,7 @@ SOURCES = puff session session_impl + settings socket_io socket_type socks5_stream diff --git a/include/libtorrent/Makefile.am b/include/libtorrent/Makefile.am index ddd689d75..92033b0bb 100644 --- a/include/libtorrent/Makefile.am +++ b/include/libtorrent/Makefile.am @@ -78,6 +78,7 @@ nobase_include_HEADERS = \ session.hpp \ session_settings.hpp \ session_status.hpp \ + settings.hpp \ size_type.hpp \ socket.hpp \ socket_io.hpp \ diff --git a/include/libtorrent/assert.hpp b/include/libtorrent/assert.hpp index 780101e45..752fd18e0 100644 --- a/include/libtorrent/assert.hpp +++ b/include/libtorrent/assert.hpp @@ -51,6 +51,8 @@ std::string demangle(char const* name); #if (defined __linux__ || defined __MACH__) && defined __GNUC__ +#include + TORRENT_EXPORT void assert_fail(const char* expr, int line, char const* file, char const* function, char const* val); #define TORRENT_ASSERT(x) do { if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__, 0); } while (false) #define TORRENT_ASSERT_VAL(x, y) do { if (x) {} else { std::stringstream __s__; __s__ << #y ": " << y; assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__, __s__.str().c_str()); } } while (false) diff --git a/include/libtorrent/bencode.hpp b/include/libtorrent/bencode.hpp index 303019966..9e3d14afa 100644 --- a/include/libtorrent/bencode.hpp +++ b/include/libtorrent/bencode.hpp @@ -209,6 +209,8 @@ namespace libtorrent ret += 2; break; default: + // trying to encode a structure with uninitialized values! + TORRENT_ASSERT_VAL(false, e.type()); // do nothing break; } diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp index cd8081a0a..4ac7c66a6 100644 --- a/include/libtorrent/session_settings.hpp +++ b/include/libtorrent/session_settings.hpp @@ -37,6 +37,8 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/config.hpp" #include "libtorrent/version.hpp" +#include + namespace libtorrent { diff --git a/include/libtorrent/settings.hpp b/include/libtorrent/settings.hpp new file mode 100644 index 000000000..872128650 --- /dev/null +++ b/include/libtorrent/settings.hpp @@ -0,0 +1,62 @@ +/* + +Copyright (c) 2010, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef SETTINGS_HPP_INCLUDED +#define SETTINGS_HPP_INCLUDED + +#include "libtorrent/config.hpp" +#include "libtorrent/session_settings.hpp" + +namespace libtorrent +{ + struct lazy_entry; + struct entry; + + enum { std_string = 0, character = 1, short_integer = 2 + , integer = 3, floating_point = 4, boolean = 5}; + + // this is used to map struct entries + // to names in a bencoded dictionary to + // save and load the struct + struct bencode_map_entry + { + char const* name; + int offset; // struct offset + int type; + }; + + void load_struct(lazy_entry const& e, void* s, bencode_map_entry const* m, int num); + void save_struct(entry& e, void const* s, bencode_map_entry const* m, int num, void const* def = 0); +} + +#endif + diff --git a/src/Makefile.am b/src/Makefile.am index ef8d06ffa..ed16a6b83 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -62,6 +62,7 @@ libtorrent_rasterbar_la_SOURCES = \ puff.cpp \ session.cpp \ session_impl.cpp \ + settings.cpp \ sha1.cpp \ smart_ban.cpp \ socket_io.cpp \ diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 9c44cf938..432ab959e 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -75,6 +75,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/lsd.hpp" #include "libtorrent/instantiate_connection.hpp" #include "libtorrent/peer_info.hpp" +#include "libtorrent/settings.hpp" #ifndef TORRENT_WINDOWS #include @@ -180,19 +181,6 @@ namespace aux { } }; - enum { std_string = 0, character = 1, short_integer = 2 - , integer = 3, floating_point = 4, boolean = 5}; - - // this is used to map struct entries - // to names in a bencoded dictionary to - // save and load the struct - struct bencode_map_entry - { - char const* name; - int offset; // struct offset - int type; - }; - #define TORRENT_SETTING(t, x) {#x, offsetof(session_settings,x), t}, bencode_map_entry session_settings_map[] = @@ -376,19 +364,32 @@ namespace aux { int num_entries; int flag; int offset; + int default_offset; + }; + + // the names in here need to match the names in session_impl + // to make the macro simpler + struct all_default_values + { + session_settings m_settings; + proxy_settings m_proxy; + pe_settings m_pe_settings; +#ifndef TORRENT_DISABLE_DHT + dht_settings m_dht_settings; +#endif }; #define lenof(x) sizeof(x)/sizeof(x[0]) #define TORRENT_CATEGORY(name, flag, member, map) \ - { name, map, lenof(map), session:: flag , offsetof(session_impl, member) }, + { name, map, lenof(map), session:: flag , offsetof(session_impl, member), offsetof(all_default_values, member) }, session_category all_settings[] = { TORRENT_CATEGORY("settings", save_settings, m_settings, session_settings_map) #ifndef TORRENT_DISABLE_DHT -// TORRENT_CATEGORY("dht", save_dht_settings, m_dht_settings, dht_settings_map) - TORRENT_CATEGORY("proxy", save_proxy, m_proxy, proxy_settings_map) + TORRENT_CATEGORY("dht", save_dht_settings, m_dht_settings, dht_settings_map) #endif + TORRENT_CATEGORY("proxy", save_proxy, m_proxy, proxy_settings_map) #if TORRENT_USE_I2P // TORRENT_CATEGORY("i2p", save_i2p_proxy, m_i2p_proxy, proxy_settings_map) #endif @@ -399,63 +400,6 @@ namespace aux { #undef lenof - void load_struct(lazy_entry const& e, void* s, bencode_map_entry const* m, int num) - { - for (int i = 0; i < num; ++i) - { - lazy_entry const* key = e.dict_find(m[i].name); - if (key == 0) continue; - void* dest = ((char*)s) + m[i].offset; - switch (m[i].type) - { - case std_string: - { - if (key->type() != lazy_entry::string_t) continue; - *((std::string*)dest) = key->string_value(); - break; - } - case character: - case boolean: - case integer: - case floating_point: - { - if (key->type() != lazy_entry::int_t) continue; - size_type val = key->int_value(); - switch (m[i].type) - { - case character: *((char*)dest) = val; break; - case integer: *((int*)dest) = val; break; - case floating_point: *((float*)dest) = float(val) / 1000.f; break; - case boolean: *((bool*)dest) = val; break; - } - } - } - } - } - - void save_struct(entry& e, void const* s, bencode_map_entry const* m, int num) - { - for (int i = 0; i < num; ++i) - { - char const* key = m[i].name; - void const* src = ((char*)s) + m[i].offset; - entry& val = e[key]; - TORRENT_ASSERT_VAL(val.type() == entry::undefined_t, val.type()); - switch (m[i].type) - { - case std_string: - { - val = *((std::string*)src); - break; - } - case character: val = *((char*)src); break; - case integer: val = *((int*)src); break; - case floating_point: val = size_type(*((float*)src) * 1000.f); break; - case boolean: val = *((bool*)src); break; - } - } - } - #ifdef TORRENT_STATS int session_impl::logging_allocator::allocations = 0; int session_impl::logging_allocator::allocated_bytes = 0; @@ -802,17 +746,18 @@ namespace aux { entry& e = *eptr; + all_default_values def; + for (int i = 0; i < sizeof(all_settings)/sizeof(all_settings[0]); ++i) { session_category const& c = all_settings[i]; if ((flags & c.flag) == 0) continue; - save_struct(e[c.name], reinterpret_cast(this) + c.offset, c.map, c.num_entries); + save_struct(e[c.name], reinterpret_cast(this) + c.offset + , c.map, c.num_entries, reinterpret_cast(&def) + c.default_offset); } #ifndef TORRENT_DISABLE_DHT if (flags & session::save_dht_settings) { - save_struct(e["dht"], &m_dht_settings, dht_settings_map - , sizeof(dht_settings_map)/sizeof(dht_settings_map[0])); } #endif #ifndef TORRENT_DISABLE_DHT @@ -827,7 +772,8 @@ namespace aux { if (flags & session::save_i2p_proxy) { save_struct(e["i2p"], &i2p_proxy(), proxy_settings_map - , sizeof(proxy_settings_map)/sizeof(proxy_settings_map[0])); + , sizeof(proxy_settings_map)/sizeof(proxy_settings_map[0]) + , &def.m_proxy); } #endif #ifndef TORRENT_DISABLE_GEO_IP @@ -885,14 +831,6 @@ namespace aux { m_udp_socket.set_proxy_settings(m_proxy); #ifndef TORRENT_DISABLE_DHT - settings = e->dict_find_dict("dht"); - if (settings) - { - dht_settings s; - load_struct(*settings, &s, dht_settings_map - , sizeof(dht_settings_map)/sizeof(dht_settings_map[0])); - set_dht_settings(s); - } settings = e->dict_find_dict("dht state"); if (settings) { diff --git a/src/settings.cpp b/src/settings.cpp new file mode 100644 index 000000000..8811965ed --- /dev/null +++ b/src/settings.cpp @@ -0,0 +1,124 @@ +/* + +Copyright (c) 2010, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "libtorrent/settings.hpp" +#include "libtorrent/lazy_entry.hpp" +#include "libtorrent/entry.hpp" +#include "libtorrent/assert.hpp" + +#include + +namespace libtorrent +{ + + void load_struct(lazy_entry const& e, void* s, bencode_map_entry const* m, int num) + { + for (int i = 0; i < num; ++i) + { + lazy_entry const* key = e.dict_find(m[i].name); + if (key == 0) continue; + void* dest = ((char*)s) + m[i].offset; + switch (m[i].type) + { + case std_string: + { + if (key->type() != lazy_entry::string_t) continue; + *((std::string*)dest) = key->string_value(); + break; + } + case character: + case boolean: + case integer: + case floating_point: + { + if (key->type() != lazy_entry::int_t) continue; + size_type val = key->int_value(); + switch (m[i].type) + { + case character: *((char*)dest) = val; break; + case integer: *((int*)dest) = val; break; + case floating_point: *((float*)dest) = float(val) / 1000.f; break; + case boolean: *((bool*)dest) = val; break; + } + } + } + } + } + + void save_struct(entry& e, void const* s, bencode_map_entry const* m, int num, void const* def) + { + e = entry(entry::dictionary_t); + for (int i = 0; i < num; ++i) + { + char const* key = m[i].name; + void const* src = ((char*)s) + m[i].offset; + if (def) + { + // if we have a default value for this field + // and it is the default, don't save it + void const* default_value = ((char*)def) + m[i].offset; + switch (m[i].type) + { + case std_string: + if (*((std::string*)src) == *((std::string*)default_value)) continue; + break; + case character: + if (*((char*)src) == *((char*)default_value)) continue; + break; + case integer: + if (*((int*)src) == *((int*)default_value)) continue; + break; + case floating_point: + if (*((float*)src) == *((float*)default_value)) continue; + break; + case boolean: + if (*((bool*)src) == *((bool*)default_value)) continue; + break; + default: TORRENT_ASSERT(false); + } + } + entry& val = e[key]; + TORRENT_ASSERT_VAL(val.type() == entry::undefined_t, val.type()); + switch (m[i].type) + { + case std_string: val = *((std::string*)src); break; + case character: val = *((char*)src); break; + case integer: val = *((int*)src); break; + case floating_point: val = size_type(*((float*)src) * 1000.f); break; + case boolean: val = *((bool*)src); break; + default: TORRENT_ASSERT(false); + } + } + } + +} + diff --git a/test/test_primitives.cpp b/test/test_primitives.cpp index fe8b0f5ad..b2d6cfbad 100644 --- a/test/test_primitives.cpp +++ b/test/test_primitives.cpp @@ -411,6 +411,12 @@ int test_main() sett.auto_scrape_interval = 235; sett.auto_scrape_min_interval = 62; s->set_settings(sett); + +#ifndef TORRENT_DISABLE_DHT + dht_settings dhts; + dhts.max_peers_reply = 70; + s->set_dht_settings(dhts); +#endif /* #ifndef TORRENT_DISABLE_DHT dht_settings dht_sett; @@ -459,7 +465,11 @@ int test_main() ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), session_state2); TEST_CHECK(ret == 0); - printf("session_state\n%s\n", print_entry(session_state2).c_str()); + fprintf(stderr, "session_state\n%s\n", print_entry(session_state2).c_str()); + + // make sure settings that haven't been changed from their defaults are not saved + TEST_CHECK(session_state2.dict_find("settings")->dict_find("optimistic_disk_retry") == 0); + s->load_state(session_state2); #define CMP_SET(x) TEST_CHECK(s->settings().x == sett.x)