Cleaned up the dynconf/history code by using a container template

This commit is contained in:
Jean-Francois Dockes
2018-05-31 10:37:34 +02:00
parent 7b5f701b1d
commit 3b6dd445e3
10 changed files with 110 additions and 113 deletions
+22 -30
View File
@@ -14,15 +14,15 @@
* Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "docseqhist.h"
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <cmath>
#include <list>
using std::list;
using std::vector;
#include "docseqhist.h"
#include "rcldb.h"
#include "fileudi.h"
#include "base64.h"
@@ -77,7 +77,7 @@ bool RclDHistoryEntry::decode(const string &value)
// Old style entry found, make an udi, using the fs udi maker
make_udi(fn, ipath, udi);
}
LOGDEB1("RclDHistoryEntry::decode: udi [" << (udi) << "]\n" );
LOGDEB1("RclDHistoryEntry::decode: udi [" << udi << "]\n");
return true;
}
@@ -89,54 +89,46 @@ bool RclDHistoryEntry::equal(const DynConfEntry& other)
bool historyEnterDoc(RclDynConf *dncf, const string& udi)
{
LOGDEB1("historyEnterDoc: [" << (udi) << "] into " << (dncf->getFilename()) << "\n" );
LOGDEB1("historyEnterDoc: [" << udi << "] into " << dncf->getFilename() <<
"\n");
RclDHistoryEntry ne(time(0), udi);
RclDHistoryEntry scratch;
return dncf->insertNew(docHistSubKey, ne, scratch, 200);
}
list<RclDHistoryEntry> getDocHistory(RclDynConf* dncf)
vector<RclDHistoryEntry> getDocHistory(RclDynConf* dncf)
{
return dncf->getList<RclDHistoryEntry>(docHistSubKey);
return dncf->getEntries<std::vector, RclDHistoryEntry>(docHistSubKey);
}
bool DocSequenceHistory::getDoc(int num, Rcl::Doc &doc, string *sh)
{
// Retrieve history list
if (!m_hist)
return false;
if (m_hlist.empty())
m_hlist = getDocHistory(m_hist);
if (m_history.empty())
m_history = getDocHistory(m_hist);
if (num < 0 || num >= (int)m_hlist.size())
if (num < 0 || num >= (int)m_history.size())
return false;
int skip;
if (m_prevnum >= 0 && num >= m_prevnum) {
skip = num - m_prevnum;
} else {
skip = num;
m_it = m_hlist.begin();
m_prevtime = -1;
}
m_prevnum = num;
while (skip--)
m_it++;
// We get the history oldest first, but our users expect newest first
RclDHistoryEntry& hentry = m_history[m_history.size() - 1 - num];
if (sh) {
if (m_prevtime < 0 ||
abs (float(m_prevtime) - float(m_it->unixtime)) > 86400) {
m_prevtime = m_it->unixtime;
time_t t = (time_t)(m_it->unixtime);
abs (float(m_prevtime) - float(hentry.unixtime)) > 86400) {
m_prevtime = hentry.unixtime;
time_t t = (time_t)(hentry.unixtime);
*sh = string(ctime(&t));
// Get rid of the final \n in ctime
sh->erase(sh->length()-1);
} else
} else {
sh->erase();
}
}
// For now history does not store an index id. Use empty doc as ref.
Rcl::Doc idxdoc;
bool ret = m_db->getDoc(m_it->udi, idxdoc, doc);
bool ret = m_db->getDoc(hentry.udi, idxdoc, doc);
if (!ret || doc.pc == -1) {
doc.url = "UNKNOWN";
doc.ipath = "";
@@ -156,8 +148,8 @@ Rcl::Db *DocSequenceHistory::getDb()
int DocSequenceHistory::getResCnt()
{
if (m_hlist.empty())
m_hlist = getDocHistory(m_hist);
return int(m_hlist.size());
if (m_history.empty())
m_history = getDocHistory(m_hist);
return int(m_history.size());
}
+5 -5
View File
@@ -18,6 +18,8 @@
#define _DOCSEQHIST_H_INCLUDED_
#include <time.h>
#include <vector>
#include "docseq.h"
#include "dynconf.h"
@@ -45,7 +47,7 @@ class RclDHistoryEntry : public DynConfEntry {
class DocSequenceHistory : public DocSequence {
public:
DocSequenceHistory(Rcl::Db *d, RclDynConf *h, const string &t)
: DocSequence(t), m_db(d), m_hist(h), m_prevnum(-1), m_prevtime(-1) {}
: DocSequence(t), m_db(d), m_hist(h) {}
virtual ~DocSequenceHistory() {}
virtual bool getDoc(int num, Rcl::Doc &doc, string *sh = 0);
@@ -57,11 +59,9 @@ protected:
private:
Rcl::Db *m_db;
RclDynConf *m_hist;
int m_prevnum;
time_t m_prevtime;
time_t m_prevtime{-1};
std::string m_description; // This is just an nls translated 'doc history'
std::list<RclDHistoryEntry> m_hlist;
std::list<RclDHistoryEntry>::const_iterator m_it;
std::vector<RclDHistoryEntry> m_history;
};
extern bool historyEnterDoc(RclDynConf *dncf, const string& udi);
+6 -19
View File
@@ -60,13 +60,13 @@ bool RclDynConf::insertNew(const string &sk, DynConfEntry &n, DynConfEntry &s,
for (it = names.begin(); it != names.end(); it++) {
string oval;
if (!m_data.get(*it, oval, sk)) {
LOGDEB("No data for " << ((*it)) << "\n" );
LOGDEB("No data for " << *it << "\n");
continue;
}
s.decode(oval);
if (s.equal(n)) {
LOGDEB("Erasing old entry\n" );
LOGDEB("Erasing old entry\n");
m_data.erase(*it, sk);
changed = true;
}
@@ -96,9 +96,9 @@ bool RclDynConf::insertNew(const string &sk, DynConfEntry &n, DynConfEntry &s,
string value;
n.encode(value);
LOGDEB1("Encoded value [" << (value) << "] (" << (value.size()) << ")\n" );
LOGDEB1("Encoded value [" << value << "] (" << value.size() << ")\n");
if (!m_data.set(string(nname), value, sk)) {
LOGERR("RclDHistory::insertNew: set failed\n" );
LOGERR("RclDHistory::insertNew: set failed\n");
return false;
}
return true;
@@ -110,15 +110,12 @@ bool RclDynConf::eraseAll(const string &sk)
LOGDEB("RclDynConf::eraseAll: not writable\n");
return false;
}
vector<string> names = m_data.getNames(sk);
vector<string>::const_iterator it;
for (it = names.begin(); it != names.end(); it++) {
m_data.erase(*it, sk);
for (const auto& nm : m_data.getNames(sk)) {
m_data.erase(nm, sk);
}
return true;
}
// Specialization for plain strings ///////////////////////////////////
bool RclDynConf::enterString(const string sk, const string value, int maxlen)
@@ -132,16 +129,6 @@ bool RclDynConf::enterString(const string sk, const string value, int maxlen)
return insertNew(sk, ne, scratch, maxlen);
}
list<string> RclDynConf::getStringList(const string sk)
{
list<RclSListEntry> el = getList<RclSListEntry>(sk);
list<string> sl;
for (list<RclSListEntry>::const_iterator it = el.begin();
it != el.end(); it++)
sl.push_back(it->value);
return sl;
}
#else
#include <string>
+35 -13
View File
@@ -41,6 +41,7 @@
#include <string>
#include <list>
#include <vector>
#include "conftree.h"
#include "base64.h"
@@ -110,34 +111,55 @@ class RclDynConf {
*/
bool insertNew(const std::string& sk, DynConfEntry &n, DynConfEntry &s,
int maxlen = -1);
template<typename Tp> std::list<Tp> getList(const std::string& sk);
// Specialized methods for simple string lists, designated by the
// subkey value
// General method to extract entries. Maybe there would be a way to
// express the fact that Type should derive from DynConfEntry, not
// too sure how. We are just certain (further down) that it does
// have a decode() method. It's up to the user that they call
// insertNew() and getEntries() for the same type...
template <template <class, class> class Container, class Type>
Container<Type, std::allocator<Type>> getEntries(const std::string& sk);
// Specialized methods for simple strings
bool enterString(const std::string sk, const std::string value,
int maxlen = -1);
std::list<std::string> getStringList(const std::string sk);
template <template <class, class> class Container>
Container<std::string, std::allocator<std::string>>
getStringEntries(const std::string& sk);
private:
unsigned int m_mlen;
ConfSimple m_data;
};
template<typename Tp> std::list<Tp> RclDynConf::getList(const std::string &sk)
template <template <class, class> class Container, class Type>
Container<Type, std::allocator<Type>>
RclDynConf::getEntries(const std::string& sk)
{
std::list<Tp> mlist;
Tp entry;
Container<Type, std::allocator<Type>> out;
Type entry;
std::vector<std::string> names = m_data.getNames(sk);
for (std::vector<std::string>::const_iterator it = names.begin();
it != names.end(); it++) {
for (const auto& name : names) {
std::string value;
if (m_data.get(*it, value, sk)) {
if (m_data.get(name, value, sk)) {
if (!entry.decode(value))
continue;
mlist.push_front(entry);
out.push_back(entry);
}
}
return mlist;
return std::move(out);
}
template <template <class, class> class Container>
Container<std::string, std::allocator<std::string>>
RclDynConf::getStringEntries(const std::string& sk)
{
std::vector<RclSListEntry> el = getEntries<std::vector, RclSListEntry>(sk);
Container<std::string, std::allocator<std::string>> sl;
for (const auto& entry : el) {
sl.push_back(entry.value);
}
return std::move(sl);
}
// Defined subkeys. Values in dynconf.cpp