mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-10-22 17:16:17 +00:00
* Allow clock time for command scheduler interval and start time using
the format "hh:mm:ss". git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@627 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
@@ -67,6 +67,8 @@ class timer {
|
|||||||
|
|
||||||
timer operator - (const timer& t) const { return timer(m_time - t.m_time); }
|
timer operator - (const timer& t) const { return timer(m_time - t.m_time); }
|
||||||
timer operator + (const timer& t) const { return timer(m_time + t.m_time); }
|
timer operator + (const timer& t) const { return timer(m_time + t.m_time); }
|
||||||
|
timer operator * (int64_t t) const { return timer(m_time * t); }
|
||||||
|
timer operator / (int64_t t) const { return timer(m_time / t); }
|
||||||
|
|
||||||
timer operator -= (int64_t t) { m_time -= t; return *this; }
|
timer operator -= (int64_t t) { m_time -= t; return *this; }
|
||||||
timer operator -= (const timer& t) { m_time -= t.m_time; return *this; }
|
timer operator -= (const timer& t) { m_time -= t.m_time; return *this; }
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cstdlib>
|
||||||
#include <rak/functional.h>
|
#include <rak/functional.h>
|
||||||
#include <torrent/exceptions.h>
|
#include <torrent/exceptions.h>
|
||||||
|
|
||||||
@@ -98,9 +99,73 @@ CommandScheduler::call_item(value_type item) {
|
|||||||
m_slotErrorMessage("Scheduled command failed: " + item->key() + ": " + e.what());
|
m_slotErrorMessage("Scheduled command failed: " + item->key() + ": " + e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t interval = item->interval();
|
// Still schedule if we caught a torrrent::input_error?
|
||||||
|
rak::timer next = item->next_time_scheduled();
|
||||||
|
|
||||||
// Enable if we caught a torrrent::input_error?
|
if (next == rak::timer()) {
|
||||||
if (interval != 0)
|
// Remove from scheduler?
|
||||||
item->enable(interval);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next <= cachedTime)
|
||||||
|
throw torrent::internal_error("CommandScheduler::call_item(...) tried to schedule a zero interval item.");
|
||||||
|
|
||||||
|
item->enable(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
CommandScheduler::parse_absolute(const char* str) {
|
||||||
|
Time result = parse_time(str);
|
||||||
|
|
||||||
|
switch (result.first) {
|
||||||
|
case 1:
|
||||||
|
return result.second;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
return (result.second - cachedTime.seconds() % 3600) % 3600;
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
throw torrent::input_error("Could not parse interval.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
CommandScheduler::parse_interval(const char* str) {
|
||||||
|
Time result = parse_time(str);
|
||||||
|
|
||||||
|
if (result.first == 0)
|
||||||
|
throw torrent::input_error("Could not parse interval.");
|
||||||
|
|
||||||
|
return result.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandScheduler::Time
|
||||||
|
CommandScheduler::parse_time(const char* str) {
|
||||||
|
Time result(0, 0);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
char* pos;
|
||||||
|
result.first++;
|
||||||
|
result.second += strtol(str, &pos, 10);
|
||||||
|
|
||||||
|
if (pos == str || result.second < 0)
|
||||||
|
return Time(0, 0);
|
||||||
|
|
||||||
|
while (std::isspace(*pos))
|
||||||
|
++pos;
|
||||||
|
|
||||||
|
if (*pos == '\0')
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (*pos != ':' || result.first > 3)
|
||||||
|
return Time(0, 0);
|
||||||
|
|
||||||
|
if (result.first < 3)
|
||||||
|
result.second *= 60;
|
||||||
|
else
|
||||||
|
result.second *= 24;
|
||||||
|
|
||||||
|
str = pos + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ class CommandSchedulerItem;
|
|||||||
class CommandScheduler : public std::vector<CommandSchedulerItem*> {
|
class CommandScheduler : public std::vector<CommandSchedulerItem*> {
|
||||||
public:
|
public:
|
||||||
typedef rak::function1<void, const std::string&> SlotString;
|
typedef rak::function1<void, const std::string&> SlotString;
|
||||||
|
typedef std::pair<int, int> Time;
|
||||||
typedef std::vector<CommandSchedulerItem*> base_type;
|
typedef std::vector<CommandSchedulerItem*> base_type;
|
||||||
|
|
||||||
using base_type::value_type;
|
using base_type::value_type;
|
||||||
@@ -67,6 +68,11 @@ public:
|
|||||||
iterator insert(const std::string& key);
|
iterator insert(const std::string& key);
|
||||||
void erase(iterator itr);
|
void erase(iterator itr);
|
||||||
|
|
||||||
|
static uint32_t parse_absolute(const char* str);
|
||||||
|
static uint32_t parse_interval(const char* str);
|
||||||
|
|
||||||
|
static Time parse_time(const char* str);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void call_item(value_type item);
|
void call_item(value_type item);
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,8 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <torrent/exceptions.h>
|
||||||
|
|
||||||
#include "command_scheduler_item.h"
|
#include "command_scheduler_item.h"
|
||||||
|
|
||||||
CommandSchedulerItem::~CommandSchedulerItem() {
|
CommandSchedulerItem::~CommandSchedulerItem() {
|
||||||
@@ -43,17 +45,40 @@ CommandSchedulerItem::~CommandSchedulerItem() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CommandSchedulerItem::enable(uint32_t first) {
|
CommandSchedulerItem::enable(rak::timer t) {
|
||||||
|
if (t == rak::timer())
|
||||||
|
throw torrent::internal_error("CommandSchedulerItem::enable() t == rak::timer().");
|
||||||
|
|
||||||
if (is_queued())
|
if (is_queued())
|
||||||
disable();
|
disable();
|
||||||
|
|
||||||
// If 'first' is zero then we execute the task
|
// If 'first' is zero then we execute the task
|
||||||
// immediately. ''interval()'' will not return zero so we never end
|
// immediately. ''interval()'' will not return zero so we never end
|
||||||
// up in an infinit loop.
|
// up in an infinit loop.
|
||||||
priority_queue_insert(&taskScheduler, &m_task, (cachedTime + ((int64_t)first * 1000000)).round_seconds());
|
m_timeScheduled = t;
|
||||||
|
priority_queue_insert(&taskScheduler, &m_task, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CommandSchedulerItem::disable() {
|
CommandSchedulerItem::disable() {
|
||||||
|
m_timeScheduled = rak::timer();
|
||||||
priority_queue_erase(&taskScheduler, &m_task);
|
priority_queue_erase(&taskScheduler, &m_task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rak::timer
|
||||||
|
CommandSchedulerItem::next_time_scheduled() const {
|
||||||
|
if (m_interval == 0)
|
||||||
|
return rak::timer();
|
||||||
|
|
||||||
|
if (m_timeScheduled == rak::timer())
|
||||||
|
throw torrent::internal_error("CommandSchedulerItem::next_time_scheduled() m_timeScheduled == rak::timer().");
|
||||||
|
|
||||||
|
rak::timer next = m_timeScheduled;
|
||||||
|
|
||||||
|
// This should be done in a non-looping manner.
|
||||||
|
do {
|
||||||
|
next += rak::timer(m_interval) * 1000000;
|
||||||
|
} while (next <= cachedTime.round_seconds());
|
||||||
|
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|||||||
@@ -48,8 +48,7 @@ public:
|
|||||||
|
|
||||||
bool is_queued() const { return m_task.is_queued(); }
|
bool is_queued() const { return m_task.is_queued(); }
|
||||||
|
|
||||||
//void enable() { enable(interval()); }
|
void enable(rak::timer t);
|
||||||
void enable(uint32_t first);
|
|
||||||
void disable();
|
void disable();
|
||||||
|
|
||||||
const std::string& key() const { return m_key; }
|
const std::string& key() const { return m_key; }
|
||||||
@@ -61,6 +60,9 @@ public:
|
|||||||
uint32_t interval() const { return m_interval; }
|
uint32_t interval() const { return m_interval; }
|
||||||
void set_interval(uint32_t v) { m_interval = v; }
|
void set_interval(uint32_t v) { m_interval = v; }
|
||||||
|
|
||||||
|
rak::timer time_scheduled() const { return m_timeScheduled; }
|
||||||
|
rak::timer next_time_scheduled() const;
|
||||||
|
|
||||||
void set_slot(Slot::base_type* s) { m_task.set_slot(s); }
|
void set_slot(Slot::base_type* s) { m_task.set_slot(s); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -71,6 +73,7 @@ private:
|
|||||||
std::string m_command;
|
std::string m_command;
|
||||||
|
|
||||||
uint32_t m_interval;
|
uint32_t m_interval;
|
||||||
|
rak::timer m_timeScheduled;
|
||||||
|
|
||||||
rak::priority_item m_task;
|
rak::priority_item m_task;
|
||||||
|
|
||||||
|
|||||||
@@ -197,20 +197,23 @@ apply_encoding_list(Control* m, const std::string& arg) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
apply_schedule(Control* m, const std::string& arg) {
|
apply_schedule(Control* m, const std::string& arg) {
|
||||||
int first;
|
|
||||||
int interval;
|
|
||||||
char key[21];
|
char key[21];
|
||||||
|
char bufAbsolute[21];
|
||||||
|
char bufInterval[21];
|
||||||
char command[2048];
|
char command[2048];
|
||||||
|
|
||||||
if (std::sscanf(arg.c_str(), "%20[^,],%i,%i,%2047[^\n]", key, &first, &interval, command) != 4)
|
if (std::sscanf(arg.c_str(), "%20[^,],%20[^,],%20[^,],%2047[^\n]", key, bufAbsolute, bufInterval, command) != 4)
|
||||||
throw torrent::input_error("Invalid arguments to command.");
|
throw torrent::input_error("Invalid arguments to command.");
|
||||||
|
|
||||||
|
uint32_t absolute = CommandScheduler::parse_absolute(bufAbsolute);
|
||||||
|
uint32_t interval = CommandScheduler::parse_interval(bufInterval);
|
||||||
|
|
||||||
CommandSchedulerItem* item = *m->command_scheduler()->insert(rak::trim(std::string(key)));
|
CommandSchedulerItem* item = *m->command_scheduler()->insert(rak::trim(std::string(key)));
|
||||||
|
|
||||||
item->set_command(rak::trim(std::string(command)));
|
item->set_command(rak::trim(std::string(command)));
|
||||||
item->set_interval(interval);
|
item->set_interval(interval);
|
||||||
|
|
||||||
item->enable(first);
|
item->enable((cachedTime + rak::timer(absolute) * 1000000).round_seconds());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -245,6 +248,8 @@ initialize_option_handler(Control* c) {
|
|||||||
variables->insert("max_open_files", new utils::VariableSlotValue<int, uint32_t>(NULL, rak::ptr_fn(&torrent::set_max_open_files), "%i"));
|
variables->insert("max_open_files", new utils::VariableSlotValue<int, uint32_t>(NULL, rak::ptr_fn(&torrent::set_max_open_files), "%i"));
|
||||||
variables->insert("max_open_sockets", new utils::VariableSlotValue<int, uint32_t>(NULL, rak::ptr_fn(&torrent::set_max_open_sockets), "%i"));
|
variables->insert("max_open_sockets", new utils::VariableSlotValue<int, uint32_t>(NULL, rak::ptr_fn(&torrent::set_max_open_sockets), "%i"));
|
||||||
|
|
||||||
|
variables->insert("print", new utils::VariableSlotString<>(NULL, rak::mem_fn(control->core(), &core::Manager::push_log)));
|
||||||
|
|
||||||
// Old.
|
// Old.
|
||||||
variables->insert("port_range", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_port_range, c)));
|
variables->insert("port_range", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_port_range, c)));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user