return files.doRollback();
}
+
+ bool
+ Snapper::doCleanupAmount()
+ {
+ size_t n = 10; // TODO
+
+ y2mil("n:" << n);
+
+ vector<Snapshots::iterator> tmp;
+
+ for (Snapshots::iterator it = snapshots.begin(); it != snapshots.end(); ++it)
+ {
+ if (it->getCleanup() == "amount")
+ tmp.push_back(it);
+ }
+
+ y2mil("filtered " << tmp.size() << " snapshots");
+
+ if (tmp.size() > n)
+ {
+ tmp.erase(tmp.end() - n, tmp.end());
+
+ // TODO: only remove pre and post together
+
+ y2mil("deleting " << tmp.size() << " snapshots");
+
+ for (vector<Snapshots::iterator>::iterator it = tmp.begin(); it != tmp.end(); ++it)
+ {
+ deleteSnapshot(*it);
+ }
+ }
+
+ return true;
+ }
+
+
+ bool
+ Snapper::doCleanupTimeline()
+ {
+ // TODO: hourly, daily, monthly, yearly algorithm
+
+ return false;
+ }
+
}
if (!snapshot.description.empty())
s << " description:\"" << snapshot.description << "\"";
+ if (!snapshot.cleanup.empty())
+ s << " cleanup:\"" << snapshot.cleanup << "\"";
+
return s;
}
void
- Snapshot::setDescription(const string& desc)
+ Snapshot::setDescription(const string& val)
{
- description = desc;
+ description = val;
+ writeInfo();
+ }
+
+
+ void
+ Snapshot::setCleanup(const string& val)
+ {
+ cleanup = val;
writeInfo();
}
getChildValue(node, "pre_num", snapshot.pre_num);
+ getChildValue(node, "cleanup", snapshot.cleanup);
+
if (!checkDir(snapshot.snapshotDir()))
{
y2err("snapshot directory does not exist. not adding snapshot " << num);
if (type == POST)
setChildValue(node, "pre_num", pre_num);
+ if (!cleanup.empty())
+ setChildValue(node, "cleanup", cleanup);
+
xml.save(baseDir() + "/info.xml");
return true;
friend class Snapshots;
- Snapshot(const Snapper* snapper) : snapper(snapper), type(SINGLE), num(0), pre_num(0) {}
+ Snapshot(const Snapper* snapper)
+ : snapper(snapper), type(SINGLE), num(0), date((time_t)(-1)), pre_num(0) {}
SnapshotType getType() const { return type; }
unsigned int getPreNum() const { return pre_num; }
+ void setCleanup(const string& cleanup);
+ string getCleanup() const { return cleanup; }
+
string baseDir() const;
string snapshotDir() const;
unsigned int pre_num; // valid only for type=POST
+ string cleanup;
+
bool writeInfo() const;
bool createFilesystemSnapshot() const;
bool deleteFilesystemSnapshot() const;
typedef list<Snapshot>::iterator iterator;
typedef list<Snapshot>::const_iterator const_iterator;
+ iterator begin() { return entries.begin(); }
const_iterator begin() const { return entries.begin(); }
+
+ iterator end() { return entries.end(); }
const_iterator end() const { return entries.end(); }
iterator find(unsigned int num);
header.add("#");
header.add("Pre #");
header.add("Date");
+ header.add("Cleanup");
header.add("Description");
table.setHeader(header);
row.add(decString(it->getNum()));
row.add(it->getType() == POST ? decString(it->getPreNum()) : "");
row.add(it->isCurrent() ? "" : datetime(it->getDate(), false, false));
+ row.add(it->getCleanup());
row.add(it->getDescription());
table.add(row);
}
<< _("\t--pre-number <number>\t\tNumber of corresponding pre snapshot.") << endl
<< _("\t--description, -d <description>\tDescription for snapshot.") << endl
<< _("\t--print-number, -p\t\tPrint number of created snapshot.") << endl
+ << _("\t--cleanup-algorithm, -c\t\tCleanup algorithm for snapshot.") << endl
<< endl;
}
{ "pre-number", required_argument, 0, 0 },
{ "description", required_argument, 0, 'd' },
{ "print-number", no_argument, 0, 'p' },
+ { "cleanup", required_argument, 0, 'c' },
{ 0, 0, 0, 0 }
};
Snapshots::const_iterator snap1;
string description;
bool print_number = false;
+ string cleanup;
GetOpts::parsed_opts::const_iterator it;
if ((it = opts.find("print-number")) != opts.end())
print_number = true;
+ if ((it = opts.find("cleanup")) != opts.end())
+ cleanup = it->second;
+
switch (type)
{
case SINGLE: {
- Snapshots::const_iterator snap1 = sh->createSingleSnapshot(description);
+ Snapshots::iterator snap1 = sh->createSingleSnapshot(description);
+ snap1->setCleanup(cleanup);
if (print_number)
cout << snap1->getNum() << endl;
} break;
case PRE: {
- Snapshots::const_iterator snap1 = sh->createPreSnapshot(description);
+ Snapshots::iterator snap1 = sh->createPreSnapshot(description);
+ snap1->setCleanup(cleanup);
if (print_number)
cout << snap1->getNum() << endl;
} break;
case POST: {
- Snapshots::const_iterator snap2 = sh->createPostSnapshot(snap1);
+ Snapshots::iterator snap2 = sh->createPostSnapshot(snap1);
+ snap2->setCleanup(cleanup);
if (print_number)
cout << snap2->getNum() << endl;
sh->startBackgroundComparsion(snap1, snap2);
}
+void
+help_cleanup()
+{
+ cout << _(" Cleanup snapshots:") << endl
+ << _("\tsnapper cleanup <cleanup-algorithm>") << endl
+ << endl;
+}
+
+
+void
+command_cleanup()
+{
+ const struct option options[] = {
+ { 0, 0, 0, 0 }
+ };
+
+ GetOpts::parsed_opts opts = getopts.parse("cleanup", options);
+ if (getopts.numArgs() != 1)
+ {
+ cerr << _("Command 'cleanup' needs one arguments.") << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ string cleanup = getopts.popArg();
+
+ if (cleanup == "amount")
+ {
+ sh->doCleanupAmount();
+ }
+ else if (cleanup == "timeline")
+ {
+ sh->doCleanupTimeline();
+ }
+ else
+ {
+ cerr << sformat(_("Unknown cleanup algorithm '%s'."), cleanup.c_str()) << endl;
+ exit(EXIT_FAILURE);
+ }
+}
+
+
void
command_help()
{
help_delete();
help_diff();
help_rollback();
+ help_cleanup();
}
cmds["delete"] = command_delete;
cmds["diff"] = command_diff;
cmds["rollback"] = command_rollback;
+ cmds["cleanup"] = command_cleanup;
cmds["help"] = command_help;
const struct option options[] = {