diff --git a/doc/log_stats.plot b/doc/log_stats.plot index 6de59379..1d8eeaca 100644 --- a/doc/log_stats.plot +++ b/doc/log_stats.plot @@ -46,6 +46,7 @@ gnuplot << EOF set terminal png size 1024,768 enhanced +#set terminal png size 2*1024,768 enhanced set xdata time set timefmt "%s" set format x "%H:%M" @@ -55,61 +56,61 @@ set autoscale xfix set key autotitle columnhead set output "output_$1_sockets.png" -plot "peer_stats.$1" using 1:7 smooth bezier with lines lw 4,\ - "peer_stats.$1" using 1:5 smooth bezier with lines lw 4,\ - "peer_stats.$1" using 1:6 smooth bezier with lines lw 4,\ - " #include #include +#include #include #include #include @@ -337,8 +338,25 @@ f_multicall(core::Download* download, const torrent::Object::list_type& args) { // parsing and searching command map for every single call. torrent::Object resultRaw = torrent::Object::create_list(); torrent::Object::list_type& result = resultRaw.as_list(); + std::vector regex_list; + + bool use_regex = true; + + if (args.front().is_list()) + std::transform(args.front().as_list().begin(), args.front().as_list().end(), + std::back_inserter(regex_list), + std::bind(&torrent::Object::as_string_c, std::placeholders::_1)); + else if (args.front().is_string() && !args.front().as_string().empty()) + regex_list.push_back(args.front().as_string()); + else + use_regex = false; for (torrent::FileList::const_iterator itr = download->file_list()->begin(), last = download->file_list()->end(); itr != last; itr++) { + if (use_regex && + std::find_if(regex_list.begin(), regex_list.end(), + std::bind(&rak::regex::operator(), std::placeholders::_1, (*itr)->path()->as_string())) == regex_list.end()) + continue; + torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list(); for (torrent::Object::list_const_iterator cItr = ++args.begin(), cLast = args.end(); cItr != args.end(); cItr++) { diff --git a/src/command_file.cc b/src/command_file.cc index 56004a87..f9c54417 100644 --- a/src/command_file.cc +++ b/src/command_file.cc @@ -56,6 +56,7 @@ apply_f_set_priority(torrent::File* file, uint32_t value) { file->set_priority((torrent::priority_t)value); } +// TODO: Redundant. torrent::Object apply_f_path(torrent::File* file) { if (file->path()->empty()) @@ -110,6 +111,13 @@ initialize_command_file() { CMD2_FILE_VALUE_V("f.unset_create_queued", std::bind(&torrent::File::unset_flags, std::placeholders::_1, torrent::File::flag_create_queued)); CMD2_FILE_VALUE_V("f.unset_resize_queued", std::bind(&torrent::File::unset_flags, std::placeholders::_1, torrent::File::flag_resize_queued)); + CMD2_FILE ("f.prioritize_first", std::bind(&torrent::File::has_flags, std::placeholders::_1, torrent::File::flag_prioritize_first)); + CMD2_FILE_V("f.prioritize_first.enable", std::bind(&torrent::File::set_flags, std::placeholders::_1, torrent::File::flag_prioritize_first)); + CMD2_FILE_V("f.prioritize_first.disable", std::bind(&torrent::File::unset_flags, std::placeholders::_1, torrent::File::flag_prioritize_first)); + CMD2_FILE ("f.prioritize_last", std::bind(&torrent::File::has_flags, std::placeholders::_1, torrent::File::flag_prioritize_last)); + CMD2_FILE_V("f.prioritize_last.enable", std::bind(&torrent::File::set_flags, std::placeholders::_1, torrent::File::flag_prioritize_last)); + CMD2_FILE_V("f.prioritize_last.disable", std::bind(&torrent::File::unset_flags, std::placeholders::_1, torrent::File::flag_prioritize_last)); + CMD2_FILE("f.size_bytes", std::bind(&torrent::File::size_bytes, std::placeholders::_1)); CMD2_FILE("f.size_chunks", std::bind(&torrent::File::size_chunks, std::placeholders::_1)); CMD2_FILE("f.completed_chunks", std::bind(&torrent::File::completed_chunks, std::placeholders::_1)); diff --git a/src/command_helpers.h b/src/command_helpers.h index de0446f0..b9b81ef5 100644 --- a/src/command_helpers.h +++ b/src/command_helpers.h @@ -122,6 +122,13 @@ void initialize_commands(); CMD2_ANY(key, std::bind(&rpc::object_storage::get, control->object_storage(), \ torrent::raw_string::from_c_str(key))); +#define CMD2_VAR_LIST(key) \ + control->object_storage()->insert_c_str(key, torrent::Object::create_list(), rpc::object_storage::flag_list_type); \ + CMD2_ANY(key, std::bind(&rpc::object_storage::get, control->object_storage(), \ + torrent::raw_string::from_c_str(key))); \ + CMD2_ANY_LIST(key ".set", std::bind(&rpc::object_storage::set_list, control->object_storage(), \ + torrent::raw_string::from_c_str(key), std::placeholders::_2)); + #define CMD2_FUNC_SINGLE(key, cmds) \ CMD2_ANY(key, std::bind(&rpc::command_function_call, torrent::raw_string::from_c_str(cmds), \ std::placeholders::_1, std::placeholders::_2)); diff --git a/src/command_local.cc b/src/command_local.cc index 96c29d7a..bec708bc 100644 --- a/src/command_local.cc +++ b/src/command_local.cc @@ -318,6 +318,10 @@ initialize_command_local() { (utils::FileStatusCache::base_type*)control->core()->file_status_cache())); CMD2_ANY_V ("system.file_status_cache.prune", std::bind(&utils::FileStatusCache::prune, control->core()->file_status_cache())); + CMD2_VAR_BOOL ("file.prioritize_toc", 0); + CMD2_VAR_LIST ("file.prioritize_toc.first"); + CMD2_VAR_LIST ("file.prioritize_toc.last"); + CMD2_ANY ("system.files.opened_counter", std::bind(&FM_t::files_opened_counter, fileManager)); CMD2_ANY ("system.files.closed_counter", std::bind(&FM_t::files_closed_counter, fileManager)); CMD2_ANY ("system.files.failed_counter", std::bind(&FM_t::files_failed_counter, fileManager)); @@ -376,9 +380,13 @@ initialize_command_local() { CMD2_EXECUTE ("execute2", rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_throw); CMD2_EXECUTE ("execute.throw", rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_throw); + CMD2_EXECUTE ("execute.throw.bg", rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_throw | rpc::ExecFile::flag_background); CMD2_EXECUTE ("execute.nothrow", rpc::ExecFile::flag_expand_tilde); + CMD2_EXECUTE ("execute.nothrow.bg", rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_background); CMD2_EXECUTE ("execute.raw", rpc::ExecFile::flag_throw); + CMD2_EXECUTE ("execute.raw.bg", rpc::ExecFile::flag_throw | rpc::ExecFile::flag_background); CMD2_EXECUTE ("execute.raw_nothrow", 0); + CMD2_EXECUTE ("execute.raw_nothrow.bg", rpc::ExecFile::flag_background); CMD2_EXECUTE ("execute.capture", rpc::ExecFile::flag_throw | rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_capture); CMD2_EXECUTE ("execute.capture_nothrow", rpc::ExecFile::flag_expand_tilde | rpc::ExecFile::flag_capture); diff --git a/src/main.cc b/src/main.cc index 6d46db1b..dcddf958 100644 --- a/src/main.cc +++ b/src/main.cc @@ -237,12 +237,17 @@ main(int argc, char** argv) { "method.set_key = event.download.inserted_new, 1_prepare, \"branch=d.state=,view.set_visible=started,view.set_visible=stopped ;d.save_full_session=\"\n" "method.set_key = event.download.inserted_session, 1_prepare, \"branch=d.state=,view.set_visible=started,view.set_visible=stopped\"\n" + "method.set_key = event.download.inserted, 1_prioritize_toc, \"branch=file.prioritize_toc=,{\\\"f.multicall=(file.prioritize_toc.first),f.prioritize_first.enable=\\\",\\\"f.multicall=(file.prioritize_toc.last),f.prioritize_last.enable=\\\",d.update_priorities=}\"\n" + "method.set_key = event.download.erased, !_download_list, ui.unfocus_download=\n" "method.set_key = event.download.erased, ~_delete_tied, d.delete_tied=\n" "method.insert.c_simple = group.insert_persistent_view," "((view.add,((argument.0)))),((view.persistent,((argument.0)))),((group.insert,((argument.0)),((argument.0))))\n" + "file.prioritize_toc.first.set = {*.avi,*.mp4,*.mkv,*.gz}\n" + "file.prioritize_toc.last.set = {*.zip}\n" + // Allow setting 'group2.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 diff --git a/src/rpc/exec_file.cc b/src/rpc/exec_file.cc index fbeee4f6..7c017d1a 100644 --- a/src/rpc/exec_file.cc +++ b/src/rpc/exec_file.cc @@ -131,11 +131,19 @@ ExecFile::execute(const char* file, char* const* argv, int flags) { } } - int status; - int wpid = waitpid(childPid, &status, 0); + if (flags & flag_background) { + if (m_logFd != -1) + write(m_logFd, "\n--- Background task ---\n", sizeof("\n--- Background task ---\n")); + + return 0; + } - while (wpid == -1 && rak::error_number::current().value() == rak::error_number::e_intr) + int status; + int wpid; + + do { wpid = waitpid(childPid, &status, 0); + } while (wpid == -1 && rak::error_number::current().value() == rak::error_number::e_intr); if (wpid != childPid) throw torrent::internal_error("ExecFile::execute(...) waitpid failed."); diff --git a/src/rpc/exec_file.h b/src/rpc/exec_file.h index 803af318..02cb8c55 100644 --- a/src/rpc/exec_file.h +++ b/src/rpc/exec_file.h @@ -49,6 +49,7 @@ public: static const int flag_expand_tilde = 0x1; static const int flag_throw = 0x2; static const int flag_capture = 0x4; + static const int flag_background = 0x8; ExecFile() : m_logFd(-1) {} diff --git a/src/rpc/object_storage.cc b/src/rpc/object_storage.cc index 5d3c85bc..bbba6231 100644 --- a/src/rpc/object_storage.cc +++ b/src/rpc/object_storage.cc @@ -69,6 +69,7 @@ object_storage::insert(const char* key_data, uint32_t key_size, const torrent::O case flag_bool_type: object = !!convert_to_value(rawObject); break; case flag_value_type: object = convert_to_value(rawObject); break; case flag_string_type: object = convert_to_string(rawObject); break; + case flag_list_type: use_raw = true; break; case flag_function_type: use_raw = true; break; case flag_multi_type: object = torrent::Object::create_map(); break; } @@ -129,6 +130,16 @@ object_storage::set_string(const torrent::raw_string& key, const std::string& ob return itr->second.object = object; } +const torrent::Object& +object_storage::set_list(const torrent::raw_string& key, const torrent::Object::list_type& object) { + local_iterator itr = find_local(key); + + if (itr == end(bucket_count()) || (itr->second.flags & mask_type) != flag_list_type) + throw torrent::input_error("Key not found or wrong type."); + + return itr->second.object = torrent::Object::create_list_range(object.begin(), object.end()); +} + const torrent::Object& object_storage::set_function(const torrent::raw_string& key, const std::string& object) { local_iterator itr = find_local(key); diff --git a/src/rpc/object_storage.h b/src/rpc/object_storage.h index 381be144..c9081c63 100644 --- a/src/rpc/object_storage.h +++ b/src/rpc/object_storage.h @@ -84,8 +84,9 @@ public: static const unsigned int flag_bool_type = 0x2; static const unsigned int flag_value_type = 0x3; static const unsigned int flag_string_type = 0x4; - static const unsigned int flag_function_type = 0x5; - static const unsigned int flag_multi_type = 0x6; + static const unsigned int flag_list_type = 0x5; + static const unsigned int flag_function_type = 0x6; + static const unsigned int flag_multi_type = 0x7; static const unsigned int mask_type = 0xf; @@ -122,6 +123,10 @@ public: const torrent::Object& set_c_str_string(const char* str, const std::string& object) { return set_string(torrent::raw_string::from_c_str(str), object); } const torrent::Object& set_str_string(const std::string& str, const std::string& object) { return set_string(torrent::raw_string::from_string(str), object); } + const torrent::Object& set_list(const torrent::raw_string& key, const torrent::Object::list_type& object); + const torrent::Object& set_c_str_list(const char* str, const torrent::Object::list_type& object) { return set_list(torrent::raw_string::from_c_str(str), object); } + const torrent::Object& set_str_list(const std::string& str, const torrent::Object::list_type& object) { return set_list(torrent::raw_string::from_string(str), object); } + // Functions callers: torrent::Object call_function(const torrent::raw_string& key, target_type target, const torrent::Object& object); torrent::Object call_function_str(const std::string& key, target_type target, const torrent::Object& object); diff --git a/src/ui/element_file_list.cc b/src/ui/element_file_list.cc index eaac7fb5..b8b4c965 100644 --- a/src/ui/element_file_list.cc +++ b/src/ui/element_file_list.cc @@ -97,7 +97,8 @@ element_file_list_create_info() { element->push_column("Range:", te_command("cat=$f.range_first=,\" - \",$f.range_second=")); element->push_back(""); - element->push_column("Queued:", te_command("cat=\"$if=$f.is_create_queued=,create\",\" \",\"$if=$f.is_resize_queued=,resize\"")); + element->push_column("Queued:", te_command("cat=\"$if=$f.is_create_queued=,create\",\" \",\"$if=$f.is_resize_queued=,resize\"")); + element->push_column("Prioritize:", te_command("cat=\"$if=$f.prioritize_first=,first\",\" \",\"$if=$f.prioritize_last=,last\"")); element->set_column_width(element->column_width() + 1);