On Tue, 23 Sep 2003, Andreas Aardal Hanssen wrote:
>Hi, Michael :-).
>On Tue, 23 Sep 2003, Michael Amster wrote:
>>something like this for each folder (note I have 744 folders and this
>>takes about 1s per folder - it also pins CPU at 100%):
>>001 LIST "" "INBOX/myfolder/%"
This little patch should make consecutive LIST requests it a bit faster:
Andy :-)
--- src/operator-list.cc 14 Sep 2003 08:21:28 -0000 1.2
+++ src/operator-list.cc 23 Sep 2003 21:01:03 -0000
@@ -59,14 +59,13 @@
using namespace Binc;
namespace {
- const int DIR_SELECT = 0x01;
- const int DIR_MARKED = 0x02;
- const int DIR_NOINFERIORS = 0x04;
+ const time_t LIST_CACHE_TIMEOUT = 10;
}
//----------------------------------------------------------------------
ListOperator::ListOperator(void)
{
+ cacheTimeout = 0;
}
//----------------------------------------------------------------------
@@ -91,6 +90,7 @@
Request &command)
{
IO &com = IOFactory::getInstance().get(1);
+ IO &logger = IOFactory::getInstance().get(2);
const char delim = depot.getDelimiter();
// special case: if the mailbox argument is empty, then give a
@@ -112,68 +112,83 @@
trim(ref, string(&delim, 1));
// a map from mailbox name to flags
- map<string, int> mailboxes;
+ map<string, unsigned int> mailboxes;
- // read through all entries in depository.
- for (Depot::iterator i = depot.begin("."); i != depot.end(); ++i) {
- const string path = *i;
- const string mpath = depot.filenameToMailbox(path);
- Mailbox *m = 0;
-
- // skip entries that are not identified as mailboxes
- if ((m = depot.get(mpath)) == 0)
- continue;
-
- // convert file name to mailbox name. skip it if there is no
- // corresponding mailbox name.
- string tmp = toCanonMailbox(depot.filenameToMailbox(path));
- trim(tmp, string(&delim, 1));
- if (tmp == "") continue;
- else {
- // inherit flags that were already set for this mailbox.
- int flags = DIR_SELECT;
- if (m->isMarked(path)) flags |= DIR_MARKED;
- if (mailboxes.find(tmp) != mailboxes.end()) flags |= mailboxes[tmp];
- mailboxes[tmp] = flags;
- }
-
- // now add all superior mailboxes with no flags set if not
- // added already.
- string::size_type pos = tmp.rfind(delim);
- while (pos != string::npos) {
- tmp = tmp.substr(0, pos);
+ if (cacheTimeout == 0 || cacheTimeout < time(0) - LIST_CACHE_TIMEOUT) {
+ // read through all entries in depository.
+ for (Depot::iterator i = depot.begin("."); i != depot.end(); ++i) {
+ const string path = *i;
+ const string mpath = depot.filenameToMailbox(path);
+ Mailbox *m = 0;
+
+ // skip entries that are not identified as mailboxes
+ if ((m = depot.get(mpath)) == 0)
+ continue;
+
+ // convert file name to mailbox name. skip it if there is no
+ // corresponding mailbox name.
+ string tmp = toCanonMailbox(depot.filenameToMailbox(path));
trim(tmp, string(&delim, 1));
+ if (tmp == "") continue;
+ else {
+ // inherit flags that were already set for this mailbox.
+ int flags = DIR_SELECT;
+ if (m->isMarked(path)) flags |= DIR_MARKED;
+ if (mailboxes.find(tmp) != mailboxes.end()) flags |= mailboxes[tmp];
+ mailboxes[tmp] = flags;
+ }
- if (mailboxes.find(tmp) == mailboxes.end())
- mailboxes[tmp] = 0;
-
- pos = tmp.rfind(delim);
+ // now add all superior mailboxes with no flags set if not
+ // added already.
+ string::size_type pos = tmp.rfind(delim);
+ while (pos != string::npos) {
+ tmp = tmp.substr(0, pos);
+ trim(tmp, string(&delim, 1));
+
+ if (mailboxes.find(tmp) == mailboxes.end())
+ mailboxes[tmp] = 0;
+
+ pos = tmp.rfind(delim);
+ }
}
- }
- // find leaf nodes O(N^2)
- map<string, int>::iterator i;
- for (i = mailboxes.begin(); i != mailboxes.end(); ++i) {
- string mailbox = i->first;
- mailbox += delim;
-
- bool leaf = true;
- map<string, int>::const_iterator j;
- for (j = mailboxes.begin(); j != mailboxes.end(); ++j) {
- string::size_type pos = j->first.rfind(delim);
- if (pos == string::npos) continue;
-
- string base = j->first.substr(0, pos + 1);
-
- if (mailbox == base) {
- leaf = false;
- break;
+ // find leaf nodes O(N^2)
+ map<string, unsigned int>::iterator i;
+ for (i = mailboxes.begin(); i != mailboxes.end(); ++i) {
+ string mailbox = i->first;
+ mailbox += delim;
+
+ bool leaf = true;
+ map<string, unsigned int>::const_iterator j = mailboxes.begin();
+ for (; j != mailboxes.end(); ++j) {
+ string::size_type pos = j->first.rfind(delim);
+ if (pos == string::npos) continue;
+
+ string base = j->first.substr(0, pos + 1);
+
+ if (mailbox == base) {
+ leaf = false;
+ break;
+ }
+ }
+
+ if (leaf) {
+ unsigned int flags = i->second;
+ flags |= DIR_LEAF;
+ i->second = flags;
}
}
+
+ cache = mailboxes;
+ cacheTimeout = time(0);
+ } else {
+ mailboxes = cache;
+ cacheTimeout = time(0);
}
-
+
// finally, print all mailbox entries with flags.
- for (i = mailboxes.begin(); i != mailboxes.end(); ++i) {
+ map<string, unsigned int>::iterator i = mailboxes.begin();
+ for (; i != mailboxes.end(); ++i) {
if (ref == "" || ((ref.length() <= i->first.length())
&& (i->first.substr(0, ref.length()) == ref)))
if (regexMatch(i->first, regex) == 0) {
--- src/operators.h 18 Aug 2003 18:06:05 -0000 1.1.1.1
+++ src/operators.h 23 Sep 2003 21:01:03 -0000
@@ -201,6 +201,16 @@
//--------------------------------------------------------------------
class ListOperator : public Operator {
+ protected:
+ enum MailboxFlags {
+ DIR_SELECT = 0x01,
+ DIR_MARKED = 0x02,
+ DIR_NOINFERIORS = 0x04,
+ DIR_LEAF = 0x08
+ };
+
+ std::map<std::string, unsigned int> cache;
+ time_t cacheTimeout;
public:
ProcessResult process(Depot &, Request &);
virtual ParseResult parse(Request &) const;