This commit is contained in:
Jean-Francois Dockes 2016-04-12 10:04:48 +02:00
parent d70b3cb4d2
commit c06eb296c1
2 changed files with 610 additions and 554 deletions

View File

@ -44,8 +44,9 @@ static ssize_t writev(int fd, const struct iovec *iov, int iovcnt)
ssize_t tot = 0; ssize_t tot = 0;
for (int i = 0; i < iovcnt; i++) { for (int i = 0; i < iovcnt; i++) {
ssize_t ret = ::write(fd, iov[i].iov_base, iov[i].iov_len); ssize_t ret = ::write(fd, iov[i].iov_base, iov[i].iov_len);
if (ret > 0) if (ret > 0) {
tot += ret; tot += ret;
}
if (ret != (ssize_t)iov[i].iov_len) { if (ret != (ssize_t)iov[i].iov_len) {
return ret == -1 ? -1 : tot; return ret == -1 ? -1 : tot;
} }
@ -157,8 +158,7 @@ class UdiH {
public: public:
UCHAR h[UDIHLEN]; UCHAR h[UDIHLEN];
UdiH(const string& udi) UdiH(const string& udi) {
{
MD5_CTX ctx; MD5_CTX ctx;
MD5Init(&ctx); MD5Init(&ctx);
MD5Update(&ctx, (const UCHAR*)udi.c_str(), udi.length()); MD5Update(&ctx, (const UCHAR*)udi.c_str(), udi.length());
@ -168,7 +168,7 @@ public:
} }
string asHexString() const { string asHexString() const {
static const char hex[]="0123456789abcdef"; static const char hex[] = "0123456789abcdef";
string out; string out;
for (int i = 0; i < UDIHLEN; i++) { for (int i = 0; i < UDIHLEN; i++) {
out.append(1, hex[h[i] >> 4]); out.append(1, hex[h[i] >> 4]);
@ -176,21 +176,22 @@ public:
} }
return out; return out;
} }
bool operator==(const UdiH& r) const bool operator==(const UdiH& r) const {
{
for (int i = 0; i < UDIHLEN; i++) for (int i = 0; i < UDIHLEN; i++)
if (h[i] != r.h[i]) if (h[i] != r.h[i]) {
return false; return false;
}
return true; return true;
} }
bool operator<(const UdiH& r) const bool operator<(const UdiH& r) const {
{
for (int i = 0; i < UDIHLEN; i++) { for (int i = 0; i < UDIHLEN; i++) {
if (h[i] < r.h[i]) if (h[i] < r.h[i]) {
return true; return true;
if (h[i] > r.h[i]) }
if (h[i] > r.h[i]) {
return false; return false;
} }
}
return false; return false;
} }
}; };
@ -231,8 +232,7 @@ public:
bool m_ofskhcplt; // Has cache been fully read since open? bool m_ofskhcplt; // Has cache been fully read since open?
// Add udi->offset translation to map // Add udi->offset translation to map
bool khEnter(const string& udi, off_t ofs) bool khEnter(const string& udi, off_t ofs) {
{
UdiH h(udi); UdiH h(udi);
LOGDEB2(("Circache::khEnter: h %s offs %lu udi [%s]\n", LOGDEB2(("Circache::khEnter: h %s offs %lu udi [%s]\n",
@ -256,8 +256,7 @@ public:
LOGDEB2(("Circache::khEnter: inserted\n")); LOGDEB2(("Circache::khEnter: inserted\n"));
return true; return true;
} }
void khDump() void khDump() {
{
for (kh_type::const_iterator it = m_ofskh.begin(); for (kh_type::const_iterator it = m_ofskh.begin();
it != m_ofskh.end(); it++) { it != m_ofskh.end(); it++) {
LOGDEB(("Circache::KHDUMP: %s %d\n", LOGDEB(("Circache::KHDUMP: %s %d\n",
@ -268,8 +267,7 @@ public:
// Return vector of candidate offsets for udi (possibly several // Return vector of candidate offsets for udi (possibly several
// because there may be hash collisions, and also multiple // because there may be hash collisions, and also multiple
// instances). // instances).
bool khFind(const string& udi, vector<off_t>& ofss) bool khFind(const string& udi, vector<off_t>& ofss) {
{
ofss.clear(); ofss.clear();
UdiH h(udi); UdiH h(udi);
@ -280,16 +278,21 @@ public:
pair<kh_type::iterator, kh_type::iterator> p = m_ofskh.equal_range(h); pair<kh_type::iterator, kh_type::iterator> p = m_ofskh.equal_range(h);
#if 0 #if 0
if (p.first == m_ofskh.end()) LOGDEB(("KHFIND: FIRST END()\n")); if (p.first == m_ofskh.end()) {
if (p.second == m_ofskh.end()) LOGDEB(("KHFIND: SECOND END()\n")); LOGDEB(("KHFIND: FIRST END()\n"));
}
if (p.second == m_ofskh.end()) {
LOGDEB(("KHFIND: SECOND END()\n"));
}
if (!(p.first->first == h)) if (!(p.first->first == h))
LOGDEB(("KHFIND: NOKEY: %s %s\n", LOGDEB(("KHFIND: NOKEY: %s %s\n",
p.first->first.asHexString().c_str(), p.first->first.asHexString().c_str(),
p.second->first.asHexString().c_str())); p.second->first.asHexString().c_str()));
#endif #endif
if (p.first == m_ofskh.end() || !(p.first->first == h)) if (p.first == m_ofskh.end() || !(p.first->first == h)) {
return false; return false;
}
for (kh_type::iterator it = p.first; it != p.second; it++) { for (kh_type::iterator it = p.first; it != p.second; it++) {
ofss.push_back(it->second); ofss.push_back(it->second);
@ -297,34 +300,33 @@ public:
return true; return true;
} }
// Clear entry for udi/offs // Clear entry for udi/offs
bool khClear(const pair<string, off_t>& ref) bool khClear(const pair<string, off_t>& ref) {
{
UdiH h(ref.first); UdiH h(ref.first);
pair<kh_type::iterator, kh_type::iterator> p = m_ofskh.equal_range(h); pair<kh_type::iterator, kh_type::iterator> p = m_ofskh.equal_range(h);
if (p.first != m_ofskh.end() && (p.first->first == h)) { if (p.first != m_ofskh.end() && (p.first->first == h)) {
for (kh_type::iterator it = p.first; it != p.second; ) { for (kh_type::iterator it = p.first; it != p.second;) {
kh_type::iterator tmp = it++; kh_type::iterator tmp = it++;
if (tmp->second == ref.second) if (tmp->second == ref.second) {
m_ofskh.erase(tmp); m_ofskh.erase(tmp);
} }
} }
}
return true; return true;
} }
// Clear entries for vector of udi/offs // Clear entries for vector of udi/offs
bool khClear(const vector<pair<string, off_t> >& udis) bool khClear(const vector<pair<string, off_t> >& udis) {
{
for (vector<pair<string, off_t> >::const_iterator it = udis.begin(); for (vector<pair<string, off_t> >::const_iterator it = udis.begin();
it != udis.end(); it++) it != udis.end(); it++) {
khClear(*it); khClear(*it);
}
return true; return true;
} }
// Clear all entries for udi // Clear all entries for udi
bool khClear(const string& udi) bool khClear(const string& udi) {
{
UdiH h(udi); UdiH h(udi);
pair<kh_type::iterator, kh_type::iterator> p = m_ofskh.equal_range(h); pair<kh_type::iterator, kh_type::iterator> p = m_ofskh.equal_range(h);
if (p.first != m_ofskh.end() && (p.first->first == h)) { if (p.first != m_ofskh.end() && (p.first->first == h)) {
for (kh_type::iterator it = p.first; it != p.second; ) { for (kh_type::iterator it = p.first; it != p.second;) {
kh_type::iterator tmp = it++; kh_type::iterator tmp = it++;
m_ofskh.erase(tmp); m_ofskh.erase(tmp);
} }
@ -334,21 +336,22 @@ public:
CirCacheInternal() CirCacheInternal()
: m_fd(-1), m_maxsize(-1), m_oheadoffs(-1), : m_fd(-1), m_maxsize(-1), m_oheadoffs(-1),
m_nheadoffs(0), m_npadsize(0), m_uniquentries(false), m_nheadoffs(0), m_npadsize(0), m_uniquentries(false),
m_buffer(0), m_bufsiz(0), m_ofskhcplt(false) m_buffer(0), m_bufsiz(0), m_ofskhcplt(false) {
{}
~CirCacheInternal()
{
if (m_fd >= 0)
close(m_fd);
if (m_buffer)
free(m_buffer);
} }
char *buf(size_t sz) ~CirCacheInternal() {
{ if (m_fd >= 0) {
if (m_bufsiz >= sz) close(m_fd);
}
if (m_buffer) {
free(m_buffer);
}
}
char *buf(size_t sz) {
if (m_bufsiz >= sz) {
return m_buffer; return m_buffer;
}
if ((m_buffer = (char *)realloc(m_buffer, sz))) { if ((m_buffer = (char *)realloc(m_buffer, sz))) {
m_bufsiz = sz; m_bufsiz = sz;
} else { } else {
@ -359,8 +362,7 @@ public:
} }
// Name for the cache file // Name for the cache file
string datafn(const string& d) string datafn(const string& d) {
{
return path_cat(d, "circache.crch"); return path_cat(d, "circache.crch");
} }
@ -392,8 +394,7 @@ public:
return true; return true;
} }
bool readfirstblock() bool readfirstblock() {
{
if (m_fd < 0) { if (m_fd < 0) {
m_reason << "readfirstblock: not open "; m_reason << "readfirstblock: not open ";
return false; return false;
@ -438,8 +439,7 @@ public:
return true; return true;
} }
bool writeEntryHeader(off_t offset, const EntryHeaderData& d) bool writeEntryHeader(off_t offset, const EntryHeaderData& d) {
{
if (m_fd < 0) { if (m_fd < 0) {
m_reason << "writeEntryHeader: not open "; m_reason << "writeEntryHeader: not open ";
return false; return false;
@ -460,8 +460,7 @@ public:
return true; return true;
} }
CCScanHook::status readEntryHeader(off_t offset, EntryHeaderData& d) CCScanHook::status readEntryHeader(off_t offset, EntryHeaderData& d) {
{
if (m_fd < 0) { if (m_fd < 0) {
m_reason << "readEntryHeader: not open "; m_reason << "readEntryHeader: not open ";
return CCScanHook::Error; return CCScanHook::Error;
@ -496,8 +495,7 @@ public:
} }
CCScanHook::status scan(off_t startoffset, CCScanHook *user, CCScanHook::status scan(off_t startoffset, CCScanHook *user,
bool fold = false) bool fold = false) {
{
if (m_fd < 0) { if (m_fd < 0) {
m_reason << "scan: not open "; m_reason << "scan: not open ";
return CCScanHook::Error; return CCScanHook::Error;
@ -515,7 +513,8 @@ public:
EntryHeaderData d; EntryHeaderData d;
CCScanHook::status st; CCScanHook::status st;
switch ((st = readEntryHeader(startoffset, d))) { switch ((st = readEntryHeader(startoffset, d))) {
case CCScanHook::Continue: break; case CCScanHook::Continue:
break;
case CCScanHook::Eof: case CCScanHook::Eof:
if (fold && !already_folded) { if (fold && !already_folded) {
already_folded = true; already_folded = true;
@ -531,7 +530,7 @@ public:
if (d.dicsize) { if (d.dicsize) {
// d.dicsize is 0 for erased entries // d.dicsize is 0 for erased entries
char *bf; char *bf;
if ((bf = buf(d.dicsize+1)) == 0) { if ((bf = buf(d.dicsize + 1)) == 0) {
return CCScanHook::Error; return CCScanHook::Error;
} }
bf[d.dicsize] = 0; bf[d.dicsize] = 0;
@ -564,13 +563,14 @@ public:
} }
} }
bool readHUdi(off_t hoffs, EntryHeaderData& d, string& udi) bool readHUdi(off_t hoffs, EntryHeaderData& d, string& udi) {
{ if (readEntryHeader(hoffs, d) != CCScanHook::Continue) {
if (readEntryHeader(hoffs, d) != CCScanHook::Continue)
return false; return false;
}
string dic; string dic;
if (!readDicData(hoffs, d, dic, 0)) if (!readDicData(hoffs, d, dic, 0)) {
return false; return false;
}
if (d.dicsize == 0) { if (d.dicsize == 0) {
// This is an erased entry // This is an erased entry
udi.erase(); udi.erase();
@ -585,8 +585,7 @@ public:
} }
bool readDicData(off_t hoffs, EntryHeaderData& hd, string& dic, bool readDicData(off_t hoffs, EntryHeaderData& hd, string& dic,
string* data) string* data) {
{
off_t offs = hoffs + CIRCACHE_HEADER_SIZE; off_t offs = hoffs + CIRCACHE_HEADER_SIZE;
// This syscall could be avoided in some cases if we saved the offset // This syscall could be avoided in some cases if we saved the offset
// at each seek. In most cases, we just read the header and we are // at each seek. In most cases, we just read the header and we are
@ -599,8 +598,9 @@ public:
char *bf = 0; char *bf = 0;
if (hd.dicsize) { if (hd.dicsize) {
bf = buf(hd.dicsize); bf = buf(hd.dicsize);
if (bf == 0) if (bf == 0) {
return false; return false;
}
if (read(m_fd, bf, hd.dicsize) != int(hd.dicsize)) { if (read(m_fd, bf, hd.dicsize) != int(hd.dicsize)) {
m_reason << "CirCache::get: read() failed: errno " << errno; m_reason << "CirCache::get: read() failed: errno " << errno;
return false; return false;
@ -609,14 +609,16 @@ public:
} else { } else {
dic.erase(); dic.erase();
} }
if (data == 0) if (data == 0) {
return true; return true;
}
if (hd.datasize) { if (hd.datasize) {
bf = buf(hd.datasize); bf = buf(hd.datasize);
if (bf == 0) if (bf == 0) {
return false; return false;
if (read(m_fd, bf, hd.datasize) != int(hd.datasize)){ }
if (read(m_fd, bf, hd.datasize) != int(hd.datasize)) {
m_reason << "CirCache::get: read() failed: errno " << errno; m_reason << "CirCache::get: read() failed: errno " << errno;
return false; return false;
} }
@ -669,12 +671,10 @@ public:
off_t headoffs; off_t headoffs;
off_t padsize; off_t padsize;
CCScanHookRecord() CCScanHookRecord()
: headoffs(0), padsize(0) : headoffs(0), padsize(0) {
{
} }
virtual status takeone(off_t offs, const string& udi, virtual status takeone(off_t offs, const string& udi,
const EntryHeaderData& d) const EntryHeaderData& d) {
{
headoffs = offs; headoffs = offs;
padsize = d.padsize; padsize = d.padsize;
LOGDEB2(("CCScanHookRecord::takeone: offs %s padsize %s\n", LOGDEB2(("CCScanHookRecord::takeone: offs %s padsize %s\n",
@ -745,7 +745,7 @@ bool CirCache::create(off_t maxsize, int flags)
} }
if ((m_d->m_fd = ::open(m_d->datafn(m_dir).c_str(), if ((m_d->m_fd = ::open(m_d->datafn(m_dir).c_str(),
O_CREAT|O_RDWR|O_TRUNC|O_BINARY, 0666)) < 0) { O_CREAT | O_RDWR | O_TRUNC | O_BINARY, 0666)) < 0) {
m_d->m_reason << "CirCache::create: open/creat(" << m_d->m_reason << "CirCache::create: open/creat(" <<
m_d->datafn(m_dir) << ") failed " << "errno " << errno; m_d->datafn(m_dir) << ") failed " << "errno " << errno;
return false; return false;
@ -773,12 +773,13 @@ bool CirCache::open(OpMode mode)
return false; return false;
} }
if (m_d->m_fd >= 0) if (m_d->m_fd >= 0) {
::close(m_d->m_fd); ::close(m_d->m_fd);
}
if ((m_d->m_fd = ::open(m_d->datafn(m_dir).c_str(), if ((m_d->m_fd = ::open(m_d->datafn(m_dir).c_str(),
mode == CC_OPREAD ? mode == CC_OPREAD ?
O_RDONLY|O_BINARY : O_RDWR|O_BINARY)) < 0) { O_RDONLY | O_BINARY : O_RDWR | O_BINARY)) < 0) {
m_d->m_reason << "CirCache::open: open(" << m_d->datafn(m_dir) << m_d->m_reason << "CirCache::open: open(" << m_d->datafn(m_dir) <<
") failed " << "errno " << errno; ") failed " << "errno " << errno;
return false; return false;
@ -789,8 +790,7 @@ bool CirCache::open(OpMode mode)
class CCScanHookDump : public CCScanHook { class CCScanHookDump : public CCScanHook {
public: public:
virtual status takeone(off_t offs, const string& udi, virtual status takeone(off_t offs, const string& udi,
const EntryHeaderData& d) const EntryHeaderData& d) {
{
cout << "Scan: offs " << offs << " dicsize " << d.dicsize cout << "Scan: offs " << offs << " dicsize " << d.dicsize
<< " datasize " << d.datasize << " padsize " << d.padsize << << " datasize " << d.datasize << " padsize " << d.padsize <<
" flags " << d.flags << " flags " << d.flags <<
@ -835,12 +835,11 @@ public:
off_t m_offs; off_t m_offs;
EntryHeaderData m_hd; EntryHeaderData m_hd;
CCScanHookGetter(const string &udi, int ti) CCScanHookGetter(const string& udi, int ti)
: m_udi(udi), m_targinstance(ti), m_instance(0), m_offs(0){} : m_udi(udi), m_targinstance(ti), m_instance(0), m_offs(0) {}
virtual status takeone(off_t offs, const string& udi, virtual status takeone(off_t offs, const string& udi,
const EntryHeaderData& d) const EntryHeaderData& d) {
{
LOGDEB2(("Circache:Scan: off %ld udi [%s] dcsz %u dtsz %u pdsz %u " LOGDEB2(("Circache:Scan: off %ld udi [%s] dcsz %u dtsz %u pdsz %u "
" flgs %hu\n", " flgs %hu\n",
long(offs), udi.c_str(), (UINT)d.dicsize, long(offs), udi.c_str(), (UINT)d.dicsize,
@ -849,9 +848,10 @@ public:
m_instance++; m_instance++;
m_offs = offs; m_offs = offs;
m_hd = d; m_hd = d;
if (m_instance == m_targinstance) if (m_instance == m_targinstance) {
return Stop; return Stop;
} }
}
return Continue; return Continue;
} }
}; };
@ -882,8 +882,9 @@ bool CirCache::get(const string& udi, string& dic, string& data, int instance)
LOGDEB1(("Circache::get: trying offs %lu\n", (ULONG)*it)); LOGDEB1(("Circache::get: trying offs %lu\n", (ULONG)*it));
EntryHeaderData d; EntryHeaderData d;
string fudi; string fudi;
if (!m_d->readHUdi(*it, d, fudi)) if (!m_d->readHUdi(*it, d, fudi)) {
return false; return false;
}
if (!fudi.compare(udi)) { if (!fudi.compare(udi)) {
// Found one, memorize offset. Done if instance // Found one, memorize offset. Done if instance
// matches, else go on. If instance is -1 need to // matches, else go on. If instance is -1 need to
@ -913,8 +914,9 @@ bool CirCache::get(const string& udi, string& dic, string& data, int instance)
CCScanHook::status ret = m_d->scan(start, &getter, true); CCScanHook::status ret = m_d->scan(start, &getter, true);
if (ret == CCScanHook::Eof) { if (ret == CCScanHook::Eof) {
if (getter.m_instance == 0) if (getter.m_instance == 0) {
return false; return false;
}
} else if (ret != CCScanHook::Stop) { } else if (ret != CCScanHook::Stop) {
return false; return false;
} }
@ -960,16 +962,18 @@ bool CirCache::erase(const string& udi)
LOGDEB(("CirCache::erase: reading at %lu\n", (unsigned long)*it)); LOGDEB(("CirCache::erase: reading at %lu\n", (unsigned long)*it));
EntryHeaderData d; EntryHeaderData d;
string fudi; string fudi;
if (!m_d->readHUdi(*it, d, fudi)) if (!m_d->readHUdi(*it, d, fudi)) {
return false; return false;
}
LOGDEB(("CirCache::erase: found fudi [%s]\n", fudi.c_str())); LOGDEB(("CirCache::erase: found fudi [%s]\n", fudi.c_str()));
if (!fudi.compare(udi)) { if (!fudi.compare(udi)) {
EntryHeaderData nd; EntryHeaderData nd;
nd.padsize = d.dicsize + d.datasize + d.padsize; nd.padsize = d.dicsize + d.datasize + d.padsize;
LOGDEB(("CirCache::erase: rewriting at %lu\n", (unsigned long)*it)); LOGDEB(("CirCache::erase: rewriting at %lu\n", (unsigned long)*it));
if (*it == m_d->m_nheadoffs) if (*it == m_d->m_nheadoffs) {
m_d->m_npadsize = nd.padsize; m_d->m_npadsize = nd.padsize;
if(!m_d->writeEntryHeader(*it, nd)) { }
if (!m_d->writeEntryHeader(*it, nd)) {
LOGERR(("CirCache::erase: write header failed\n")); LOGERR(("CirCache::erase: write header failed\n"));
return false; return false;
} }
@ -987,17 +991,19 @@ public:
off_t sizeseen; off_t sizeseen;
vector<pair<string, off_t> > squashed_udis; vector<pair<string, off_t> > squashed_udis;
CCScanHookSpacer(off_t sz) CCScanHookSpacer(off_t sz)
: sizewanted(sz), sizeseen(0) {assert(sz > 0);} : sizewanted(sz), sizeseen(0) {
assert(sz > 0);
}
virtual status takeone(off_t offs, const string& udi, virtual status takeone(off_t offs, const string& udi,
const EntryHeaderData& d) const EntryHeaderData& d) {
{
LOGDEB2(("Circache:ScanSpacer:off %u dcsz %u dtsz %u pdsz %u udi[%s]\n", LOGDEB2(("Circache:ScanSpacer:off %u dcsz %u dtsz %u pdsz %u udi[%s]\n",
(UINT)offs, d.dicsize, d.datasize, d.padsize, udi.c_str())); (UINT)offs, d.dicsize, d.datasize, d.padsize, udi.c_str()));
sizeseen += CIRCACHE_HEADER_SIZE + d.dicsize + d.datasize + d.padsize; sizeseen += CIRCACHE_HEADER_SIZE + d.dicsize + d.datasize + d.padsize;
squashed_udis.push_back(make_pair(udi, offs)); squashed_udis.push_back(make_pair(udi, offs));
if (sizeseen >= sizewanted) if (sizeseen >= sizewanted) {
return Stop; return Stop;
}
return Continue; return Continue;
} }
}; };
@ -1076,7 +1082,7 @@ bool CirCache::put(const string& udi, const ConfSimple *iconf,
// Need to read the latest entry's header, to rewrite it with a // Need to read the latest entry's header, to rewrite it with a
// zero pad size // zero pad size
EntryHeaderData pd; EntryHeaderData pd;
if (m_d->readEntryHeader(m_d->m_nheadoffs, pd) != CCScanHook::Continue){ if (m_d->readEntryHeader(m_d->m_nheadoffs, pd) != CCScanHook::Continue) {
return false; return false;
} }
if (int(pd.padsize) != m_d->m_npadsize) { if (int(pd.padsize) != m_d->m_npadsize) {
@ -1090,8 +1096,9 @@ bool CirCache::put(const string& udi, const ConfSimple *iconf,
} else { } else {
LOGDEB(("CirCache::put: recov. prev. padsize %d\n", pd.padsize)); LOGDEB(("CirCache::put: recov. prev. padsize %d\n", pd.padsize));
pd.padsize = 0; pd.padsize = 0;
if (!m_d->writeEntryHeader(m_d->m_nheadoffs, pd)) if (!m_d->writeEntryHeader(m_d->m_nheadoffs, pd)) {
return false; return false;
}
// If we fail between here and the end, the file is broken. // If we fail between here and the end, the file is broken.
} }
nwriteoffs = m_d->m_oheadoffs - recovpadsize; nwriteoffs = m_d->m_oheadoffs - recovpadsize;
@ -1183,7 +1190,7 @@ bool CirCache::rewind(bool& eof)
eof = false; eof = false;
off_t fsize = lseek(m_d->m_fd, 0, SEEK_END); off_t fsize = lseek(m_d->m_fd, 0, SEEK_END);
if (fsize == (off_t)-1) { if (fsize == (off_t) - 1) {
LOGERR(("CirCache::rewind: seek to EOF failed\n")); LOGERR(("CirCache::rewind: seek to EOF failed\n"));
return false; return false;
} }
@ -1197,7 +1204,7 @@ bool CirCache::rewind(bool& eof)
} }
CCScanHook::status st = m_d->readEntryHeader(m_d->m_itoffs, m_d->m_ithd); CCScanHook::status st = m_d->readEntryHeader(m_d->m_itoffs, m_d->m_ithd);
switch(st) { switch (st) {
case CCScanHook::Eof: case CCScanHook::Eof:
eof = true; eof = true;
return false; return false;
@ -1239,8 +1246,9 @@ bool CirCache::next(bool& eof)
st = m_d->readEntryHeader(m_d->m_itoffs, m_d->m_ithd); st = m_d->readEntryHeader(m_d->m_itoffs, m_d->m_ithd);
} }
if (st == CCScanHook::Continue) if (st == CCScanHook::Continue) {
return true; return true;
}
return false; return false;
} }
@ -1251,8 +1259,9 @@ bool CirCache::getCurrentUdi(string& udi)
return false; return false;
} }
if (!m_d->readHUdi(m_d->m_itoffs, m_d->m_ithd, udi)) if (!m_d->readHUdi(m_d->m_itoffs, m_d->m_ithd, udi)) {
return false; return false;
}
return true; return true;
} }
@ -1262,8 +1271,9 @@ bool CirCache::getCurrent(string& udi, string& dic, string& data)
LOGERR(("CirCache::getCurrent: null data\n")); LOGERR(("CirCache::getCurrent: null data\n"));
return false; 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; return false;
}
ConfSimple conf(dic, 1); ConfSimple conf(dic, 1);
conf.get("udi", udi, cstr_null); conf.get("udi", udi, cstr_null);
@ -1284,8 +1294,9 @@ static void *allocmem(
} }
int inc = (*np > maxinc) ? maxinc : *np; int inc = (*np > maxinc) ? maxinc : *np;
if ((cp = realloc(cp, (*np + inc) * sz)) != 0) if ((cp = realloc(cp, (*np + inc) * sz)) != 0) {
*np += inc; *np += inc;
}
return cp; return cp;
} }
@ -1325,7 +1336,7 @@ static bool inflateToDynBuf(void* inp, UINT inlen, void **outpp, UINT *outlenp)
if ((outp = (char*)allocmem(outp, inlen, &alloc, if ((outp = (char*)allocmem(outp, inlen, &alloc,
imul, mxinc)) == 0) { imul, mxinc)) == 0) {
LOGERR(("Inflate: out of memory, current alloc %d\n", LOGERR(("Inflate: out of memory, current alloc %d\n",
alloc*inlen)); alloc * inlen));
inflateEnd(&d_stream); inflateEnd(&d_stream);
return false; return false;
} else { } else {
@ -1335,7 +1346,9 @@ static bool inflateToDynBuf(void* inp, UINT inlen, void **outpp, UINT *outlenp)
d_stream.next_out = (Bytef*)(outp + d_stream.total_out); d_stream.next_out = (Bytef*)(outp + d_stream.total_out);
} }
err = inflate(&d_stream, Z_NO_FLUSH); err = inflate(&d_stream, Z_NO_FLUSH);
if (err == Z_STREAM_END) break; if (err == Z_STREAM_END) {
break;
}
if (err != Z_OK) { if (err != Z_OK) {
LOGERR(("Inflate: error %d msg %s\n", err, d_stream.msg)); LOGERR(("Inflate: error %d msg %s\n", err, d_stream.msg));
inflateEnd(&d_stream); inflateEnd(&d_stream);
@ -1527,17 +1540,17 @@ bool appendcc(const string ddir, const string& sdir)
static char *thisprog; static char *thisprog;
static char usage [] = static char usage [] =
" -c [-u] <dirname> <sizekbs>: create\n" " -c [-u] <dirname> <sizekbs>: create\n"
" -p <dirname> <apath> [apath ...] : put files\n" " -p <dirname> <apath> [apath ...] : put files\n"
" -d <dirname> : dump\n" " -d <dirname> : dump\n"
" -g [-i instance] [-D] <dirname> <udi>: get\n" " -g [-i instance] [-D] <dirname> <udi>: get\n"
" -D: also dump data\n" " -D: also dump data\n"
" -e <dirname> <udi> : erase\n" " -e <dirname> <udi> : erase\n"
" -s <dirname> <newmbs> : resize\n" " -s <dirname> <newmbs> : resize\n"
" -a <targetdir> <dir> [<dir> ...]: append old content to target\n" " -a <targetdir> <dir> [<dir> ...]: append old content to target\n"
" The target should be first resized to hold all the data, else only\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" " as many entries as capacity permit will be retained\n"
; ;
static void static void
Usage(FILE *fp = stderr) Usage(FILE *fp = stderr)
@ -1564,40 +1577,72 @@ int main(int argc, char **argv)
int instance = -1; int instance = -1;
thisprog = argv[0]; thisprog = argv[0];
argc--; argv++; argc--;
argv++;
while (argc > 0 && **argv == '-') { while (argc > 0 && **argv == '-') {
(*argv)++; (*argv)++;
if (!(**argv)) if (!(**argv))
/* Cas du "adb - core" */ /* Cas du "adb - core" */
{
Usage(); Usage();
}
while (**argv) while (**argv)
switch (*(*argv)++) { switch (*(*argv)++) {
case 'a': op_flags |= OPT_a; break; case 'a':
case 'c': op_flags |= OPT_c; break; op_flags |= OPT_a;
case 'D': op_flags |= OPT_D; break; break;
case 'd': op_flags |= OPT_d; break; case 'c':
case 'e': op_flags |= OPT_e; break; op_flags |= OPT_c;
case 'g': op_flags |= OPT_g; break; break;
case 'i': op_flags |= OPT_i; if (argc < 2) Usage(); case 'D':
if ((sscanf(*(++argv), "%d", &instance)) != 1) op_flags |= OPT_D;
break;
case 'd':
op_flags |= OPT_d;
break;
case 'e':
op_flags |= OPT_e;
break;
case 'g':
op_flags |= OPT_g;
break;
case 'i':
op_flags |= OPT_i;
if (argc < 2) {
Usage(); Usage();
}
if ((sscanf(*(++argv), "%d", &instance)) != 1) {
Usage();
}
argc--; argc--;
goto b1; goto b1;
case 'p': op_flags |= OPT_p; break; case 'p':
case 's': op_flags |= OPT_s; break; op_flags |= OPT_p;
case 'u': op_flags |= OPT_u; break; break;
default: Usage(); break; case 's':
op_flags |= OPT_s;
break;
case 'u':
op_flags |= OPT_u;
break;
default:
Usage();
break;
} }
b1: argc--; argv++; b1:
argc--;
argv++;
} }
DebugLog::getdbl()->setloglevel(DEBERR); DebugLog::getdbl()->setloglevel(DEBERR);
DebugLog::setfilename("stderr"); DebugLog::setfilename("stderr");
if (argc < 1) if (argc < 1) {
Usage(); Usage();
string dir = *argv++;argc--; }
string dir = *argv++;
argc--;
CirCache cc(dir); CirCache cc(dir);
@ -1605,11 +1650,13 @@ int main(int argc, char **argv)
if (argc != 1) { if (argc != 1) {
Usage(); Usage();
} }
off_t sizekb = atoi(*argv++);argc--; off_t sizekb = atoi(*argv++);
argc--;
int flags = 0; int flags = 0;
if (op_flags & OPT_u) if (op_flags & OPT_u) {
flags |= CirCache::CC_CRUNIQUE; flags |= CirCache::CC_CRUNIQUE;
if (!cc.create(sizekb*1024, flags)) { }
if (!cc.create(sizekb * 1024, flags)) {
cerr << "Create failed:" << cc.getReason() << endl; cerr << "Create failed:" << cc.getReason() << endl;
exit(1); exit(1);
} }
@ -1617,7 +1664,8 @@ int main(int argc, char **argv)
if (argc != 1) { if (argc != 1) {
Usage(); Usage();
} }
int newmbs = atoi(*argv++);argc--; int newmbs = atoi(*argv++);
argc--;
if (!resizecc(dir, newmbs)) { if (!resizecc(dir, newmbs)) {
exit(1); exit(1);
} }
@ -1632,14 +1680,16 @@ int main(int argc, char **argv)
argc--; argc--;
} }
} else if (op_flags & OPT_p) { } else if (op_flags & OPT_p) {
if (argc < 1) if (argc < 1) {
Usage(); Usage();
}
if (!cc.open(CirCache::CC_OPWRITE)) { if (!cc.open(CirCache::CC_OPWRITE)) {
cerr << "Open failed: " << cc.getReason() << endl; cerr << "Open failed: " << cc.getReason() << endl;
exit(1); exit(1);
} }
while (argc) { while (argc) {
string fn = *argv++;argc--; string fn = *argv++;
argc--;
char dic[1000]; char dic[1000];
string data, reason; string data, reason;
if (!file_to_string(fn, data, &reason)) { if (!file_to_string(fn, data, &reason)) {
@ -1656,7 +1706,9 @@ int main(int argc, char **argv)
if (!cc.put(udi, &conf, data, 0)) { if (!cc.put(udi, &conf, data, 0)) {
cerr << "Put failed: " << cc.getReason() << endl; cerr << "Put failed: " << cc.getReason() << endl;
cerr << "conf: ["; conf.write(cerr); cerr << "]" << endl; cerr << "conf: [";
conf.write(cerr);
cerr << "]" << endl;
exit(1); exit(1);
} }
} }
@ -1667,23 +1719,26 @@ int main(int argc, char **argv)
exit(1); exit(1);
} }
while (argc) { while (argc) {
string udi = *argv++;argc--; string udi = *argv++;
argc--;
string dic, data; string dic, data;
if (!cc.get(udi, dic, data, instance)) { if (!cc.get(udi, dic, data, instance)) {
cerr << "Get failed: " << cc.getReason() << endl; cerr << "Get failed: " << cc.getReason() << endl;
exit(1); exit(1);
} }
cout << "Dict: [" << dic << "]" << endl; cout << "Dict: [" << dic << "]" << endl;
if (op_flags & OPT_D) if (op_flags & OPT_D) {
cout << "Data: [" << data << "]" << endl; cout << "Data: [" << data << "]" << endl;
} }
}
} else if (op_flags & OPT_e) { } else if (op_flags & OPT_e) {
if (!cc.open(CirCache::CC_OPWRITE)) { if (!cc.open(CirCache::CC_OPWRITE)) {
cerr << "Open failed: " << cc.getReason() << endl; cerr << "Open failed: " << cc.getReason() << endl;
exit(1); exit(1);
} }
while (argc) { while (argc) {
string udi = *argv++;argc--; string udi = *argv++;
argc--;
string dic, data; string dic, data;
if (!cc.erase(udi)) { if (!cc.erase(udi)) {
cerr << "Erase failed: " << cc.getReason() << endl; cerr << "Erase failed: " << cc.getReason() << endl;
@ -1696,8 +1751,9 @@ int main(int argc, char **argv)
exit(1); exit(1);
} }
cc.dump(); cc.dump();
} else } else {
Usage(); Usage();
}
exit(0); exit(0);
} }

View File

@ -40,26 +40,23 @@
#include <string> #include <string>
#ifndef NO_NAMESPACES
using std::string;
#endif
class ConfSimple; class ConfSimple;
class CirCacheInternal; class CirCacheInternal;
class CirCache { class CirCache {
public: public:
CirCache(const string& dir); CirCache(const std::string& dir);
virtual ~CirCache(); virtual ~CirCache();
virtual string getReason(); virtual std::string getReason();
enum CreateFlags {CC_CRNONE=0, enum CreateFlags {CC_CRNONE = 0,
// Unique entries: erase older instances when same udi // Unique entries: erase older instances when same udi
// is stored. // is stored.
CC_CRUNIQUE=1, CC_CRUNIQUE = 1,
// Truncate file (restart from scratch). // Truncate file (restart from scratch).
CC_CRTRUNCATE = 2}; CC_CRTRUNCATE = 2
};
virtual bool create(off_t maxsize, int flags); virtual bool create(off_t maxsize, int flags);
enum OpMode {CC_OPREAD, CC_OPWRITE}; enum OpMode {CC_OPREAD, CC_OPWRITE};
@ -67,15 +64,15 @@ public:
virtual std::string getpath(); virtual std::string getpath();
virtual bool get(const string& udi, string& dic, string& data, virtual bool get(const std::string& udi, std::string& dic,
int instance = -1); std::string& data, int instance = -1);
// Note: the dicp MUST have an udi entry // Note: the dicp MUST have an udi entry
enum PutFlags {NoCompHint = 1}; enum PutFlags {NoCompHint = 1};
virtual bool put(const string& udi, const ConfSimple *dicp, virtual bool put(const std::string& udi, const ConfSimple *dicp,
const string& data, unsigned int flags = 0); const std::string& data, unsigned int flags = 0);
virtual bool erase(const string& udi); virtual bool erase(const std::string& udi);
/** Walk the archive. /** Walk the archive.
* *
@ -86,10 +83,11 @@ public:
/** Back to oldest */ /** Back to oldest */
virtual bool rewind(bool& eof); virtual bool rewind(bool& eof);
/** Get entry under cursor */ /** Get entry under cursor */
virtual bool getCurrent(string& udi, string& dic, string& data); virtual bool getCurrent(std::string& udi, std::string& dic,
std::string& data);
/** Get current entry udi only. Udi can be empty (erased empty), caller /** Get current entry udi only. Udi can be empty (erased empty), caller
* should call again */ * should call again */
virtual bool getCurrentUdi(string& udi); virtual bool getCurrentUdi(std::string& udi);
/** Skip to next. (false && !eof) -> error, (false&&eof)->EOF. */ /** Skip to next. (false && !eof) -> error, (false&&eof)->EOF. */
virtual bool next(bool& eof); virtual bool next(bool& eof);
@ -98,10 +96,12 @@ public:
protected: protected:
CirCacheInternal *m_d; CirCacheInternal *m_d;
string m_dir; std::string m_dir;
private: private:
CirCache(const CirCache&) {} CirCache(const CirCache&) {}
CirCache& operator=(const CirCache&) {return *this;} CirCache& operator=(const CirCache&) {
return *this;
}
}; };
#endif /* _circache_h_included_ */ #endif /* _circache_h_included_ */