Switch to unified view

a/src/query/history.cpp b/src/query/history.cpp
1
#ifndef lint
1
#ifndef lint
2
static char rcsid[] = "@(#$Id: history.cpp,v 1.5 2006-01-23 13:32:28 dockes Exp $ (C) 2005 J.F.Dockes";
2
static char rcsid[] = "@(#$Id: history.cpp,v 1.6 2006-09-11 09:08:44 dockes Exp $ (C) 2005 J.F.Dockes";
3
#endif
3
#endif
4
/*
4
/*
5
 *   This program is free software; you can redistribute it and/or modify
5
 *   This program is free software; you can redistribute it and/or modify
6
 *   it under the terms of the GNU General Public License as published by
6
 *   it under the terms of the GNU General Public License as published by
7
 *   the Free Software Foundation; either version 2 of the License, or
7
 *   the Free Software Foundation; either version 2 of the License, or
...
...
31
using namespace std;
31
using namespace std;
32
#endif
32
#endif
33
33
34
static const char *docSubkey = "docs";
34
static const char *docSubkey = "docs";
35
35
36
RclDHistory::RclDHistory(const string &fn, unsigned int mxs)
36
// Encode/decode document history entry: Unix time + base64 of fn +
37
    : m_mlen(mxs), m_data(fn.c_str())
37
// base64 of ipath separated by a space. If ipath is not set, there
38
// are only 2 parts
39
bool RclDHistoryEntry::encode(string& value)
38
{
40
{
41
    char chartime[20];
42
    sprintf(chartime, "%ld", unixtime);
43
    string bfn, bipath;
44
    base64_encode(fn, bfn);
45
    base64_encode(ipath, bipath);
46
    value = string(chartime) + " " + bfn + " " + bipath;
47
    return true;
39
}
48
}
40
49
bool RclDHistoryEntry::decode(const string &value)
41
bool RclDHistory::decodeValue(const string &value, RclDHistoryEntry *e)
42
{
50
{
43
    list<string> vall;
51
    list<string> vall;
44
    stringToStrings(value, vall);
52
    stringToStrings(value, vall);
45
    list<string>::const_iterator it1 = vall.begin();
53
    list<string>::const_iterator it1 = vall.begin();
46
    if (vall.size() < 2)
54
    if (vall.size() < 2)
47
    return false;
55
    return false;
48
    e->unixtime = atol((*it1++).c_str());
56
    unixtime = atol((*it1++).c_str());
49
    base64_decode(*it1++, e->fn);
57
    base64_decode(*it1++, fn);
50
    if (vall.size() == 3)
58
    if (vall.size() == 3)
51
    base64_decode(*it1, e->ipath);
59
    base64_decode(*it1, ipath);
52
    else
60
    else
53
    e->ipath.erase();
61
    ipath.erase();
54
    return true;
62
    return true;
55
}
63
}
56
64
bool RclDHistoryEntry::equal(const HistoryEntry& other)
57
bool RclDHistory::enterDocument(const string fn, const string ipath)
58
{
65
{
59
    LOGDEB(("RclDHistory::enterDocument: [%s] [%s] into %s\n", 
66
    const RclDHistoryEntry& e = dynamic_cast<const RclDHistoryEntry&>(other);
60
      fn.c_str(), ipath.c_str(), m_data.getFilename().c_str()));
67
    return e.fn == fn && e.ipath == ipath;
61
    // Encode value part: Unix time + base64 of fn + base64 of ipath
68
}
62
    // separated by a space. If ipath is not set, there are only 2 parts
69
63
    char chartime[20];
70
64
    time_t now = time(0);
71
// Encode/decode simple string. base64 used to avoid problems with
65
    sprintf(chartime, "%ld", (long)now);
72
// strange chars
66
    string bfn, bipath;
73
bool RclSListEntry::encode(string& enc)
74
{
75
    base64_encode(value, enc);
76
    return true;
77
}
78
bool RclSListEntry::decode(const string &enc)
79
{
67
    base64_encode(fn, bfn);
80
    base64_decode(enc, value);
68
    base64_encode(ipath, bipath);
81
    return true;
69
    string value = string(chartime) + " " + bfn + " " + bipath;
82
}
83
bool RclSListEntry::equal(const HistoryEntry& other)
84
{
85
    const RclSListEntry& e = dynamic_cast<const RclSListEntry&>(other);
86
    return e.value == value;
87
}
70
88
71
89
bool RclHistory::insertNew(const string &sk, HistoryEntry &n, HistoryEntry &s)
72
    LOGDEB1(("Encoded value [%s] (%d)\n", value.c_str(), value.size()));
90
{
73
    // Is this doc already in history ? If it is we remove the old entry
91
    // Is this doc already in history ? If it is we remove the old entry
74
    list<string> names = m_data.getNames(docSubkey);
92
    list<string> names = m_data.getNames(sk);
75
    list<string>::const_iterator it;
93
    list<string>::const_iterator it;
76
    bool changed = false;
94
    bool changed = false;
77
    for (it = names.begin(); it != names.end(); it++) {
95
    for (it = names.begin(); it != names.end(); it++) {
78
    string oval;
96
    string oval;
79
    if (!m_data.get(*it, oval, docSubkey)) {
97
    if (!m_data.get(*it, oval, sk)) {
80
        LOGDEB(("No data for %s\n", (*it).c_str()));
98
        LOGDEB(("No data for %s\n", (*it).c_str()));
81
        continue;
99
        continue;
82
    }
100
    }
83
  RclDHistoryEntry entry;
101
  s.decode(oval);
84
  decodeValue(oval, &entry);
85
102
86
  if (entry.fn == fn && entry.ipath == ipath) {
103
  if (s.equal(n)) {
87
        LOGDEB(("Erasing old entry\n"));
104
        LOGDEB(("Erasing old entry\n"));
88
        m_data.erase(*it, docSubkey);
105
        m_data.erase(*it, sk);
89
        changed = true;
106
        changed = true;
90
    }
107
    }
91
    }
108
    }
92
109
93
    // Maybe reget list
110
    // Maybe reget list
94
    if (changed)
111
    if (changed)
95
    names = m_data.getNames(docSubkey);
112
    names = m_data.getNames(sk);
96
113
97
    // How many do we have
114
    // How many do we have
98
    if (names.size() >= m_mlen) {
115
    if (names.size() >= m_mlen) {
99
    // Need to erase entries until we're back to size. Note that
116
    // Need to erase entries until we're back to size. Note that
100
    // we don't ever reset numbers. Problems will arise when
117
    // we don't ever reset numbers. Problems will arise when
101
    // history is 4 billion entries old
118
    // history is 4 billion entries old
102
    it = names.begin();
119
    it = names.begin();
103
    for (unsigned int i = 0; i < names.size() - m_mlen + 1; i++, it++) {
120
    for (unsigned int i = 0; i < names.size() - m_mlen + 1; i++, it++) {
104
        m_data.erase(*it, docSubkey);
121
        m_data.erase(*it, sk);
105
    }
122
    }
106
    }
123
    }
107
124
108
    // Increment highest number
125
    // Increment highest number
109
    unsigned int hi = names.empty() ? 0 : 
126
    unsigned int hi = names.empty() ? 0 : 
110
    (unsigned int)atoi(names.back().c_str());
127
    (unsigned int)atoi(names.back().c_str());
111
    hi++;
128
    hi++;
112
    char nname[20];
129
    char nname[20];
113
    sprintf(nname, "%010u", hi);
130
    sprintf(nname, "%010u", hi);
114
131
132
    string value;
133
    n.encode(value);
134
    LOGDEB1(("Encoded value [%s] (%d)\n", value.c_str(), value.size()));
115
    if (!m_data.set(string(nname), value, docSubkey)) {
135
    if (!m_data.set(string(nname), value, sk)) {
116
    LOGERR(("RclDHistory::enterDocument: set failed\n"));
136
    LOGERR(("RclDHistory::insertNew: set failed\n"));
117
    return false;
137
    return false;
118
    }
138
    }
119
    return true;
139
    return true;
120
}
121
140
141
}
142
143
bool RclHistory::eraseAll(const string &sk)
144
{
145
    // Is this doc already in history ? If it is we remove the old entry
146
    list<string> names = m_data.getNames(sk);
147
    list<string>::const_iterator it;
148
    for (it = names.begin(); it != names.end(); it++) {
149
      m_data.erase(*it, sk);
150
    }
151
    return true;
152
}
153
154
155
bool RclHistory::enterString(const string sk, const string value)
156
{
157
    RclSListEntry ne(value);
158
    RclSListEntry scratch;
159
    return insertNew(sk, ne, scratch);
160
}
161
list<string> RclHistory::getStringList(const string sk) 
162
{
163
    list<RclSListEntry> el = getHistory<RclSListEntry>(sk);
164
    list<string> sl;
165
    for (list<RclSListEntry>::const_iterator it = el.begin(); 
166
   it != el.end(); it++) 
167
  sl.push_back(it->value);
168
    return sl;
169
}
170
171
/// *************** History entries specific methods
172
bool RclHistory::enterDoc(const string fn, const string ipath)
173
{
174
    LOGDEB(("RclDHistory::enterDoc: [%s] [%s] into %s\n", 
175
      fn.c_str(), ipath.c_str(), m_data.getFilename().c_str()));
176
    RclDHistoryEntry ne(time(0), fn, ipath);
177
    RclDHistoryEntry scratch;
178
    return insertNew(docSubkey, ne, scratch);
179
}
180
122
list<RclDHistoryEntry> RclDHistory::getDocHistory()
181
list<RclDHistoryEntry> RclHistory::getDocHistory()
123
{
182
{
124
    list<RclDHistoryEntry> mlist;
183
    return getHistory<RclDHistoryEntry>(docSubkey);
125
    RclDHistoryEntry entry;
126
    list<string> names = m_data.getNames(docSubkey);
127
    for (list<string>::const_iterator it = names.begin(); 
128
   it != names.end(); it++) {
129
  string value;
130
  if (m_data.get(*it, value, docSubkey)) {
131
      if (!decodeValue(value, &entry))
132
      continue;
133
      mlist.push_front(entry);
134
  }
184
}
135
    }
185
136
    return mlist;
137
}
138
186
139
187
140
#else
188
#else
141
#include <string>
189
#include <string>
190
#include <iostream>
142
191
143
#include "history.h"
192
#include "history.h"
144
#include "debuglog.h"
193
#include "debuglog.h"
145
194
146
#ifndef NO_NAMESPACES
195
#ifndef NO_NAMESPACES
147
using namespace std;
196
using namespace std;
148
#endif
197
#endif
149
198
199
static string thisprog;
200
201
static string usage =
202
    " [-e] [-s <subkey>]"
203
    "  \n\n"
204
    ;
205
206
static void
207
Usage(void)
208
{
209
    cerr << thisprog  << ": usage:\n" << usage;
210
    exit(1);
211
}
212
213
static int        op_flags;
214
#define OPT_e     0x2
215
#define OPT_s     0x4
216
150
int main(int argc, char **argv)
217
int main(int argc, char **argv)
151
{
218
{
219
    string sk = "docs";
220
221
    thisprog = argv[0];
222
    argc--; argv++;
223
224
    while (argc > 0 && **argv == '-') {
225
  (*argv)++;
226
  if (!(**argv))
227
      /* Cas du "adb - core" */
228
      Usage();
229
  while (**argv)
230
      switch (*(*argv)++) {
231
      case 's':   op_flags |= OPT_s; if (argc < 2)  Usage();
232
      sk = *(++argv);
233
      argc--; 
234
      goto b1;
235
      case 'e':   op_flags |= OPT_e; break;
236
      default: Usage();   break;
237
      }
238
    b1: argc--; argv++;
239
    }
240
    if (argc != 0)
241
  Usage();
242
152
    RclDHistory hist("toto", 5);
243
    RclHistory hist("toto", 5);
153
    DebugLog::getdbl()->setloglevel(DEBDEB1);
244
    DebugLog::getdbl()->setloglevel(DEBDEB1);
154
    DebugLog::setfilename("stderr");
245
    DebugLog::setfilename("stderr");
155
246
247
    if (op_flags & OPT_e) {
248
  hist.eraseAll(sk);
249
    } else {
156
    for (int i = 0; i < 10; i++) {
250
  for (int i = 0; i < 10; i++) {
157
    char docname[100];
251
        char docname[100];
158
  sprintf(docname, "A very long document document name is very long indeed and this is the end of it here and exactly here:\n%d", i);
252
      sprintf(docname, "A very long document document name"
253
          "is very long indeed and this is the end of "
254
          "it here and exactly here:\n%d",    i);
159
    hist.enterDocument(string(docname), "ipathx");
255
        hist.enterDoc(string(docname), "ipathx");
160
    }
256
  }
161
257
162
    list< pair<string, string> > hlist = hist.getDocHistory();
258
  list<RclDHistoryEntry> hlist = hist.getDocHistory();
163
    for (list< pair<string, string> >::const_iterator it = hlist.begin();
259
  for (list<RclDHistoryEntry>::const_iterator it = hlist.begin();
164
     it != hlist.end(); it++) {
260
         it != hlist.end(); it++) {
165
  printf("[%s] [%s]\n", it->first.c_str(), it->second.c_str());
261
      printf("[%ld] [%s] [%s]\n", it->unixtime, 
166
    }
262
         it->fn.c_str(), it->ipath.c_str());
167
}
263
  }
264
    }
265
}
168
266
169
#endif
267
#endif