* 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:
rakshasa
2006-01-25 21:23:46 +00:00
parent 305e3bdf2b
commit c89ae513ef
6 changed files with 118 additions and 12 deletions
+2
View File
@@ -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 * (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 -= (const timer& t) { m_time -= t.m_time; return *this; }
+69 -4
View File
@@ -37,6 +37,7 @@
#include "config.h"
#include <algorithm>
#include <cstdlib>
#include <rak/functional.h>
#include <torrent/exceptions.h>
@@ -98,9 +99,73 @@ CommandScheduler::call_item(value_type item) {
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 (interval != 0)
item->enable(interval);
if (next == rak::timer()) {
// Remove from scheduler?
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;
}
}
+6
View File
@@ -46,6 +46,7 @@ class CommandSchedulerItem;
class CommandScheduler : public std::vector<CommandSchedulerItem*> {
public:
typedef rak::function1<void, const std::string&> SlotString;
typedef std::pair<int, int> Time;
typedef std::vector<CommandSchedulerItem*> base_type;
using base_type::value_type;
@@ -67,6 +68,11 @@ public:
iterator insert(const std::string& key);
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:
void call_item(value_type item);
+27 -2
View File
@@ -36,6 +36,8 @@
#include "config.h"
#include <torrent/exceptions.h>
#include "command_scheduler_item.h"
CommandSchedulerItem::~CommandSchedulerItem() {
@@ -43,17 +45,40 @@ CommandSchedulerItem::~CommandSchedulerItem() {
}
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())
disable();
// If 'first' is zero then we execute the task
// immediately. ''interval()'' will not return zero so we never end
// 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
CommandSchedulerItem::disable() {
m_timeScheduled = rak::timer();
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;
}
+5 -2
View File
@@ -48,8 +48,7 @@ public:
bool is_queued() const { return m_task.is_queued(); }
//void enable() { enable(interval()); }
void enable(uint32_t first);
void enable(rak::timer t);
void disable();
const std::string& key() const { return m_key; }
@@ -61,6 +60,9 @@ public:
uint32_t interval() const { return m_interval; }
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); }
private:
@@ -71,6 +73,7 @@ private:
std::string m_command;
uint32_t m_interval;
rak::timer m_timeScheduled;
rak::priority_item m_task;
+9 -4
View File
@@ -197,20 +197,23 @@ apply_encoding_list(Control* m, const std::string& arg) {
void
apply_schedule(Control* m, const std::string& arg) {
int first;
int interval;
char key[21];
char bufAbsolute[21];
char bufInterval[21];
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.");
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)));
item->set_command(rak::trim(std::string(command)));
item->set_interval(interval);
item->enable(first);
item->enable((cachedTime + rak::timer(absolute) * 1000000).round_seconds());
}
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_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.
variables->insert("port_range", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_port_range, c)));