From: Arvin Schnell Date: Wed, 2 Mar 2011 15:41:01 +0000 (+0100) Subject: - implemented timeline cleanup X-Git-Tag: v0.1.3~442 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a8c7ec5fa0003e04fca5b38840005f2ef47bfa77;p=thirdparty%2Fsnapper.git - implemented timeline cleanup --- diff --git a/data/example-config b/data/example-config index 249f8817..2ca422a4 100644 --- a/data/example-config +++ b/data/example-config @@ -16,3 +16,9 @@ TIMELINE_CREATE="yes" # cleanup hourly snapshots after some time TIMELINE_CLEANUP="yes" +# limits for timeline cleanup +TIMELINE_LIMIT_HOURLY="10" +TIMELINE_LIMIT_DAILY="10" +TIMELINE_LIMIT_MONTHLY="10" +TIMELINE_LIMIT_YEARLY="10" + diff --git a/snapper/Snapper.cc b/snapper/Snapper.cc index b85f2113..1c483934 100644 --- a/snapper/Snapper.cc +++ b/snapper/Snapper.cc @@ -187,11 +187,11 @@ namespace snapper // Removes pre and post snapshots from tmp that do have a corresponding // snapshot but which is not included in tmp. void - Snapper::filter1(vector& tmp1) + Snapper::filter1(list& tmp1) { - vector ret; + list ret; - for (vector::const_iterator it1 = tmp1.begin(); it1 != tmp1.end(); ++it1) + for (list::const_iterator it1 = tmp1.begin(); it1 != tmp1.end(); ++it1) { if ((*it1)->getType() == PRE) { @@ -231,7 +231,7 @@ namespace snapper y2mil("limit:" << limit); - vector tmp; + list tmp; for (Snapshots::iterator it = snapshots.begin(); it != snapshots.end(); ++it) { @@ -241,12 +241,15 @@ namespace snapper if (tmp.size() > limit) { - tmp.erase(tmp.end() - limit, tmp.end()); + list::iterator it = tmp.end(); + advance(it, - limit); + tmp.erase(it, tmp.end()); + filter1(tmp); y2mil("deleting " << tmp.size() << " snapshots"); - for (vector::iterator it = tmp.begin(); it != tmp.end(); ++it) + for (list::iterator it = tmp.begin(); it != tmp.end(); ++it) deleteSnapshot(*it); } @@ -254,31 +257,162 @@ namespace snapper } + bool + is_first(list::const_iterator first, + list::const_iterator last, + Snapshots::const_iterator it1, + std::function pred) + { + time_t t1 = it1->getDate(); + struct tm tmp1; + localtime_r(&t1, &tmp1); + + for (list::const_iterator it2 = first; it2 != last; ++it2) + { + if (it1 == *it2) + continue; + + time_t t2 = (*it2)->getDate(); + struct tm tmp2; + localtime_r(&t2, &tmp2); + + if (pred(tmp1, tmp2) && t1 > t2) + return false; + } + + return true; + } + + + bool + equal_year(const struct tm& tmp1, const struct tm& tmp2) + { + return tmp1.tm_year == tmp2.tm_year; + } + + bool + equal_month(const struct tm& tmp1, const struct tm& tmp2) + { + return equal_year(tmp1, tmp2) && tmp1.tm_mon == tmp2.tm_mon; + } + + bool + equal_day(const struct tm& tmp1, const struct tm& tmp2) + { + return equal_month(tmp1, tmp2) && tmp1.tm_mday == tmp2.tm_mday; + } + + bool + equal_hour(const struct tm& tmp1, const struct tm& tmp2) + { + return equal_day(tmp1, tmp2) && tmp1.tm_hour == tmp2.tm_hour; + } + + + bool + is_first_yearly(list::const_iterator first, + list::const_iterator last, + Snapshots::const_iterator it1) + { + return is_first(first, last, it1, equal_year); + } + + bool + is_first_monthly(list::const_iterator first, + list::const_iterator last, + Snapshots::const_iterator it1) + { + return is_first(first, last, it1, equal_month); + } + + bool + is_first_daily(list::const_iterator first, + list::const_iterator last, + Snapshots::const_iterator it1) + { + return is_first(first, last, it1, equal_day); + } + + bool + is_first_hourly(list::const_iterator first, + list::const_iterator last, + Snapshots::const_iterator it1) + { + return is_first(first, last, it1, equal_hour); + } + + bool Snapper::doCleanupTimeline() { - // TODO: hourly, daily, monthly, yearly algorithm + size_t limit_hourly = 10; + size_t limit_daily = 10; + size_t limit_monthly = 10; + size_t limit_yearly = 10; + + string val; + if (config->getValue("TIMELINE_LIMIT_HOURLY", val)) + val >> limit_hourly; + if (config->getValue("TIMELINE_LIMIT_DAILY", val)) + val >> limit_daily; + if (config->getValue("TIMELINE_LIMIT_MONTHLY", val)) + val >> limit_monthly; + if (config->getValue("TIMELINE_LIMIT_YEARLY", val)) + val >> limit_yearly; + + y2mil("limit_hourly:" << limit_hourly << " limit_daily:" << limit_daily << + " limit_monthly:" << limit_monthly << " limit_yearly:" << limit_yearly); - size_t limit = 30; + size_t num_hourly = 0; + size_t num_daily = 0; + size_t num_monthly = 0; + size_t num_yearly = 0; - vector tmp; + list tmp; for (Snapshots::iterator it = snapshots.begin(); it != snapshots.end(); ++it) { if (it->getCleanup() == "timeline") - tmp.push_back(it); + tmp.push_front(it); } - if (tmp.size() > limit) + list::iterator it = tmp.begin(); + while (it != tmp.end()) { - tmp.erase(tmp.end() - limit, tmp.end()); - filter1(tmp); + if (num_hourly < limit_hourly && is_first_hourly(it, tmp.end(), *it)) + { + ++num_hourly; + it = tmp.erase(it); + } + else if (num_daily < limit_daily && is_first_daily(it, tmp.end(), *it)) + { + ++num_daily; + it = tmp.erase(it); + } + else if (num_monthly < limit_monthly && is_first_monthly(it, tmp.end(), *it)) + { + ++num_monthly; + it = tmp.erase(it); + } + else if (num_yearly < limit_yearly && is_first_yearly(it, tmp.end(), *it)) + { + ++num_yearly; + it = tmp.erase(it); + } + else + { + ++it; + } + } - y2mil("deleting " << tmp.size() << " snapshots"); + tmp.reverse(); - for (vector::iterator it = tmp.begin(); it != tmp.end(); ++it) - deleteSnapshot(*it); - } + filter1(tmp); + + y2mil("deleting " << tmp.size() << " snapshots"); + + for (list::iterator it = tmp.begin(); it != tmp.end(); ++it) + deleteSnapshot(*it); return true; } diff --git a/snapper/Snapper.h b/snapper/Snapper.h index 22c3b91d..a10ea225 100644 --- a/snapper/Snapper.h +++ b/snapper/Snapper.h @@ -88,7 +88,7 @@ namespace snapper private: - void filter1(vector& tmp1); + void filter1(list& tmp1); const string config_name;