a/upmpd/ohmetacache.cxx b/upmpd/ohmetacache.cxx
...
...
21
#include <iostream>
21
#include <iostream>
22
using namespace std;
22
using namespace std;
23
23
24
#include "ohmetacache.hxx"
24
#include "ohmetacache.hxx"
25
#include "conftree.hxx"
25
#include "conftree.hxx"
26
#include "libupnpp/workqueue.hxx"
26
#include "libupnpp/log.hxx"
27
#include "libupnpp/log.hxx"
27
#include "base64.hxx"
28
#include "base64.hxx"
29
30
class SaveCacheTask {
31
public:
32
    SaveCacheTask(const string& fn, const mcache_type& cache)
33
        : m_fn(fn), m_cache(cache)
34
        {}
35
36
    string m_fn;
37
    mcache_type m_cache;
38
};
39
static WorkQueue<SaveCacheTask*> saveQueue("SaveQueue");
28
40
29
// We use base64 to encode names and value, and need to replace the '='
41
// We use base64 to encode names and value, and need to replace the '='
30
static const char eqesc = '*';
42
static const char eqesc = '*';
31
static void eqtoggle(string& nm)
43
static void eqtoggle(string& nm)
32
{
44
{
...
...
41
        }
53
        }
42
        i--;
54
        i--;
43
    }
55
    }
44
}
56
}
45
57
46
bool dmcacheSave(const char *fn, const mcache_type& cache)
58
bool dmcacheSave(const string& fn, const mcache_type& cache)
47
{
59
{
48
    ConfSimple cs(fn);
60
    SaveCacheTask *tsk = new SaveCacheTask(fn, cache);
49
    if (cs.getStatus() != ConfSimple::STATUS_RW) {
61
50
        LOGERR("dmcacheSave: could not open " << fn << " for writing" << endl);
62
    // Use the flush option to put() so that only the latest version
51
        return false;
63
    // stays on the queue, possibly saving writes.
52
    }
64
    if (!saveQueue.put(tsk, true)) {
53
    cs.clear();
65
        LOGERR("dmcacheSave: can't queue save task" << endl);
54
    cs.holdWrites(true);
55
    for (mcache_type::const_iterator it = cache.begin();
56
         it != cache.end(); it++) {
57
        //LOGDEB("dmcacheSave: " << it->first << " -> " << it->second << endl);
58
        string name = base64_encode(it->first);
59
        eqtoggle(name);
60
        cs.set(name, base64_encode(it->second));
61
    }
62
    
63
    if (!cs.holdWrites(false)) {
64
        LOGERR("dmcacheSave: write error while saving to " << fn << endl);
65
        return false;
66
        return false;
66
    }
67
    }
67
    return true;
68
    return true;
68
}
69
}
69
70
70
bool dmcacheRestore(const char *fn, mcache_type& cache)
71
static void *dmcacheSaveWorker(void *)
71
{
72
{
73
    for (;;) {
74
        SaveCacheTask *tsk = 0;
75
        size_t qsz;
76
        if (!saveQueue.take(&tsk, &qsz)) {
77
            LOGERR("dmcacheSaveWorker: can't get task from queue" << endl);
78
            saveQueue.workerExit();
79
            return (void*)1;
80
        }
81
        LOGDEB("dmcacheSave: got save task: " << tsk->m_cache.size() << 
82
               " entries to " << tsk->m_fn << endl);
83
84
        // Beware that calling the constructor with a std::string
85
        // would result in a memory-based object...
86
        ConfSimple cs(tsk->m_fn.c_str());
87
        cs.clear();
88
        if (cs.getStatus() != ConfSimple::STATUS_RW) {
89
            LOGERR("dmcacheSave: could not open " << tsk->m_fn 
90
                   << " for writing" << endl);
91
            delete tsk;
92
            continue;
93
        }
94
        cs.holdWrites(true);
95
        for (mcache_type::const_iterator it = tsk->m_cache.begin();
96
             it != tsk->m_cache.end(); it++) {
97
            string name = base64_encode(it->first);
98
            eqtoggle(name);
99
            string value = base64_encode(it->second);
100
            //LOGDEB("dmcacheSave: " << name << " -> " << value << endl);
101
            cs.set(name, value);
102
        }
103
    
104
        if (!cs.holdWrites(false)) {
105
            LOGERR("dmcacheSave: write error while saving to " << 
106
                   tsk->m_fn << endl);
107
        }
108
        delete tsk;
109
    }
110
}
111
112
bool dmcacheRestore(const string& fn, mcache_type& cache)
113
{
114
    // Restore is called once at startup, so seize the opportunity to start the
115
    // save thread
116
    if (!saveQueue.start(1, dmcacheSaveWorker, 0)) {
117
        LOGERR("dmcacheRestore: could not start save thread" << endl);
118
        return false;
119
    }
120
121
    // Beware that calling the constructor with a std::string
122
    // would result in a memory-based object...
72
    ConfSimple cs(fn, 1);
123
    ConfSimple cs(fn.c_str(), 1);
73
    if (!cs.ok()) {
124
    if (!cs.ok()) {
74
        LOGINF("dmcacheRestore: could not read metadata from " << fn << endl);
125
        LOGINF("dmcacheRestore: could not read metadata from " << fn << endl);
75
        return false;
126
        return false;
76
    }
127
    }
77
128