From 241586a3a7d24c63e1c5f4c979e7a8db758a0843 Mon Sep 17 00:00:00 2001 From: Jean-Francois Dockes Date: Wed, 13 Apr 2016 15:52:41 +0200 Subject: [PATCH] 1st proto for GUI webcache editor --- src/common/beaglequeuecache.cpp | 2 +- src/qtgui/rclm_wins.cpp | 14 ++ src/qtgui/rclmain.ui | 6 + src/qtgui/rclmain_w.cpp | 2 + src/qtgui/rclmain_w.h | 4 + src/qtgui/recoll.pro.in | 5 +- src/qtgui/webcache.cpp | 195 +++++++++++++++++++++ src/qtgui/webcache.h | 61 +++++++ src/qtgui/webcache.ui | 51 ++++++ src/utils/circache.cpp | 289 +++++++++++++------------------- src/utils/circache.h | 17 +- 11 files changed, 465 insertions(+), 181 deletions(-) create mode 100644 src/qtgui/webcache.cpp create mode 100644 src/qtgui/webcache.h create mode 100644 src/qtgui/webcache.ui diff --git a/src/common/beaglequeuecache.cpp b/src/common/beaglequeuecache.cpp index 2f82dd1b..3e9f1d89 100644 --- a/src/common/beaglequeuecache.cpp +++ b/src/common/beaglequeuecache.cpp @@ -62,7 +62,7 @@ bool BeagleQueueCache::getFromCache(const string& udi, Rcl::Doc &dotdoc, LOGERR(("BeagleQueueCache::getFromCache: cache is null\n")); return false; } - if (!m_cache->get(udi, dict, data)) { + if (!m_cache->get(udi, dict, &data)) { LOGDEB(("BeagleQueueCache::getFromCache: get failed\n")); return false; } diff --git a/src/qtgui/rclm_wins.cpp b/src/qtgui/rclm_wins.cpp index e13950c1..671275f5 100644 --- a/src/qtgui/rclm_wins.cpp +++ b/src/qtgui/rclm_wins.cpp @@ -30,6 +30,7 @@ #include "fragbuts.h" #include "specialindex.h" #include "rclmain_w.h" +#include "webcache.h" using namespace std; @@ -74,6 +75,19 @@ void RclMain::showSpellDialog() } } +void RclMain::showWebcacheDialog() +{ + if (webcache == 0) { + webcache = new WebcacheEdit(0); + connect(new QShortcut(quitKeySeq, webcache), SIGNAL (activated()), + this, SLOT (fileExit())); + webcache->show(); + } else { + webcache->close(); + webcache->show(); + } +} + void RclMain::showIndexStatistics() { showSpellDialog(); diff --git a/src/qtgui/rclmain.ui b/src/qtgui/rclmain.ui index 18a19872..71558876 100644 --- a/src/qtgui/rclmain.ui +++ b/src/qtgui/rclmain.ui @@ -103,6 +103,7 @@ + @@ -532,6 +533,11 @@ Index &statistics + + + Webcache Editor + + diff --git a/src/qtgui/rclmain_w.cpp b/src/qtgui/rclmain_w.cpp index 78514680..56b81363 100644 --- a/src/qtgui/rclmain_w.cpp +++ b/src/qtgui/rclmain_w.cpp @@ -350,6 +350,8 @@ void RclMain::init() this, SLOT(showAdvSearchDialog())); connect(toolsSpellAction, SIGNAL(triggered()), this, SLOT(showSpellDialog())); + connect(actionWebcache_Editor, SIGNAL(triggered()), + this, SLOT(showWebcacheDialog())); connect(actionQuery_Fragments, SIGNAL(triggered()), this, SLOT(showFragButs())); connect(actionSpecial_Indexing, SIGNAL(triggered()), diff --git a/src/qtgui/rclmain_w.h b/src/qtgui/rclmain_w.h index 432e241a..d891af50 100644 --- a/src/qtgui/rclmain_w.h +++ b/src/qtgui/rclmain_w.h @@ -42,6 +42,7 @@ class CronToolW; class RTIToolW; class FragButs; class SpecIdxW; +class WebcacheEdit; #include "ui_rclmain.h" @@ -73,6 +74,7 @@ public: fragbuts(0), specidx(0), periodictimer(0), + webcache(0), restable(0), displayingTable(0), m_idNoStem(0), @@ -122,6 +124,7 @@ public slots: virtual void previewClosed(Preview *w); virtual void showAdvSearchDialog(); virtual void showSpellDialog(); + virtual void showWebcacheDialog(); virtual void showIndexStatistics(); virtual void showFragButs(); virtual void showSpecIdx(); @@ -200,6 +203,7 @@ private: FragButs *fragbuts; SpecIdxW *specidx; QTimer *periodictimer; + WebcacheEdit *webcache; ResTable *restable; bool displayingTable; QAction *m_idNoStem; diff --git a/src/qtgui/recoll.pro.in b/src/qtgui/recoll.pro.in index a1c34086..445546c5 100644 --- a/src/qtgui/recoll.pro.in +++ b/src/qtgui/recoll.pro.in @@ -41,6 +41,7 @@ HEADERS += \ systray.h \ uiprefs_w.h \ viewaction_w.h \ + webcache.h \ widgets/editdialog.h \ widgets/listdialog.h \ widgets/qxtconfirmationmessage.h @@ -78,6 +79,7 @@ SOURCES += \ systray.cpp \ uiprefs_w.cpp \ viewaction_w.cpp \ + webcache.cpp \ widgets/qxtconfirmationmessage.cpp \ xmltosd.cpp @@ -98,7 +100,8 @@ FORMS = \ ssearchb.ui \ uiprefs.ui \ viewaction.ui \ - + webcache.ui + RESOURCES = recoll.qrc unix { diff --git a/src/qtgui/webcache.cpp b/src/qtgui/webcache.cpp new file mode 100644 index 00000000..3a4b787f --- /dev/null +++ b/src/qtgui/webcache.cpp @@ -0,0 +1,195 @@ +/* Copyright (C) 2016 J.F.Dockes + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include "autoconfig.h" + +#include +#include +#include MEMORY_INCLUDE +#include UNORDERED_MAP_INCLUDE + +#ifndef USING_STD_REGEX +#include +#include +#else +#include +#endif + +#include + +#include "recoll.h" +#include "webcache.h" +#include "beaglequeuecache.h" +#include "circache.h" +#include "conftree.h" + +using namespace std; + +class CEnt { +public: + CEnt(const string& ud, const string& ur, const string& mt) + : udi(ud), url(ur), mimetype(mt) { + } + string udi; + string url; + string mimetype; +}; + +class WebcacheModelInternal { +public: + STD_SHARED_PTR cache; + vector all; + vector disp; +}; + +WebcacheModel::WebcacheModel(QObject *parent) + : QAbstractTableModel(parent), m(new WebcacheModelInternal()) +{ + qDebug() << "WebcacheModel::WebcacheModel()"; + m->cache = + STD_SHARED_PTR(new BeagleQueueCache(theconfig)); + + if (m->cache) { + bool eof; + m->cache->cc()->rewind(eof); + while (!eof) { + string udi, sdic; + m->cache->cc()->getCurrent(udi, sdic); + ConfSimple dic(sdic); + string mime, url; + dic.get("mimetype", mime); + dic.get("url", url); + if (!udi.empty()) { + m->all.push_back(CEnt(udi, url, mime)); + m->disp.push_back(CEnt(udi, url, mime)); + } + if (!m->cache->cc()->next(eof)) + break; + } + } +} + +int WebcacheModel::rowCount(const QModelIndex&) const +{ + //qDebug() << "WebcacheModel::rowCount(): " << m->disp.size(); + return int(m->disp.size()); +} + +int WebcacheModel::columnCount(const QModelIndex&) const +{ + //qDebug() << "WebcacheModel::columnCount()"; + return 2; +} + +QVariant WebcacheModel::headerData (int col, Qt::Orientation orientation, + int role) const +{ + // qDebug() << "WebcacheModel::headerData()"; + if (orientation != Qt::Horizontal || role != Qt::DisplayRole) { + return QVariant(); + } + switch (col) { + case 0: return QVariant(tr("MIME")); + case 1: return QVariant(tr("Url")); + default: return QVariant(); + } +} + +QVariant WebcacheModel::data(const QModelIndex& index, int role) const +{ + //qDebug() << "WebcacheModel::data()"; + Q_UNUSED(index); + if (role != Qt::DisplayRole) { + return QVariant(); + } + int row = index.row(); + if (row < 0 || row >= int(m->disp.size())) { + return QVariant(); + } + + /* We now read the data on init */ +#if 0 + string sdic; + if (!m->cache->cc()->get(m->disp[row].udi, sdic)) { + return QVariant(); + } + ConfSimple dic(sdic); + //ostringstream os; dic.write(os); cerr << "DIC: " << os.str() << endl; + string mime, url; + dic.get("mimetype", mime); + dic.get("url", url); +#else + const string& mime = m->disp[row].mimetype; + const string& url = m->disp[row].url; +#endif + + switch (index.column()) { + case 0: return QVariant(QString::fromUtf8(mime.c_str())); + case 1: return QVariant(QString::fromUtf8(url.c_str())); + default: return QVariant(); + } +} + +#ifndef USING_STD_REGEX +#define M_regexec(A,B,C,D,E) regexec(&(A),B,C,D,E) +#else +#define M_regexec(A,B,C,D,E) (!regex_match(B,A)) +#endif + +void WebcacheModel::setSearchFilter(const QString& _txt) +{ + string txt = qs2utf8s(_txt); + +#ifndef USING_STD_REGEX + regex_t exp; + if (regcomp(&exp, txt.c_str(), REG_NOSUB|REG_EXTENDED)) { + //qDebug() << "regcomp failed for " << _txt; + return; + } +#else + basic_regex exp; + try { + exp = basic_regexp(txt, std::regex_constants::nosubs | + std::regex_constants::extended); + } catch(...) { + return; + } +#endif + + m->disp.clear(); + for (unsigned int i = 0; i < m->all.size(); i++) { + if (!M_regexec(exp, m->all[i].url.c_str(), 0, 0, 0)) { + m->disp.push_back(m->all[i]); + } else { + //qDebug() << "match failed. exp" << _txt << "data" << + // m->all[i].url.c_str(); + } + } + emit dataChanged(createIndex(0,0,0), createIndex(1, m->all.size(),0)); +} + + +WebcacheEdit::WebcacheEdit(QWidget *parent) + : QDialog(parent) +{ + qDebug() << "WebcacheEdit::WebcacheEdit()"; + setupUi(this); + m_model = new WebcacheModel(this); + webcacheTV->setModel(m_model); + connect(searchLE, SIGNAL(textEdited(const QString&)), + m_model, SLOT(setSearchFilter(const QString&))); +} + diff --git a/src/qtgui/webcache.h b/src/qtgui/webcache.h new file mode 100644 index 00000000..5b9196e1 --- /dev/null +++ b/src/qtgui/webcache.h @@ -0,0 +1,61 @@ +/* Copyright (C) 2016 J.F.Dockes + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#ifndef _WEBCACHE_H_INCLUDED_ +#define _WEBCACHE_H_INCLUDED_ +#include "autoconfig.h" + +#include +#include +#include MEMORY_INCLUDE + +#include "ui_webcache.h" + +#include + +class WebcacheModelInternal; + +class WebcacheModel : public QAbstractTableModel { + Q_OBJECT; + +public: + WebcacheModel(QObject *parent = 0); + + // Reimplemented methods + virtual int rowCount (const QModelIndex& = QModelIndex()) const; + virtual int columnCount(const QModelIndex& = QModelIndex()) const; + virtual QVariant headerData (int col, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + virtual QVariant data(const QModelIndex& index, + int role = Qt::DisplayRole ) const; +public slots: + void setSearchFilter(const QString&); + +private: + WebcacheModelInternal *m; +}; + +class WebcacheEdit : public QDialog, public Ui::Webcache { + Q_OBJECT; + +public: + WebcacheEdit(QWidget *parent); +private: + WebcacheModel *m_model; +}; + + +#endif /* _WEBCACHE_H_INCLUDED_ */ diff --git a/src/qtgui/webcache.ui b/src/qtgui/webcache.ui new file mode 100644 index 00000000..f7e9974a --- /dev/null +++ b/src/qtgui/webcache.ui @@ -0,0 +1,51 @@ + + + Webcache + + + + 0 + 0 + 400 + 300 + + + + Webcache editor + + + + + + + + Search regexp + + + searchLE + + + + + + + + + + + + QAbstractItemView::NoEditTriggers + + + true + + + false + + + + + + + + diff --git a/src/utils/circache.cpp b/src/utils/circache.cpp index a67bd742..20e73911 100644 --- a/src/utils/circache.cpp +++ b/src/utils/circache.cpp @@ -30,6 +30,8 @@ #include #include "chrono.h" +#include MEMORY_INCLUDE + #ifndef _WIN32 #include @@ -857,7 +859,7 @@ public: }; // instance == -1 means get latest. Otherwise specify from 1+ -bool CirCache::get(const string& udi, string& dic, string& data, int instance) +bool CirCache::get(const string& udi, string& dic, string *data, int instance) { Chrono chron; if (m_d->m_fd < 0) { @@ -900,7 +902,7 @@ bool CirCache::get(const string& udi, string& dic, string& data, int instance) } // Did we read an appropriate entry ? if (o_good != 0 && (instance == -1 || instance == finst)) { - bool ret = m_d->readDicData(o_good, d_good, dic, &data); + bool ret = m_d->readDicData(o_good, d_good, dic, data); LOGDEB0(("Circache::get: hfound, %d mS\n", chron.millis())); return ret; @@ -920,8 +922,7 @@ bool CirCache::get(const string& udi, string& dic, string& data, int instance) } else if (ret != CCScanHook::Stop) { return false; } - bool bret = - m_d->readDicData(getter.m_offs, getter.m_hd, dic, &data); + bool bret = m_d->readDicData(getter.m_offs, getter.m_hd, dic, data); LOGDEB0(("Circache::get: scanfound, %d mS\n", chron.millis())); return bret; @@ -943,8 +944,8 @@ bool CirCache::erase(const string& udi) // If the mem cache is not up to date, update it, we're too lazy // to do a scan if (!m_d->m_ofskhcplt) { - string dic, data; - get("nosuchudi probably exists", dic, data); + string dic; + get("nosuchudi probably exists", dic); if (!m_d->m_ofskhcplt) { LOGERR(("CirCache::erase : cache not updated after get\n")); return false; @@ -1265,13 +1266,13 @@ bool CirCache::getCurrentUdi(string& udi) return true; } -bool CirCache::getCurrent(string& udi, string& dic, string& data) +bool CirCache::getCurrent(string& udi, string& dic, string *data) { if (m_d == 0) { LOGERR(("CirCache::getCurrent: null data\n")); return false; } - if (!m_d->readDicData(m_d->m_itoffs, m_d->m_ithd, dic, &data)) { + if (!m_d->readDicData(m_d->m_itoffs, m_d->m_ithd, dic, data)) { return false; } @@ -1367,6 +1368,85 @@ static bool inflateToDynBuf(void* inp, UINT inlen, void **outpp, UINT *outlenp) return true; } +// Copy all entries from occ to ncc. Both are already open. +static bool copyall(STD_SHARED_PTR occ, + STD_SHARED_PTR ncc, int& nentries, + ostringstream& msg) +{ + bool eof = false; + if (!occ->rewind(eof)) { + if (!eof) { + msg << "Initial rewind failed" << endl; + return false; + } + } + nentries = 0; + while (!eof) { + string udi, sdic, data; + if (!occ->getCurrent(udi, sdic, &data)) { + msg << "getCurrent failed: " << occ->getReason() << endl; + return false; + } + // Shouldn't getcurrent deal with this ? + if (sdic.size() == 0) { + //cerr << "Skip empty entry" << endl; + occ->next(eof); + continue; + } + ConfSimple dic(sdic); + if (!dic.ok()) { + msg << "Could not parse entry attributes dic" << endl; + return false; + } + //cerr << "UDI: " << udi << endl; + if (!ncc->put(udi, &dic, data)) { + msg << "put failed: " << ncc->getReason() << " sdic [" << sdic << + "]" << endl; + return false; + } + nentries++; + occ->next(eof); + } + return true; +} + +// Append all entries from sdir to ddir +int CirCache::append(const string ddir, const string& sdir, string *reason) +{ + ostringstream msg; + // Open source file + STD_SHARED_PTR occ(new CirCache(sdir)); + if (!occ->open(CirCache::CC_OPREAD)) { + if (reason) { + msg << "Open failed in " << sdir << " : " << + occ->getReason() << endl; + *reason = msg.str(); + } + return -1; + } + // Open dest file + STD_SHARED_PTR ncc(new CirCache(ddir)); + if (!ncc->open(CirCache::CC_OPWRITE)) { + if (reason) { + msg << "Open failed in " << ddir << " : " << + ncc->getReason() << endl; + *reason = msg.str(); + } + return -1; + } + + int nentries; + if (!copyall(occ, ncc, nentries, msg)) { + if (reason) { + *reason = msg.str(); + } + return -1; + } + + return nentries; +} + + #else // TEST -> #include "autoconfig.h" @@ -1380,163 +1460,17 @@ static bool inflateToDynBuf(void* inp, UINT inlen, void **outpp, UINT *outlenp) #include #include +#include MEMORY_INCLUDE #include "circache.h" #include "fileudi.h" #include "conftree.h" #include "readfile.h" #include "debuglog.h" +#include "smallut.h" using namespace std; -// Copy all entries from occ to ncc. Both are already open. -bool copyall(STD_SHARED_PTR occ, - STD_SHARED_PTR ncc, int& nentries) -{ - bool eof = false; - if (!occ->rewind(eof)) { - if (!eof) { - cerr << "Initial rewind failed" << endl; - return false; - } - } - nentries = 0; - while (!eof) { - string udi, sdic, data; - if (!occ->getCurrent(udi, sdic, data)) { - cerr << "getCurrent failed: " << occ->getReason() << endl; - return false; - } - // Shouldn't getcurrent deal with this ? - if (sdic.size() == 0) { - //cerr << "Skip empty entry" << endl; - occ->next(eof); - continue; - } - ConfSimple dic(sdic); - if (!dic.ok()) { - cerr << "Could not parse entry attributes dic" << endl; - return false; - } - //cerr << "UDI: " << udi << endl; - if (!ncc->put(udi, &dic, data)) { - cerr << "put failed: " << ncc->getReason() << " sdic [" << sdic << - "]" << endl; - return false; - } - nentries++; - occ->next(eof); - } - return true; -} - -#warning resizecc is not useful, create(newsize) works ! - -// Wrote the following at a point where I thought that simple resizing -// did not work. Upon further study (or updates?), it appears it does -// ! So the following code is not useful actually - -// Resize circache. This can't be done easily if the write point is -// inside the file (we already reached the old max size). We create a -// new file with the new size and copy the old entries into it. The -// old file is then renamed into a backup and the new file renamed in -// place. -bool resizecc(const string& dir, int newmbs) -{ - // Create object for existing file and get the file name - STD_SHARED_PTR occ(new CirCache(dir)); - string ofn = occ->getpath(); - - // Check for previous backup - string backupfn = ofn + ".orig"; - if (access(backupfn.c_str(), 0) >= 0) { - cerr << "Backup file " << backupfn << - " exists, please move it out of the way" << endl; - return false; - } - - if (!occ->open(CirCache::CC_OPREAD)) { - cerr << "Open failed in " << dir << " : " << occ->getReason() << endl; - return false; - } - - // Create the new empty file in a temporary directory - string tmpdir = path_cat(dir, "tmp"); - if (access(tmpdir.c_str(), 0) < 0) { - if (mkdir(tmpdir.c_str(), 0700) < 0) { - cerr << "Cant create temporary directory " << tmpdir << " "; - perror("mkdir"); - return false; - } - } - STD_SHARED_PTR ncc(new CirCache(tmpdir)); - string nfn = ncc->getpath(); - if (!ncc->create(off_t(newmbs) * 1000 * 1024, - CirCache::CC_CRUNIQUE | CirCache::CC_CRTRUNCATE)) { - cerr << "Cant create new file in " << tmpdir << " : " << - ncc->getReason() << endl; - return false; - } - - int nentries; - if (!copyall(occ, ncc, nentries)) { - cerr << "Copy failed\n"; - return false; - } - - // Done with our objects here, there is no close() method, so - // delete them - occ.reset(); - ncc.reset(); - - // Create backup by renaming the old file - if (rename(ofn.c_str(), backupfn.c_str()) < 0) { - cerr << "Could not create backup " << backupfn << " : "; - perror("rename"); - return false; - } - cout << "Created backup file " << backupfn << endl; - - // Move the new file in place. - if (rename(nfn.c_str(), ofn.c_str()) < 0) { - cerr << "Could not rename new file from " << nfn << " to " << - ofn << " : "; - perror("rename"); - return false; - } - cout << "Resize done, copied " << nentries << " entries " << endl; - return true; -} - -// Append all entries from sdir to ddir -bool appendcc(const string ddir, const string& sdir) -{ - // Open source file - STD_SHARED_PTR occ(new CirCache(sdir)); - if (!occ->open(CirCache::CC_OPREAD)) { - cerr << "Open failed in " << sdir << " : " << occ->getReason() << endl; - return false; - } - // Open dest file - STD_SHARED_PTR ncc(new CirCache(ddir)); - if (!ncc->open(CirCache::CC_OPWRITE)) { - cerr << "Open failed in " << ddir << " : " << ncc->getReason() << endl; - return false; - } - - int nentries; - if (!copyall(occ, ncc, nentries)) { - cerr << "Copy failed\n"; - return false; - } - - occ.reset(); - ncc.reset(); - - cout << "Copy done, copied " << nentries << " entries " << endl; - return true; -} - static char *thisprog; static char usage [] = @@ -1546,7 +1480,6 @@ static char usage [] = " -g [-i instance] [-D] : get\n" " -D: also dump data\n" " -e : erase\n" - " -s : resize\n" " -a [ ...]: append old content to target\n" " The target should be first resized to hold all the data, else only\n" " as many entries as capacity permit will be retained\n" @@ -1569,7 +1502,6 @@ static int op_flags; #define OPT_D 0x80 #define OPT_u 0x100 #define OPT_e 0x200 -#define OPT_s 0x400 #define OPT_a 0x800 int main(int argc, char **argv) @@ -1620,9 +1552,6 @@ int main(int argc, char **argv) case 'p': op_flags |= OPT_p; break; - case 's': - op_flags |= OPT_s; - break; case 'u': op_flags |= OPT_u; break; @@ -1660,21 +1589,14 @@ b1: cerr << "Create failed:" << cc.getReason() << endl; exit(1); } - } else if (op_flags & OPT_s) { - if (argc != 1) { - Usage(); - } - int newmbs = atoi(*argv++); - argc--; - if (!resizecc(dir, newmbs)) { - exit(1); - } } else if (op_flags & OPT_a) { if (argc < 1) { Usage(); } while (argc) { - if (!appendcc(dir, *argv++)) { + string reason; + if (CirCache::append(dir, *argv++, &reason) < 0) { + cerr << reason << endl; return 1; } argc--; @@ -1698,11 +1620,24 @@ b1: } string udi; make_udi(fn, "", udi); - sprintf(dic, "#whatever...\nmimetype = text/plain\nudi=%s\n", - udi.c_str()); - string sdic; - sdic.assign(dic, strlen(dic)); - ConfSimple conf(sdic); + string cmd("xdg-mime query filetype "); + // Should do more quoting here... + cmd += "'" + fn + "'"; + FILE *fp = popen(cmd.c_str(), "r"); + char* buf=0; + size_t sz = 0; + ::getline(&buf, &sz, fp); + pclose(fp); + string mimetype(buf); + free(buf); + trimstring(mimetype, "\n\r"); + cout << "Got [" << mimetype << "]\n"; + + string s; + ConfSimple conf(s); + conf.set("udi", udi); + conf.set("mimetype", mimetype); + //ostringstream str; conf.write(str); cout << str.str() << endl; if (!cc.put(udi, &conf, data, 0)) { cerr << "Put failed: " << cc.getReason() << endl; @@ -1722,7 +1657,7 @@ b1: string udi = *argv++; argc--; string dic, data; - if (!cc.get(udi, dic, data, instance)) { + if (!cc.get(udi, dic, &data, instance)) { cerr << "Get failed: " << cc.getReason() << endl; exit(1); } diff --git a/src/utils/circache.h b/src/utils/circache.h index 2022af1b..5f92cbe7 100644 --- a/src/utils/circache.h +++ b/src/utils/circache.h @@ -64,8 +64,9 @@ public: virtual std::string getpath(); + // Set data to 0 if you just want the header virtual bool get(const std::string& udi, std::string& dic, - std::string& data, int instance = -1); + std::string *data = 0, int instance = -1); // Note: the dicp MUST have an udi entry enum PutFlags {NoCompHint = 1}; @@ -84,7 +85,7 @@ public: virtual bool rewind(bool& eof); /** Get entry under cursor */ virtual bool getCurrent(std::string& udi, std::string& dic, - std::string& data); + std::string *data = 0); /** Get current entry udi only. Udi can be empty (erased empty), caller * should call again */ virtual bool getCurrentUdi(std::string& udi); @@ -94,6 +95,18 @@ public: /* Debug. This writes the entry headers to stdout */ virtual bool dump(); + /* Utility: append all entries from sdir to ddir. + * + * This does not need to be a member at all, just using the namespace here. + * + * @param ddir destination circache (must be previously created + * with appropriate size) + * @param sdir source circache + * @ret number of entries copied or -a + */ + static int append(const std::string ddir, const std::string& sdir, + std::string *reason = 0); + protected: CirCacheInternal *m_d; std::string m_dir;