diff --git a/src/command_download.cc b/src/command_download.cc index 00667cb7..12e3fc57 100644 --- a/src/command_download.cc +++ b/src/command_download.cc @@ -511,16 +511,6 @@ d_list_remove(core::Download* download, const torrent::Object& rawArgs, const ch return torrent::Object(); } -void -add_copy_to_download(const char* src, const char* dest) { - rpc::CommandMap::iterator itr = rpc::commands.find(src); - - if (itr == rpc::commands.end()) - throw torrent::internal_error("add_copy_to_download(...) key not found."); - - rpc::commands.insert(dest, itr->second); -} - #define CMD_ON_INFO(func) rak::on(std::mem_fun(&core::Download::info), std::mem_fun(&torrent::DownloadInfo::func)) #define CMD2_ON_INFO(func) std::tr1::bind(&torrent::DownloadInfo::func, std::tr1::bind(&core::Download::info, std::tr1::placeholders::_1)) diff --git a/src/command_dynamic.cc b/src/command_dynamic.cc index 623ce610..43346325 100644 --- a/src/command_dynamic.cc +++ b/src/command_dynamic.cc @@ -112,59 +112,55 @@ system_method_insert_object(const torrent::Object::list_type& args, int flags) { rpc::object_storage::iterator obj_itr = control->object_storage()->insert_str(rawKey, value, flags); - // Add commands: - rpc::command_base* command_get = new rpc::command_base(); - if ((flags & rpc::object_storage::mask_type) == rpc::object_storage::flag_function_type || - (flags & rpc::object_storage::mask_type) == rpc::object_storage::flag_multi_type) - command_get->set_function_2 > - (std::tr1::bind(&rpc::object_storage::call_function_str, control->object_storage(), - rawKey, std::tr1::placeholders::_1, std::tr1::placeholders::_2)); - else - command_get->set_function_2 > - (std::tr1::bind(&rpc::object_storage::get_str, control->object_storage(), rawKey)); + (flags & rpc::object_storage::mask_type) == rpc::object_storage::flag_multi_type) { - rpc::commands.insert_type(create_new_key<0>(rawKey, ""), - command_get, - &rpc::command_base_call, - cmd_flags, NULL, NULL); + rpc::commands.insert_slot >::type> + (create_new_key<0>(rawKey, ""), + std::tr1::bind(&rpc::object_storage::call_function_str, control->object_storage(), + rawKey, std::tr1::placeholders::_1, std::tr1::placeholders::_2), + &rpc::command_base_call, + cmd_flags, NULL, NULL); + + } else { + rpc::commands.insert_slot >::type> + (create_new_key<0>(rawKey, ""), + std::tr1::bind(&rpc::object_storage::get_str, control->object_storage(), rawKey), + &rpc::command_base_call, + cmd_flags, NULL, NULL); + } // TODO: Next... Make test class for this. // // Ehm... no proper handling if these throw. if (!(flags & rpc::object_storage::flag_constant)) { - rpc::command_base* command_set = new rpc::command_base(); - rpc::command_base_call_type command_call = NULL; - switch (flags & rpc::object_storage::mask_type) { case rpc::object_storage::flag_bool_type: - command_set->set_function_2 > - (std::tr1::bind(&rpc::object_storage::set_str_bool, control->object_storage(), rawKey, std::tr1::placeholders::_2)); - - command_call = &rpc::command_base_call_value; + rpc::commands.insert_slot >::type> + (create_new_key<5>(rawKey, ".set"), + std::tr1::bind(&rpc::object_storage::set_str_bool, control->object_storage(), rawKey, std::tr1::placeholders::_2), + &rpc::command_base_call_value, + cmd_flags, NULL, NULL); break; case rpc::object_storage::flag_value_type: - command_set->set_function_2 > - (std::tr1::bind(&rpc::object_storage::set_str_value, control->object_storage(), rawKey, std::tr1::placeholders::_2)); - - command_call = &rpc::command_base_call_value; + rpc::commands.insert_slot >::type> + (create_new_key<5>(rawKey, ".set"), + std::tr1::bind(&rpc::object_storage::set_str_value, control->object_storage(), rawKey, std::tr1::placeholders::_2), + &rpc::command_base_call_value, + cmd_flags, NULL, NULL); break; case rpc::object_storage::flag_string_type: - command_set->set_function_2 > - (std::tr1::bind(&rpc::object_storage::set_str_string, control->object_storage(), rawKey, std::tr1::placeholders::_2)); - - command_call = &rpc::command_base_call_string; + rpc::commands.insert_slot >::type> + (create_new_key<5>(rawKey, ".set"), + std::tr1::bind(&rpc::object_storage::set_str_string, control->object_storage(), rawKey, std::tr1::placeholders::_2), + &rpc::command_base_call_string, + cmd_flags, NULL, NULL); break; case rpc::object_storage::flag_function_type: case rpc::object_storage::flag_multi_type: - default: - delete command_set; - return torrent::Object(); + default: break; } - - rpc::commands.insert_type(create_new_key<5>(rawKey, ".set"), - command_set, command_call, cmd_flags, NULL, NULL); } return torrent::Object(); diff --git a/src/command_helpers.cc b/src/command_helpers.cc index 2783ac73..9c999b8e 100644 --- a/src/command_helpers.cc +++ b/src/command_helpers.cc @@ -42,9 +42,6 @@ #include "control.h" #include "command_helpers.h" -rpc::command_base commandNewSlots[COMMAND_NEW_SLOTS_SIZE]; -rpc::command_base* commandNewSlotItr = commandNewSlots; - void initialize_command_dynamic(); void initialize_command_download(); void initialize_command_events(); @@ -68,11 +65,4 @@ initialize_commands() { initialize_command_peer(); initialize_command_tracker(); initialize_command_scheduler(); - -#ifdef ADDING_COMMANDS - if (commandNewSlotItr > commandNewSlots + COMMAND_NEW_SLOTS_SIZE) -#else - if (commandNewSlotItr != commandNewSlots + COMMAND_NEW_SLOTS_SIZE) -#endif - throw torrent::internal_error("initialize_commands() static command array size mismatch."); } diff --git a/src/command_helpers.h b/src/command_helpers.h index 47da30f4..43a178c4 100644 --- a/src/command_helpers.h +++ b/src/command_helpers.h @@ -41,19 +41,6 @@ #include "rpc/parse_commands.h" #include "rpc/object_storage.h" -namespace rpc { - class CommandObjectPtr; -} - -// By using a static array we avoid allocating the variables on the -// heap. This should reduce memory use and improve cache locality. -#define COMMAND_NEW_SLOTS_SIZE 500 - -#define ADDING_COMMANDS - -extern rpc::command_base commandNewSlots[COMMAND_NEW_SLOTS_SIZE]; -extern rpc::command_base* commandNewSlotItr; - void initialize_commands(); // @@ -61,13 +48,11 @@ void initialize_commands(); // #define CMD2_A_FUNCTION(key, function, slot, parm, doc) \ - commandNewSlotItr->set_function::type>(slot); \ - rpc::commands.insert_type(key, commandNewSlotItr++, &rpc::function, \ + rpc::commands.insert_slot::type>(key, slot, &rpc::function, \ rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, NULL, NULL); #define CMD2_A_FUNCTION_PRIVATE(key, function, slot, parm, doc) \ - commandNewSlotItr->set_function::type>(slot); \ - rpc::commands.insert_type(key, commandNewSlotItr++, &rpc::function, \ + rpc::commands.insert_slot::type>(key, slot, &rpc::function, \ rpc::CommandMap::flag_dont_delete, NULL, NULL); #define CMD2_ANY(key, slot) CMD2_A_FUNCTION(key, command_base_call, slot, "i:", "") diff --git a/src/rpc/command.h b/src/rpc/command.h index 126564ee..5e63b572 100644 --- a/src/rpc/command.h +++ b/src/rpc/command.h @@ -160,7 +160,9 @@ public: }; command_base() { new (&_pod()) base_function(); } - virtual ~command_base() { _pod().~base_function(); } + command_base(const command_base& src) { new (&_pod()) base_function(src._pod()); } + + ~command_base() { _pod().~base_function(); } static torrent::Object* argument(unsigned int index) { return current_stack.begin() + index; } static torrent::Object& argument_ref(unsigned int index) { return *(current_stack.begin() + index); } @@ -188,14 +190,17 @@ public: // template types, yet what the C++0x standard will say about this I // have no idea atm. template tmpl& _pod() { return reinterpret_cast(t_pod); } + template const tmpl& _pod() const { return reinterpret_cast(t_pod); } template static const torrent::Object _call(command_base* cmd, target_type target, Args args); -protected: - command_base(const command_base&); - void operator = (const command_base&); + command_base& operator = (const command_base& src) { + _pod() = src._pod(); + return *this; + } +protected: // For use by functions that need to use placeholders to arguments // within commands. E.d. callable command strings where one of the // arguments within the command needs to be supplied by the caller. diff --git a/src/rpc/command_map.cc b/src/rpc/command_map.cc index a6e460c4..a4c7579e 100644 --- a/src/rpc/command_map.cc +++ b/src/rpc/command_map.cc @@ -61,8 +61,8 @@ CommandMap::~CommandMap() { std::vector keys; for (iterator itr = base_type::begin(), last = base_type::end(); itr != last; itr++) { - if (!(itr->second.m_flags & flag_dont_delete)) - delete itr->second.m_variable; +// if (!(itr->second.m_flags & flag_dont_delete)) +// delete itr->second.m_variable; if (itr->second.m_flags & flag_delete_key) keys.push_back(itr->first); @@ -73,7 +73,7 @@ CommandMap::~CommandMap() { } CommandMap::iterator -CommandMap::insert(key_type key, command_base* variable, int flags, const char* parm, const char* doc) { +CommandMap::insert(key_type key, int flags, const char* parm, const char* doc) { iterator itr = base_type::find(key); if (itr != base_type::end()) @@ -82,21 +82,21 @@ CommandMap::insert(key_type key, command_base* variable, int flags, const char* if (rpc::xmlrpc.is_valid()) rpc::xmlrpc.insert_command(key, parm, doc); - return base_type::insert(itr, value_type(key, command_map_data_type(variable, flags, parm, doc))); + return base_type::insert(itr, value_type(key, command_map_data_type(flags, parm, doc))); } -void -CommandMap::insert(key_type key, const command_map_data_type src) { - iterator itr = base_type::find(key); +// void +// CommandMap::insert(key_type key, const command_map_data_type src) { +// iterator itr = base_type::find(key); - if (itr != base_type::end()) - throw torrent::internal_error("CommandMap::insert(...) tried to insert an already existing key."); +// if (itr != base_type::end()) +// throw torrent::internal_error("CommandMap::insert(...) tried to insert an already existing key."); - itr = base_type::insert(itr, value_type(key, command_map_data_type(src.m_variable, src.m_flags | flag_dont_delete, src.m_parm, src.m_doc))); +// itr = base_type::insert(itr, value_type(key, command_map_data_type(src.m_variable, src.m_flags | flag_dont_delete, src.m_parm, src.m_doc))); - // We can assume all the slots are the same size. - itr->second.m_anySlot = src.m_anySlot; -} +// // We can assume all the slots are the same size. +// itr->second.m_anySlot = src.m_anySlot; +// } void CommandMap::erase(iterator itr) { @@ -107,8 +107,8 @@ CommandMap::erase(iterator itr) { if (itr->second.m_flags & flag_has_redirects) throw torrent::input_error("Can't erase a command that has redirects."); - if (!(itr->second.m_flags & flag_dont_delete)) - delete itr->second.m_variable; +// if (!(itr->second.m_flags & flag_dont_delete)) +// delete itr->second.m_variable; const char* key = itr->second.m_flags & flag_delete_key ? itr->first : NULL; @@ -137,12 +137,12 @@ CommandMap::create_redirect(key_type key_new, key_type key_dest, int flags) { flags |= dest_itr->second.m_flags & ~(flag_delete_key | flag_has_redirects); iterator itr = base_type::insert(base_type::end(), - value_type(key_new, command_map_data_type(dest_itr->second.m_variable, - flags, + value_type(key_new, command_map_data_type(flags, dest_itr->second.m_parm, dest_itr->second.m_doc))); // We can assume all the slots are the same size. + itr->second.m_variable = dest_itr->second.m_variable; itr->second.m_anySlot = dest_itr->second.m_anySlot; } @@ -158,59 +158,17 @@ CommandMap::call_catch(key_type key, target_type target, const mapped_type& args const CommandMap::mapped_type CommandMap::call_command(key_type key, const mapped_type& arg, target_type target) { - const_iterator itr = base_type::find(key); + iterator itr = base_type::find(key); if (itr == base_type::end()) throw torrent::input_error("Command \"" + std::string(key) + "\" does not exist."); -// if (target.first != Command::target_generic && target.second == NULL) { -// // We received a target that is NULL, so throw an exception unless -// // we can convert it to a void target. -// if (itr->second.m_target > Command::target_any) -// throw torrent::input_error("Command type mis-match."); - -// target.first = Command::target_generic; -// } - -// if (itr->second.m_target != target.first && itr->second.m_target > Command::target_any) { -// // Mismatch between the target and command type. If it is not -// // possible to convert, then throw an input error. -// if (target.first == Command::target_file_itr && itr->second.m_target == Command::target_file) -// target = target_type((int)Command::target_file, static_cast(target.second)->file()); -// else -// throw torrent::input_error("Command type mis-match."); -// } - - // This _should_ be optimized int just two calls. -// switch (itr->second.m_target) { -// case Command::target_any: return itr->second.m_anySlot(itr->second.m_variable, target, arg); -// default: throw torrent::internal_error("CommandMap::call_command(...) Invalid target."); -// } - - return itr->second.m_anySlot(itr->second.m_variable, target, arg); + return itr->second.m_anySlot(&itr->second.m_variable, target, arg); } const CommandMap::mapped_type -CommandMap::call_command(const_iterator itr, const mapped_type& arg, target_type target) { -// if (target.first != Command::target_generic && target.second == NULL) { -// // We received a target that is NULL, so throw an exception unless -// // we can convert it to a void target. -// if (itr->second.m_target > Command::target_any) -// throw torrent::input_error("Command type mis-match."); - -// target.first = Command::target_generic; -// } - -// if (itr->second.m_target != target.first && itr->second.m_target > Command::target_any) -// throw torrent::input_error("Command type mis-match."); - -// // This _should_ be optimized int just two calls. -// switch (itr->second.m_target) { -// case Command::target_any: return itr->second.m_anySlot(itr->second.m_variable, target, arg); -// default: throw torrent::internal_error("CommandMap::call_command(...) Invalid target."); -// } - - return itr->second.m_anySlot(itr->second.m_variable, target, arg); +CommandMap::call_command(iterator itr, const mapped_type& arg, target_type target) { + return itr->second.m_anySlot(&itr->second.m_variable, target, arg); } } diff --git a/src/rpc/command_map.h b/src/rpc/command_map.h index 2d4dfd44..f495b7b5 100644 --- a/src/rpc/command_map.h +++ b/src/rpc/command_map.h @@ -57,10 +57,14 @@ struct command_map_data_type { // // The any_slot should perhaps replace generic_slot? - command_map_data_type(command_base* variable, int flags, const char* parm, const char* doc) : - m_variable(variable), m_flags(flags), m_parm(parm), m_doc(doc) {} + command_map_data_type(int flags, const char* parm, const char* doc) : + m_flags(flags), m_parm(parm), m_doc(doc) {} - command_base* m_variable; + command_map_data_type(const command_map_data_type& src) : + m_variable(src.m_variable), m_anySlot(src.m_anySlot), + m_flags(src.m_flags), m_parm(src.m_parm), m_doc(src.m_doc) {} + + command_base m_variable; command_base::any_slot m_anySlot; int m_flags; @@ -104,15 +108,17 @@ public: bool is_modifiable(const_iterator itr) { return itr != end() && (itr->second.m_flags & flag_modifiable); } - iterator insert(key_type key, command_base* variable, int flags, const char* parm, const char* doc); + iterator insert(key_type key, int flags, const char* parm, const char* doc); - // Make this a wrapper call to insert without extra fluff. - void insert_type(key_type key, command_base* variable, command_base::any_slot targetSlot, int flags, const char* parm, const char* doc) { - iterator itr = insert(key, variable, flags, parm, doc); + template + void + insert_slot(key_type key, Slot variable, command_base::any_slot targetSlot, int flags, const char* parm, const char* doc) { + iterator itr = insert(key, flags, parm, doc); + itr->second.m_variable.set_function(variable); itr->second.m_anySlot = targetSlot; } - void insert(key_type key, const command_map_data_type src); + // void insert(key_type key, const command_map_data_type src); void erase(iterator itr); void create_redirect(key_type key_new, key_type key_dest, int flags); @@ -122,7 +128,7 @@ public: const mapped_type call_catch(key_type key, target_type target, const mapped_type& args = mapped_type(), const char* err = "Command failed: "); const mapped_type call_command (key_type key, const mapped_type& arg, target_type target = target_type((int)command_base::target_generic, NULL)); - const mapped_type call_command (const_iterator itr, const mapped_type& arg, target_type target = target_type((int)command_base::target_generic, NULL)); + const mapped_type call_command (iterator itr, const mapped_type& arg, target_type target = target_type((int)command_base::target_generic, NULL)); const mapped_type call_command_d(key_type key, core::Download* download, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_download, download)); } const mapped_type call_command_p(key_type key, torrent::Peer* peer, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_peer, peer)); } diff --git a/src/rpc/xmlrpc.cc b/src/rpc/xmlrpc.cc index e6579ab2..cab44f74 100644 --- a/src/rpc/xmlrpc.cc +++ b/src/rpc/xmlrpc.cc @@ -432,7 +432,7 @@ object_to_xmlrpc(xmlrpc_env* env, const torrent::Object& object) { xmlrpc_value* xmlrpc_call_command(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo) { - CommandMap::const_iterator itr = commands.find((const char*)voidServerInfo); + CommandMap::iterator itr = commands.find((const char*)voidServerInfo); if (itr == commands.end()) { xmlrpc_env_set_fault(env, XMLRPC_PARSE_ERROR, ("Command \"" + std::string((const char*)voidServerInfo) + "\" does not exist.").c_str()); diff --git a/test/rpc/command_map_test.cc b/test/rpc/command_map_test.cc index 8ce2741e..eb0b07d0 100644 --- a/test/rpc/command_map_test.cc +++ b/test/rpc/command_map_test.cc @@ -10,8 +10,7 @@ CPPUNIT_TEST_SUITE_REGISTRATION(CommandMapTest); #undef CMD2_A_FUNCTION #define CMD2_A_FUNCTION(key, function, slot, parm, doc) \ - m_commandItr->set_function::type>(slot); \ - m_map.insert_type(key, m_commandItr++, &rpc::function, \ + m_map.insert_slot::type>(key, slot, &rpc::function, \ rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, NULL, NULL); torrent::Object cmd_test_map_a(rpc::target_type t, const torrent::Object& obj) { return obj; }