diff --git a/src/command_dynamic.cc b/src/command_dynamic.cc index 83248a71..5345f013 100644 --- a/src/command_dynamic.cc +++ b/src/command_dynamic.cc @@ -67,7 +67,7 @@ create_new_key(const std::string& key, const char postfix[postfix_size]) { } // system.method.insert {name, "simple|private|const", ...} -// system.method.insert {name, "list|private|const"} +// system.method.insert {name, "multi|private|const"} // system.method.insert {name, "value|private|const"} // system.method.insert {name, "value|private|const", value} // system.method.insert {name, "bool|private|const"} @@ -100,7 +100,7 @@ system_method_insert(__UNUSED rpc::target_type target, const torrent::Object& ra if (options.find("const") != std::string::npos) flags &= ~rpc::CommandMap::flag_modifiable; - if (options.find("list") != std::string::npos) { + if (options.find("multi") != std::string::npos) { // Later, make it possible to add functions here. rpc::Command* command = new rpc::CommandFunctionList(); rpc::Command::any_slot slot = &rpc::CommandFunctionList::call; @@ -115,7 +115,8 @@ system_method_insert(__UNUSED rpc::target_type target, const torrent::Object& ra } else if (options.find("value") != std::string::npos || options.find("bool") != std::string::npos || - options.find("string") != std::string::npos) { + options.find("string") != std::string::npos || + options.find("list") != std::string::npos) { rpc::CommandVariable *command; rpc::Command::cleaned_slot getSlot; rpc::Command::cleaned_slot setSlot; @@ -128,10 +129,15 @@ system_method_insert(__UNUSED rpc::target_type target, const torrent::Object& ra command = new rpc::CommandVariable(int64_t()); getSlot = &rpc::CommandVariable::get_bool; setSlot = &rpc::CommandVariable::set_bool; - } else { + } else if (options.find("string") != std::string::npos) { command = new rpc::CommandVariable(std::string()); getSlot = &rpc::CommandVariable::get_string; setSlot = &rpc::CommandVariable::set_string; + } else { +// command = new rpc::CommandVariable(torrent::Object::create_list()); +// getSlot = &rpc::CommandVariable::get_string; +// setSlot = &rpc::CommandVariable::set_string; + throw torrent::input_error("No support for 'list' variable type."); } // Only allow deletion after adding a flag that ensures we search @@ -140,7 +146,9 @@ system_method_insert(__UNUSED rpc::target_type target, const torrent::Object& ra flags &= ~rpc::CommandMap::flag_modifiable; rpc::commands.insert_type(create_new_key<0>(rawKey, ""), command, getSlot, flags, NULL, NULL); - rpc::commands.insert_type(create_new_key<5>(rawKey, ".set"), command, setSlot, flags | rpc::CommandMap::flag_dont_delete, NULL, NULL); + + if (options.find("static") == std::string::npos) + rpc::commands.insert_type(create_new_key<5>(rawKey, ".set"), command, setSlot, flags | rpc::CommandMap::flag_dont_delete, NULL, NULL); if (++itrArgs != args.end()) (*setSlot)(command, NULL, *itrArgs); diff --git a/src/command_events.cc b/src/command_events.cc index 0ab26143..7fe4c970 100644 --- a/src/command_events.cc +++ b/src/command_events.cc @@ -93,54 +93,52 @@ apply_on_state_change(const char* name, const torrent::Object& rawArgs) { } torrent::Object -apply_on_ratio(int action, const torrent::Object& rawArgs) { - const torrent::Object::list_type& args = rawArgs.as_list(); +apply_on_ratio(const torrent::Object& rawArgs) { + const std::string& groupName = rawArgs.as_string(); - if (args.empty()) - throw torrent::input_error("Too few arguments."); + char buffer[32 + groupName.size()]; + sprintf(buffer, "group.%s.view", groupName.c_str()); - torrent::Object::list_const_iterator argItr = args.begin(); + core::ViewManager::iterator viewItr = control->view_manager()->find(rpc::commands.call(buffer, rpc::make_target()).as_string()); + + if (viewItr == control->view_manager()->end()) + throw torrent::input_error("Could not find view."); + + char* bufferStart = buffer + sprintf(buffer, "group.%s.ratio.", groupName.c_str()); // first argument: minimum ratio to reach // second argument: minimum upload amount to reach [optional] // third argument: maximum ratio to reach [optional] - int64_t minRatio = rpc::convert_to_value(*argItr++); - int64_t minUpload = argItr != args.end() ? rpc::convert_to_value(*argItr++) : 0; - int64_t maxRatio = argItr != args.end() ? rpc::convert_to_value(*argItr++) : 0; + std::strcpy(bufferStart, "min"); + int64_t minRatio = rpc::commands.call(buffer, rpc::make_target()).as_value(); + std::strcpy(bufferStart, "max"); + int64_t maxRatio = rpc::commands.call(buffer, rpc::make_target()).as_value(); + std::strcpy(bufferStart, "upload"); + int64_t minUpload = rpc::commands.call(buffer, rpc::make_target()).as_value(); - core::DownloadList* downloadList = control->core()->download_list(); + std::vector downloads; - for (core::Manager::DListItr itr = downloadList->begin(); - (itr = std::find_if(itr, downloadList->end(), std::mem_fun(&core::Download::is_seeding))) != downloadList->end(); ) { - core::Download* current = *itr++; - - if (rpc::call_command_value("d.get_ignore_commands", rpc::make_target(current)) != 0) + for (core::View::iterator itr = (*viewItr)->begin_visible(), last = (*viewItr)->end_visible(); itr != last; itr++) { + if (rpc::call_command_value("d.get_ignore_commands", rpc::make_target(*itr)) != 0) continue; - int64_t totalDone = current->download()->bytes_done(); - int64_t totalUpload = current->download()->up_rate()->total(); + rpc::parse_command_single(rpc::make_target(*itr), "print={Checked ratio of download.}"); + + int64_t totalDone = (*itr)->download()->bytes_done(); + int64_t totalUpload = (*itr)->download()->up_rate()->total(); if (!(totalUpload >= minUpload && totalUpload * 100 >= totalDone * minRatio) && !(maxRatio > 0 && totalUpload * 100 > totalDone * maxRatio)) continue; - bool success = true; + downloads.push_back(*itr); + } - switch (action) { -// case core::DownloadList::SLOTS_CLOSE: success = downloadList->close_try(current); break; -// case core::DownloadList::SLOTS_STOP: success = downloadList->stop_try(current); break; - case core::DownloadList::D_SLOTS_CLOSE: rpc::parse_command_single(rpc::make_target(current), "d.try_close="); break; - case core::DownloadList::D_SLOTS_STOP: rpc::parse_command_single(rpc::make_target(current), "d.try_stop="); break; - default: success = false; break; - } + std::strcpy(bufferStart, "command"); - if (!success) - continue; - - rpc::call_command("d.set_ignore_commands", (int64_t)1, rpc::make_target(current)); - - for (torrent::Object::list_const_iterator itr2 = argItr; itr2 != args.end(); itr2++) - rpc::parse_command_object(rpc::make_target(current), *itr2); + for (std::vector::iterator itr = downloads.begin(), last = downloads.end(); itr != last; itr++) { + rpc::commands.call("print", rpc::make_target(*itr), "Calling ratio command."); + rpc::commands.call_catch(buffer, rpc::make_target(*itr), torrent::Object(), "Ratio reached, but command failed: "); } return torrent::Object(); @@ -369,8 +367,7 @@ initialize_command_events() { ADD_COMMAND_LIST("on_hash_removed", rak::bind_ptr_fn(&apply_on_state_change, "event.download.hash_removed")); ADD_COMMAND_LIST("on_finished", rak::bind_ptr_fn(&apply_on_state_change, "event.download.finished")); - ADD_COMMAND_LIST("stop_on_ratio", rak::bind_ptr_fn(&apply_on_ratio, (int)core::DownloadList::D_SLOTS_STOP)); - ADD_COMMAND_LIST("close_on_ratio", rak::bind_ptr_fn(&apply_on_ratio, (int)core::DownloadList::D_SLOTS_CLOSE)); + ADD_COMMAND_STRING("on_ratio", rak::ptr_fn(&apply_on_ratio)); ADD_COMMAND_VOID("start_tied", &apply_start_tied); ADD_COMMAND_VOID("stop_untied", &apply_stop_untied); diff --git a/src/main.cc b/src/main.cc index d5aaef0f..8dbb6972 100644 --- a/src/main.cc +++ b/src/main.cc @@ -181,19 +181,19 @@ main(int argc, char** argv) { "system.method.insert = test.method.simple,simple,\"print=simple_test_,$argument.0=\"\n" - "system.method.insert = event.download.inserted,list\n" - "system.method.insert = event.download.inserted_new,list\n" - "system.method.insert = event.download.inserted_session,list\n" - "system.method.insert = event.download.erased,list\n" - "system.method.insert = event.download.opened,list\n" - "system.method.insert = event.download.closed,list\n" - "system.method.insert = event.download.resumed,list\n" - "system.method.insert = event.download.paused,list\n" + "system.method.insert = event.download.inserted,multi\n" + "system.method.insert = event.download.inserted_new,multi\n" + "system.method.insert = event.download.inserted_session,multi\n" + "system.method.insert = event.download.erased,multi\n" + "system.method.insert = event.download.opened,multi\n" + "system.method.insert = event.download.closed,multi\n" + "system.method.insert = event.download.resumed,multi\n" + "system.method.insert = event.download.paused,multi\n" - "system.method.insert = event.download.finished,list\n" - "system.method.insert = event.download.hash_done,list\n" - "system.method.insert = event.download.hash_removed,list\n" - "system.method.insert = event.download.hash_queued,list\n" + "system.method.insert = event.download.finished,multi\n" + "system.method.insert = event.download.hash_done,multi\n" + "system.method.insert = event.download.hash_removed,multi\n" + "system.method.insert = event.download.hash_queued,multi\n" "system.method.set_key = event.download.inserted, 1_connect_logs, d.initialize_logs=\n" "system.method.set_key = event.download.inserted_new, 1_prepare, \"branch=d.get_state=,view.set_visible=started,view.set_visible=stopped ;d.save_session=\"\n" @@ -202,6 +202,23 @@ main(int argc, char** argv) { "system.method.set_key = event.download.erased, 0_download_list, ui.unfocus_download=\n" "system.method.set_key = event.download.erased, 9_delete_tied, d.delete_tied=\n" + // Allow setting 'group.view' as constant, so that we can't + // modify the value. And look into the possibility of making + // 'const' use non-heap memory, as we know they can't be + // erased. + + // TODO: Remember to ensure it doesn't get restarted by watch + // dir, etc. Set ignore commands, or something. + + "system.method.insert = group.seeding.view,string|static|const,seeding\n" + + "system.method.insert = group.seeding.ratio.enable ,simple,\"schedule=group.seeding.ratio,5,60,on_ratio=seeding\"\n" + "system.method.insert = group.seeding.ratio.disable,simple,\"schedule_remove=group.seeding.ratio\"\n" + "system.method.insert = group.seeding.ratio.command,simple|static,\"d.try_close= ;d.set_ignore_commands=1\"\n" + "system.method.insert = group.seeding.ratio.min,value,200\n" + "system.method.insert = group.seeding.ratio.max,value,300\n" + "system.method.insert = group.seeding.ratio.upload,value,20M\n" + "set_name = \"$cat=$system.hostname=,:,$system.pid=\"\n" // Currently not doing any sorting on main.