]> git.ipfire.org Git - thirdparty/snapper.git/commitdiff
- work on dbus interface
authorArvin Schnell <aschnell@suse.de>
Mon, 21 May 2012 15:56:20 +0000 (17:56 +0200)
committerArvin Schnell <aschnell@suse.de>
Mon, 21 May 2012 15:56:20 +0000 (17:56 +0200)
12 files changed:
client/Makefile.am
client/cleanup.cc [new file with mode: 0644]
client/cleanup.h [new file with mode: 0644]
client/commands.cc
client/commands.h
client/snapper.cc
client/types.cc
client/types.h
doc/snapper.8.in
examples/python/list.py
server/Types.cc
server/snapperd.cc

index 1ea75e60efe3932bb0bd55859122f14ccfe5e33c..adcf025b1eddecc5b5be5205f326dbfd166900e8 100644 (file)
@@ -12,7 +12,8 @@ bin_PROGRAMS = snapper
 snapper_SOURCES =                      \
        snapper.cc                      \
        types.cc        types.h         \
-       commands.cc     commands.h
+       commands.cc     commands.h      \
+       cleanup.cc      cleanup.h
 
 snapper_LDADD = ../snapper/libsnapper.la utils/libutils.la ../dbus/libdbus.la -ldbus-1
 
diff --git a/client/cleanup.cc b/client/cleanup.cc
new file mode 100644 (file)
index 0000000..782e58b
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) [2011-2012] Novell, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, contact Novell, Inc.
+ *
+ * To contact Novell about this file by physical or electronic mail, you may
+ * find current contact information at www.novell.com.
+ */
+
+
+#include <algorithm>
+
+#include "commands.h"
+
+
+using namespace std;
+
+
+struct younger_than
+{
+    younger_than(time_t t)
+       : t(t) {}
+    bool operator()(XSnapshots::const_iterator it)
+       { return it->getDate() > t; }
+    const time_t t;
+};
+
+
+// Removes snapshots younger than min_age from tmp
+void
+filter1(list<XSnapshots::const_iterator>& tmp, time_t min_age)
+{
+    tmp.remove_if(younger_than(time(NULL) - min_age));
+}
+
+
+// Removes pre and post snapshots from tmp that do have a corresponding
+// snapshot but which is not included in tmp.
+void
+filter2(const XSnapshots& snapshots, list<XSnapshots::const_iterator>& tmp)
+{
+    list<XSnapshots::const_iterator> ret;
+
+    for (list<XSnapshots::const_iterator>::const_iterator it1 = tmp.begin(); it1 != tmp.end(); ++it1)
+    {
+       if ((*it1)->getType() == XPRE)
+       {
+           XSnapshots::const_iterator it2 = snapshots.findPost(*it1);
+           if (it2 != snapshots.end())
+           {
+               if (find(tmp.begin(), tmp.end(), it2) == tmp.end())
+                   continue;
+           }
+       }
+
+       if ((*it1)->getType() == XPOST)
+       {
+           XSnapshots::const_iterator it2 = snapshots.findPre(*it1);
+           if (it2 != snapshots.end())
+           {
+               if (find(tmp.begin(), tmp.end(), it2) == tmp.end())
+                   continue;
+           }
+       }
+
+       ret.push_back(*it1);
+    }
+
+    swap(ret, tmp);
+}
+
+
+bool
+do_cleanup_number(DBus::Connection& conn, const string& config_name)
+{
+    time_t min_age = 1800;
+    size_t limit = 50;
+
+    /*
+    TODO
+    string val;
+    if (config->getValue("NUMBER_MIN_AGE", val))
+       val >> min_age;
+    if (config->getValue("NUMBER_LIMIT", val))
+       val >> limit;
+    */
+
+    XSnapshots snapshots = command_list_xsnapshots(conn, config_name);
+
+    list<XSnapshots::const_iterator> tmp;
+
+    for (XSnapshots::const_iterator it = snapshots.begin(); it != snapshots.end(); ++it)
+    {
+       if (it->getCleanup() == "number")
+           tmp.push_back(it);
+    }
+
+    if (tmp.size() > limit)
+    {
+       list<XSnapshots::const_iterator>::iterator it = tmp.end();
+       advance(it, - limit);
+       tmp.erase(it, tmp.end());
+
+       filter1(tmp, min_age);
+       filter2(snapshots, tmp);
+
+       for (list<XSnapshots::const_iterator>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
+           command_delete_xsnapshot(conn, config_name, (*it)->getNum());
+    }
+
+    return true;
+}
+
+
+bool
+is_first(list<XSnapshots::const_iterator>::const_iterator first,
+        list<XSnapshots::const_iterator>::const_iterator last,
+        XSnapshots::const_iterator it1,
+        std::function<bool(const struct tm& tmp1, const struct tm& tmp2)> pred)
+{
+    time_t t1 = it1->getDate();
+    struct tm tmp1;
+    localtime_r(&t1, &tmp1);
+
+    for (list<XSnapshots::const_iterator>::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))
+           return true;
+
+       if (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<XSnapshots::const_iterator>::const_iterator first,
+               list<XSnapshots::const_iterator>::const_iterator last,
+               XSnapshots::const_iterator it1)
+{
+    return is_first(first, last, it1, equal_year);
+}
+
+bool
+is_first_monthly(list<XSnapshots::const_iterator>::const_iterator first,
+                list<XSnapshots::const_iterator>::const_iterator last,
+                XSnapshots::const_iterator it1)
+{
+    return is_first(first, last, it1, equal_month);
+}
+
+bool
+is_first_daily(list<XSnapshots::const_iterator>::const_iterator first,
+              list<XSnapshots::const_iterator>::const_iterator last,
+              XSnapshots::const_iterator it1)
+{
+    return is_first(first, last, it1, equal_day);
+}
+
+bool
+is_first_hourly(list<XSnapshots::const_iterator>::const_iterator first,
+               list<XSnapshots::const_iterator>::const_iterator last,
+               XSnapshots::const_iterator it1)
+{
+    return is_first(first, last, it1, equal_hour);
+}
+
+
+bool
+do_cleanup_timeline(DBus::Connection& conn, const string& config_name)
+{
+    time_t min_age = 1800;
+    size_t limit_hourly = 10;
+    size_t limit_daily = 10;
+    size_t limit_monthly = 10;
+    size_t limit_yearly = 10;
+
+    /*
+    TODO
+    string val;
+    if (config->getValue("TIMELINE_MIN_AGE", val))
+       val >> min_age;
+    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;
+    */
+
+    size_t num_hourly = 0;
+    size_t num_daily = 0;
+    size_t num_monthly = 0;
+    size_t num_yearly = 0;
+
+    XSnapshots snapshots = command_list_xsnapshots(conn, config_name);
+
+    list<XSnapshots::const_iterator> tmp;
+
+    for (XSnapshots::const_iterator it = snapshots.begin(); it != snapshots.end(); ++it)
+    {
+       if (it->getCleanup() == "timeline")
+           tmp.push_front(it);
+    }
+
+    list<XSnapshots::const_iterator>::iterator it = tmp.begin();
+    while (it != tmp.end())
+    {
+       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;
+       }
+    }
+
+    tmp.reverse();
+
+    filter1(tmp, min_age);
+    filter2(snapshots, tmp);
+
+    for (list<XSnapshots::const_iterator>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
+       command_delete_xsnapshot(conn, config_name, (*it)->getNum());
+
+    return true;
+}
+
+
+bool
+do_cleanup_empty_pre_post(DBus::Connection& conn, const string& config_name)
+{
+    time_t min_age = 1800;
+
+    /*
+    TODO
+    string val;
+    if (config->getValue("EMPTY_PRE_POST_MIN_AGE", val))
+       val >> min_age;
+    */
+
+    XSnapshots snapshots = command_list_xsnapshots(conn, config_name);
+
+    list<XSnapshots::const_iterator> tmp;
+
+    for (XSnapshots::const_iterator it1 = snapshots.begin(); it1 != snapshots.end(); ++it1)
+    {
+       if (it1->getType() == XPRE)
+       {
+           XSnapshots::const_iterator it2 = snapshots.findPost(it1);
+
+           if (it2 != snapshots.end())
+           {
+               command_create_xcomparison(conn, config_name, it1->getNum(), it2->getNum());
+
+               list<XFile> files = command_get_xfiles(conn, config_name, it1->getNum(), it2->getNum());
+
+               if (files.empty())
+               {
+                   tmp.push_back(it1);
+                   tmp.push_back(it2);
+               }
+           }
+       }
+    }
+
+    filter1(tmp, min_age);
+    filter2(snapshots, tmp);
+
+    for (list<XSnapshots::const_iterator>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
+       command_delete_xsnapshot(conn, config_name, (*it)->getNum());
+
+    return true;
+}
diff --git a/client/cleanup.h b/client/cleanup.h
new file mode 100644 (file)
index 0000000..0c5e3f0
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) [2011-2012] Novell, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, contact Novell, Inc.
+ *
+ * To contact Novell about this file by physical or electronic mail, you may
+ * find current contact information at www.novell.com.
+ */
+
+
+bool
+do_cleanup_number(DBus::Connection& conn, const string& config_name);
+
+bool
+do_cleanup_timeline(DBus::Connection& conn, const string& config_name);
+
+bool
+do_cleanup_empty_pre_post(DBus::Connection& conn, const string& config_name);
index a529a23cc82013e34a70cbcd0cbfecb9b630d3aa..9a7fae9738d8c9ba81985f4d61c86a361438a22a 100644 (file)
@@ -285,16 +285,3 @@ command_get_xundostatistic(DBus::Connection& conn, const string& config_name, un
 
     return ret;
 }
-
-
-void
-command_xcleanup(DBus::Connection& conn, const string& config_name, const string& algorithm)
-
-{
-    DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "Cleanup");
-
-    DBus::Hoho hoho(call);
-    hoho << config_name << algorithm;
-
-    DBus::Message reply = conn.send_and_reply_and_block(call);
-}
index 0f6a7b1e422d0c805d9726b70e2b243cef786938..fa6889f8e8eee4efa9f27ed6bc3984aecbf35662 100644 (file)
@@ -94,6 +94,3 @@ command_set_xundo_all(DBus::Connection& conn, const string& config_name, unsigne
 XUndoStatistic
 command_get_xundostatistic(DBus::Connection& conn, const string& config_name, unsigned int number1,
                           unsigned int number2);
-
-void
-command_xcleanup(DBus::Connection& conn, const string& config_name, const string& algorithm);
index 6a45678386d0c2afa994fc2417b5a8b8338eabbe..50af7a71be56ffea726a61f688a8038e8ab16503 100644 (file)
@@ -37,6 +37,7 @@
 #include "utils/GetOpts.h"
 
 #include "commands.h"
+#include "cleanup.h"
 
 using namespace snapper;
 using namespace std;
@@ -50,7 +51,6 @@ GetOpts getopts;
 bool quiet = false;
 bool verbose = false;
 string config_name = "root";
-bool disable_filters = false;
 
 
 unsigned int
@@ -1031,9 +1031,17 @@ command_cleanup(DBus::Connection& conn)
 
     string cleanup = getopts.popArg();
 
-    if (cleanup == "number" || cleanup == "timeline" || cleanup == "empty-pre-post")
+    if (cleanup == "number")
     {
-       command_xcleanup(conn, config_name, cleanup);
+       do_cleanup_number(conn, config_name);
+    }
+    else if (cleanup == "timeline")
+    {
+       do_cleanup_timeline(conn, config_name);
+    }
+    else if (cleanup == "empty-pre-post")
+    {
+       do_cleanup_empty_pre_post(conn, config_name);
     }
     else
     {
@@ -1061,7 +1069,6 @@ help()
         << _("\t--verbose, -v\t\t\tIncrease verbosity.") << endl
         << _("\t--table-style, -t <style>\tTable style (integer).") << endl
         << _("\t--config, -c <name>\t\tSet name of config to use.") << endl
-        << _("\t--disable-filters\t\tDisable filters.") << endl
         << _("\t--version\t\t\tPrint version and exit.") << endl
         << endl;
 
@@ -1139,7 +1146,6 @@ main(int argc, char** argv)
        { "verbose",            no_argument,            0,      'v' },
        { "table-style",        required_argument,      0,      't' },
        { "config",             required_argument,      0,      'c' },
-       { "disable-filters",    no_argument,            0,      0 },
        { "version",            no_argument,            0,      0 },
        { "help",               no_argument,            0,      0 },
        { 0, 0, 0, 0 }
@@ -1173,9 +1179,6 @@ main(int argc, char** argv)
     if ((opt = opts.find("config")) != opts.end())
        config_name = opt->second;
 
-    if ((opt = opts.find("disable-filters")) != opts.end())
-       disable_filters = true;
-
     if ((opt = opts.find("version")) != opts.end())
     {
        cout << "snapper " << VERSION << endl;
index 40dd25e2c9940427ed821beb7104e8c493c6d762..ae110280c981b5b98976ddd04ec106b7dcaafcda 100644 (file)
 #include "types.h"
 
 
+XSnapshots::const_iterator
+XSnapshots::findPre(const_iterator post) const
+{
+    if (post == entries.end() || post->isCurrent() || post->getType() != XPOST)
+       throw;
+
+    for (const_iterator it = begin(); it != end(); ++it)
+    {
+       if (it->getType() == XPRE && it->getNum() == post->getPreNum())
+           return it;
+    }
+
+    return end();
+}
+
+
 XSnapshots::const_iterator
 XSnapshots::findPost(const_iterator pre) const
 {
@@ -49,7 +65,7 @@ XUndoStatistic::empty() const
 namespace DBus
 {
     const char* TypeInfo<XConfigInfo>::signature = "(ss)";
-    const char* TypeInfo<XSnapshot>::signature = "(uquusa{ss})";
+    const char* TypeInfo<XSnapshot>::signature = "(uquussa{ss})";
     const char* TypeInfo<XFile>::signature = "(ssb)";
     const char* TypeInfo<XUndo>::signature = "(sb)";
 
@@ -79,7 +95,7 @@ namespace DBus
     {
        hihi.open_recurse();
        hihi >> data.num >> data.type >> data.pre_num >> data.date >> data.description
-            >> data.userdata;
+            >> data.cleanup >> data.userdata;
        hihi.close_recurse();
        return hihi;
     }
index a6cec327332ff69dc757f6801f7d57a0223adc1d..80956af9a85efaa331a89378c08c09671d94e5f0 100644 (file)
@@ -77,6 +77,7 @@ struct XSnapshots
 
     const_iterator end() const { return entries.end(); }
 
+    const_iterator findPre(const_iterator post) const;
     const_iterator findPost(const_iterator pre) const;
 
     list<XSnapshot> entries;
index 2dea5dd8d7aa0ba58f7a7dbff7583211ac86cc66..06c44a0c3ce272266221023fa7de86be73eb8735 100644 (file)
@@ -85,9 +85,6 @@ Specifies table style. Table style is identified by an integer number.
 Use specified configuration instead of the default configuration. The default
 configuration is named "root".
 .TP
-.I \-\-disable\-filters
-Disable filters.
-.TP
 .I \-\-version
 Print version and exit.
 
index eab9f54be1c6df2917b4895b766bd1942a26d7e9..897a19db0fc52745e2c2a4631df37dc9a47d4de9 100755 (executable)
@@ -11,8 +11,8 @@ snapper = dbus.Interface(bus.get_object('org.opensuse.snapper', '/org/opensuse/s
 snapshots = snapper.ListSnapshots("root")
 
 for snapshot in snapshots:
-    print snapshot[0], snapshot[1], snapshot[2], snapshot[3], snapshot[4],
-    for k, v in snapshot[5].items():
+    print snapshot[0], snapshot[1], snapshot[2], snapshot[3], snapshot[4], snapshot[5],
+    for k, v in snapshot[6].items():
         print "%s=%s" % (k, v),
     print
 
index e5be7bfeab6e246ba272020915e976282642c385..8eca0a4499fab2a8428a353b371d3a16b075a1a7 100644 (file)
@@ -26,7 +26,7 @@
 namespace DBus
 {
     const char* TypeInfo<ConfigInfo>::signature = "(ss)";
-    const char* TypeInfo<Snapshot>::signature = "(uquusa{ss})";
+    const char* TypeInfo<Snapshot>::signature = "(uquussa{ss})";
     const char* TypeInfo<File>::signature = "(ssb)";
     const char* TypeInfo<Undo>::signature = "(sb)";
 
@@ -64,7 +64,7 @@ namespace DBus
     {
        hoho.open_struct();
        hoho << data.getNum() << data.getType() << data.getPreNum() << data.getDate()
-            << data.getDescription() << data.getUserdata();
+            << data.getDescription() << data.getCleanup() << data.getUserdata();
        hoho.close_struct();
        return hoho;
     }
index 65ad9b56d5265508f93c26b15f1ec0cc0cf0b1c5..caeecd12932b3e74ce5ab5e0a55943136eb9a048 100644 (file)
@@ -174,11 +174,6 @@ reply_to_introspect(DBus::Connection& conn, DBus::Message& msg)
        "      <arg name='number-delete' type='u' direction='out'/>\n"
        "    </method>\n"
 
-       "    <method name='Cleanup'>\n"
-       "      <arg name='config-name' type='s' direction='in'/>\n"
-       "      <arg name='algorithm' type='s' direction='in'/>\n"
-       "    </method>\n"
-
        "  </interface>\n"
        "</node>\n";
 
@@ -822,42 +817,6 @@ reply_to_command_get_undo_statistics(DBus::Connection& conn, DBus::Message& msg)
 }
 
 
-void
-reply_to_command_cleanup(DBus::Connection& conn, DBus::Message& msg)
-{
-    string config_name;
-    string algorithm;
-
-    DBus::Hihi hihi(msg);
-    hihi >> config_name >> algorithm;
-
-    y2mil("GetDiff config_name:" << config_name << " algorithm:" << algorithm);
-
-    check_permission(conn, msg, config_name);
-
-    Snapper* snapper = getSnapper(config_name);
-
-    // TODO: at least the last algorithm must be in a seperate thread
-
-    if (algorithm == "number")
-    {
-       snapper->doCleanupNumber();
-    }
-    else if (algorithm == "timeline")
-    {
-       snapper->doCleanupTimeline();
-    }
-    else if (algorithm == "empty-pre-post")
-    {
-       snapper->doCleanupEmptyPrePost();
-    }
-
-    DBus::MessageMethodReturn reply(msg);
-
-    conn.send(reply);
-}
-
-
 void
 reply_to_command_debug(DBus::Connection& conn, DBus::Message& msg)
 {
@@ -956,8 +915,6 @@ dispatch(DBus::Connection& conn, DBus::Message& msg)
            reply_to_command_set_undo_all(conn, msg);
        else if (msg.is_method_call(INTERFACE, "GetUndoStatistic"))
            reply_to_command_get_undo_statistics(conn, msg);
-       else if (msg.is_method_call(INTERFACE, "Cleanup"))
-           reply_to_command_cleanup(conn, msg);
        else if (msg.is_method_call(INTERFACE, "Debug"))
            reply_to_command_debug(conn, msg);
        else