|
a/src/utils/circache.cpp |
|
b/src/utils/circache.cpp |
|
... |
|
... |
143 |
// A callback class for the header-hopping function.
|
143 |
// A callback class for the header-hopping function.
|
144 |
class CCScanHook {
|
144 |
class CCScanHook {
|
145 |
public:
|
145 |
public:
|
146 |
virtual ~CCScanHook() {}
|
146 |
virtual ~CCScanHook() {}
|
147 |
enum status {Stop, Continue, Error, Eof};
|
147 |
enum status {Stop, Continue, Error, Eof};
|
148 |
virtual status takeone(off_t offs, const string& udi,
|
148 |
virtual status takeone(int64_t offs, const string& udi,
|
149 |
const EntryHeaderData& d) = 0;
|
149 |
const EntryHeaderData& d) = 0;
|
150 |
};
|
150 |
};
|
151 |
|
151 |
|
152 |
// We have an auxiliary in-memory multimap of hashed-udi -> offset to
|
152 |
// We have an auxiliary in-memory multimap of hashed-udi -> offset to
|
153 |
// speed things up. This is created the first time the file is scanned
|
153 |
// speed things up. This is created the first time the file is scanned
|
|
... |
|
... |
195 |
}
|
195 |
}
|
196 |
}
|
196 |
}
|
197 |
return false;
|
197 |
return false;
|
198 |
}
|
198 |
}
|
199 |
};
|
199 |
};
|
200 |
typedef multimap<UdiH, off_t> kh_type;
|
200 |
typedef multimap<UdiH, int64_t> kh_type;
|
201 |
typedef multimap<UdiH, off_t>::value_type kh_value_type;
|
201 |
typedef multimap<UdiH, int64_t>::value_type kh_value_type;
|
202 |
|
202 |
|
203 |
class CirCacheInternal {
|
203 |
class CirCacheInternal {
|
204 |
public:
|
204 |
public:
|
205 |
int m_fd;
|
205 |
int m_fd;
|
206 |
////// These are cache persistent state and written to the first block:
|
206 |
////// These are cache persistent state and written to the first block:
|
207 |
// Maximum file size, after which we begin reusing old space
|
207 |
// Maximum file size, after which we begin reusing old space
|
208 |
off_t m_maxsize;
|
208 |
int64_t m_maxsize;
|
209 |
// Offset of the oldest header, or max file offset (file size)
|
209 |
// Offset of the oldest header, or max file offset (file size)
|
210 |
// while the file is growing. This is the next write position.
|
210 |
// while the file is growing. This is the next write position.
|
211 |
off_t m_oheadoffs;
|
211 |
int64_t m_oheadoffs;
|
212 |
// Offset of last write (newest header)
|
212 |
// Offset of last write (newest header)
|
213 |
off_t m_nheadoffs;
|
213 |
int64_t m_nheadoffs;
|
214 |
// Pad size for newest entry.
|
214 |
// Pad size for newest entry.
|
215 |
off_t m_npadsize;
|
215 |
int64_t m_npadsize;
|
216 |
// Keep history or only last entry
|
216 |
// Keep history or only last entry
|
217 |
bool m_uniquentries;
|
217 |
bool m_uniquentries;
|
218 |
///////////////////// End header entries
|
218 |
///////////////////// End header entries
|
219 |
|
219 |
|
220 |
// A place to hold data when reading
|
220 |
// A place to hold data when reading
|
|
... |
|
... |
224 |
// Error messages
|
224 |
// Error messages
|
225 |
ostringstream m_reason;
|
225 |
ostringstream m_reason;
|
226 |
|
226 |
|
227 |
// State for rewind/next/getcurrent operation. This could/should
|
227 |
// State for rewind/next/getcurrent operation. This could/should
|
228 |
// be moved to a separate iterator.
|
228 |
// be moved to a separate iterator.
|
229 |
off_t m_itoffs;
|
229 |
int64_t m_itoffs;
|
230 |
EntryHeaderData m_ithd;
|
230 |
EntryHeaderData m_ithd;
|
231 |
|
231 |
|
232 |
// Offset cache
|
232 |
// Offset cache
|
233 |
kh_type m_ofskh;
|
233 |
kh_type m_ofskh;
|
234 |
bool m_ofskhcplt; // Has cache been fully read since open?
|
234 |
bool m_ofskhcplt; // Has cache been fully read since open?
|
235 |
|
235 |
|
236 |
// Add udi->offset translation to map
|
236 |
// Add udi->offset translation to map
|
237 |
bool khEnter(const string& udi, off_t ofs) {
|
237 |
bool khEnter(const string& udi, int64_t ofs) {
|
238 |
UdiH h(udi);
|
238 |
UdiH h(udi);
|
239 |
|
239 |
|
240 |
LOGDEB2("Circache::khEnter: h " << (h.asHexString()) << " offs " << ((ULONG)ofs) << " udi [" << (udi) << "]\n" );
|
240 |
LOGDEB2("Circache::khEnter: h " << (h.asHexString()) << " offs " << ((ULONG)ofs) << " udi [" << (udi) << "]\n" );
|
241 |
|
241 |
|
242 |
pair<kh_type::iterator, kh_type::iterator> p = m_ofskh.equal_range(h);
|
242 |
pair<kh_type::iterator, kh_type::iterator> p = m_ofskh.equal_range(h);
|
|
... |
|
... |
263 |
}
|
263 |
}
|
264 |
|
264 |
|
265 |
// Return vector of candidate offsets for udi (possibly several
|
265 |
// Return vector of candidate offsets for udi (possibly several
|
266 |
// because there may be hash collisions, and also multiple
|
266 |
// because there may be hash collisions, and also multiple
|
267 |
// instances).
|
267 |
// instances).
|
268 |
bool khFind(const string& udi, vector<off_t>& ofss) {
|
268 |
bool khFind(const string& udi, vector<int64_t>& ofss) {
|
269 |
ofss.clear();
|
269 |
ofss.clear();
|
270 |
|
270 |
|
271 |
UdiH h(udi);
|
271 |
UdiH h(udi);
|
272 |
|
272 |
|
273 |
LOGDEB2("Circache::khFind: h " << (h.asHexString()) << " udi [" << (udi) << "]\n" );
|
273 |
LOGDEB2("Circache::khFind: h " << (h.asHexString()) << " udi [" << (udi) << "]\n" );
|
|
... |
|
... |
293 |
ofss.push_back(it->second);
|
293 |
ofss.push_back(it->second);
|
294 |
}
|
294 |
}
|
295 |
return true;
|
295 |
return true;
|
296 |
}
|
296 |
}
|
297 |
// Clear entry for udi/offs
|
297 |
// Clear entry for udi/offs
|
298 |
bool khClear(const pair<string, off_t>& ref) {
|
298 |
bool khClear(const pair<string, int64_t>& ref) {
|
299 |
UdiH h(ref.first);
|
299 |
UdiH h(ref.first);
|
300 |
pair<kh_type::iterator, kh_type::iterator> p = m_ofskh.equal_range(h);
|
300 |
pair<kh_type::iterator, kh_type::iterator> p = m_ofskh.equal_range(h);
|
301 |
if (p.first != m_ofskh.end() && (p.first->first == h)) {
|
301 |
if (p.first != m_ofskh.end() && (p.first->first == h)) {
|
302 |
for (kh_type::iterator it = p.first; it != p.second;) {
|
302 |
for (kh_type::iterator it = p.first; it != p.second;) {
|
303 |
kh_type::iterator tmp = it++;
|
303 |
kh_type::iterator tmp = it++;
|
|
... |
|
... |
307 |
}
|
307 |
}
|
308 |
}
|
308 |
}
|
309 |
return true;
|
309 |
return true;
|
310 |
}
|
310 |
}
|
311 |
// Clear entries for vector of udi/offs
|
311 |
// Clear entries for vector of udi/offs
|
312 |
bool khClear(const vector<pair<string, off_t> >& udis) {
|
312 |
bool khClear(const vector<pair<string, int64_t> >& udis) {
|
313 |
for (vector<pair<string, off_t> >::const_iterator it = udis.begin();
|
313 |
for (vector<pair<string, int64_t> >::const_iterator it = udis.begin();
|
314 |
it != udis.end(); it++) {
|
314 |
it != udis.end(); it++) {
|
315 |
khClear(*it);
|
315 |
khClear(*it);
|
316 |
}
|
316 |
}
|
317 |
return true;
|
317 |
return true;
|
318 |
}
|
318 |
}
|
|
... |
|
... |
432 |
m_uniquentries = stringToBool(value);
|
432 |
m_uniquentries = stringToBool(value);
|
433 |
}
|
433 |
}
|
434 |
return true;
|
434 |
return true;
|
435 |
}
|
435 |
}
|
436 |
|
436 |
|
437 |
bool writeEntryHeader(off_t offset, const EntryHeaderData& d,
|
437 |
bool writeEntryHeader(int64_t offset, const EntryHeaderData& d,
|
438 |
bool eraseData = false) {
|
438 |
bool eraseData = false) {
|
439 |
if (m_fd < 0) {
|
439 |
if (m_fd < 0) {
|
440 |
m_reason << "writeEntryHeader: not open ";
|
440 |
m_reason << "writeEntryHeader: not open ";
|
441 |
return false;
|
441 |
return false;
|
442 |
}
|
442 |
}
|
|
... |
|
... |
465 |
}
|
465 |
}
|
466 |
}
|
466 |
}
|
467 |
return true;
|
467 |
return true;
|
468 |
}
|
468 |
}
|
469 |
|
469 |
|
470 |
CCScanHook::status readEntryHeader(off_t offset, EntryHeaderData& d) {
|
470 |
CCScanHook::status readEntryHeader(int64_t offset, EntryHeaderData& d) {
|
471 |
if (m_fd < 0) {
|
471 |
if (m_fd < 0) {
|
472 |
m_reason << "readEntryHeader: not open ";
|
472 |
m_reason << "readEntryHeader: not open ";
|
473 |
return CCScanHook::Error;
|
473 |
return CCScanHook::Error;
|
474 |
}
|
474 |
}
|
475 |
|
475 |
|
|
... |
|
... |
498 |
}
|
498 |
}
|
499 |
LOGDEB2("Circache:readEntryHeader: dcsz " << (d.dicsize) << " dtsz " << (d.datasize) << " pdsz " << (d.padsize) << " flgs " << (d.flags) << "\n" );
|
499 |
LOGDEB2("Circache:readEntryHeader: dcsz " << (d.dicsize) << " dtsz " << (d.datasize) << " pdsz " << (d.padsize) << " flgs " << (d.flags) << "\n" );
|
500 |
return CCScanHook::Continue;
|
500 |
return CCScanHook::Continue;
|
501 |
}
|
501 |
}
|
502 |
|
502 |
|
503 |
CCScanHook::status scan(off_t startoffset, CCScanHook *user,
|
503 |
CCScanHook::status scan(int64_t startoffset, CCScanHook *user,
|
504 |
bool fold = false) {
|
504 |
bool fold = false) {
|
505 |
if (m_fd < 0) {
|
505 |
if (m_fd < 0) {
|
506 |
m_reason << "scan: not open ";
|
506 |
m_reason << "scan: not open ";
|
507 |
return CCScanHook::Error;
|
507 |
return CCScanHook::Error;
|
508 |
}
|
508 |
}
|
509 |
|
509 |
|
510 |
off_t so0 = startoffset;
|
510 |
int64_t so0 = startoffset;
|
511 |
bool already_folded = false;
|
511 |
bool already_folded = false;
|
512 |
|
512 |
|
513 |
while (true) {
|
513 |
while (true) {
|
514 |
if (already_folded && startoffset == so0) {
|
514 |
if (already_folded && startoffset == so0) {
|
515 |
m_ofskhcplt = true;
|
515 |
m_ofskhcplt = true;
|
|
... |
|
... |
567 |
startoffset += CIRCACHE_HEADER_SIZE + d.dicsize +
|
567 |
startoffset += CIRCACHE_HEADER_SIZE + d.dicsize +
|
568 |
d.datasize + d.padsize;
|
568 |
d.datasize + d.padsize;
|
569 |
}
|
569 |
}
|
570 |
}
|
570 |
}
|
571 |
|
571 |
|
572 |
bool readHUdi(off_t hoffs, EntryHeaderData& d, string& udi) {
|
572 |
bool readHUdi(int64_t hoffs, EntryHeaderData& d, string& udi) {
|
573 |
if (readEntryHeader(hoffs, d) != CCScanHook::Continue) {
|
573 |
if (readEntryHeader(hoffs, d) != CCScanHook::Continue) {
|
574 |
return false;
|
574 |
return false;
|
575 |
}
|
575 |
}
|
576 |
string dic;
|
576 |
string dic;
|
577 |
if (!readDicData(hoffs, d, dic, 0)) {
|
577 |
if (!readDicData(hoffs, d, dic, 0)) {
|
|
... |
|
... |
588 |
return false;
|
588 |
return false;
|
589 |
}
|
589 |
}
|
590 |
return true;
|
590 |
return true;
|
591 |
}
|
591 |
}
|
592 |
|
592 |
|
593 |
bool readDicData(off_t hoffs, EntryHeaderData& hd, string& dic,
|
593 |
bool readDicData(int64_t hoffs, EntryHeaderData& hd, string& dic,
|
594 |
string* data) {
|
594 |
string* data) {
|
595 |
off_t offs = hoffs + CIRCACHE_HEADER_SIZE;
|
595 |
int64_t offs = hoffs + CIRCACHE_HEADER_SIZE;
|
596 |
// This syscall could be avoided in some cases if we saved the offset
|
596 |
// This syscall could be avoided in some cases if we saved the offset
|
597 |
// at each seek. In most cases, we just read the header and we are
|
597 |
// at each seek. In most cases, we just read the header and we are
|
598 |
// at the right position
|
598 |
// at the right position
|
599 |
if (lseek(m_fd, offs, 0) != offs) {
|
599 |
if (lseek(m_fd, offs, 0) != offs) {
|
600 |
m_reason << "CirCache::get: lseek(" << offs << ") failed: " <<
|
600 |
m_reason << "CirCache::get: lseek(" << offs << ") failed: " <<
|
|
... |
|
... |
672 |
// A scan callback which just records the last header offset and
|
672 |
// A scan callback which just records the last header offset and
|
673 |
// padsize seen. This is used with a scan(nofold) to find the last
|
673 |
// padsize seen. This is used with a scan(nofold) to find the last
|
674 |
// physical record in the file
|
674 |
// physical record in the file
|
675 |
class CCScanHookRecord : public CCScanHook {
|
675 |
class CCScanHookRecord : public CCScanHook {
|
676 |
public:
|
676 |
public:
|
677 |
off_t headoffs;
|
677 |
int64_t headoffs;
|
678 |
off_t padsize;
|
678 |
int64_t padsize;
|
679 |
CCScanHookRecord()
|
679 |
CCScanHookRecord()
|
680 |
: headoffs(0), padsize(0) {
|
680 |
: headoffs(0), padsize(0) {
|
681 |
}
|
681 |
}
|
682 |
virtual status takeone(off_t offs, const string& udi,
|
682 |
virtual status takeone(int64_t offs, const string& udi,
|
683 |
const EntryHeaderData& d) {
|
683 |
const EntryHeaderData& d) {
|
684 |
headoffs = offs;
|
684 |
headoffs = offs;
|
685 |
padsize = d.padsize;
|
685 |
padsize = d.padsize;
|
686 |
LOGDEB2("CCScanHookRecord::takeone: offs " << (lltodecstr(headoffs)) << " padsize " << (lltodecstr(padsize)) << "\n" );
|
686 |
LOGDEB2("CCScanHookRecord::takeone: offs " << (lltodecstr(headoffs)) << " padsize " << (lltodecstr(padsize)) << "\n" );
|
687 |
return Continue;
|
687 |
return Continue;
|
|
... |
|
... |
691 |
string CirCache::getpath()
|
691 |
string CirCache::getpath()
|
692 |
{
|
692 |
{
|
693 |
return m_d->datafn(m_dir);
|
693 |
return m_d->datafn(m_dir);
|
694 |
}
|
694 |
}
|
695 |
|
695 |
|
696 |
bool CirCache::create(off_t maxsize, int flags)
|
696 |
bool CirCache::create(int64_t maxsize, int flags)
|
697 |
{
|
697 |
{
|
698 |
LOGDEB("CirCache::create: [" << (m_dir) << "] maxsz " << (lltodecstr((long long)maxsize)) << " flags 0x" << (flags) << "\n" );
|
698 |
LOGDEB("CirCache::create: [" << (m_dir) << "] maxsz " << (lltodecstr((long long)maxsize)) << " flags 0x" << (flags) << "\n" );
|
699 |
if (m_d == 0) {
|
699 |
if (m_d == 0) {
|
700 |
LOGERR("CirCache::create: null data\n" );
|
700 |
LOGERR("CirCache::create: null data\n" );
|
701 |
return false;
|
701 |
return false;
|
|
... |
|
... |
785 |
return m_d->readfirstblock();
|
785 |
return m_d->readfirstblock();
|
786 |
}
|
786 |
}
|
787 |
|
787 |
|
788 |
class CCScanHookDump : public CCScanHook {
|
788 |
class CCScanHookDump : public CCScanHook {
|
789 |
public:
|
789 |
public:
|
790 |
virtual status takeone(off_t offs, const string& udi,
|
790 |
virtual status takeone(int64_t offs, const string& udi,
|
791 |
const EntryHeaderData& d) {
|
791 |
const EntryHeaderData& d) {
|
792 |
cout << "Scan: offs " << offs << " dicsize " << d.dicsize
|
792 |
cout << "Scan: offs " << offs << " dicsize " << d.dicsize
|
793 |
<< " datasize " << d.datasize << " padsize " << d.padsize <<
|
793 |
<< " datasize " << d.datasize << " padsize " << d.padsize <<
|
794 |
" flags " << d.flags <<
|
794 |
" flags " << d.flags <<
|
795 |
" udi [" << udi << "]" << endl;
|
795 |
" udi [" << udi << "]" << endl;
|
|
... |
|
... |
801 |
{
|
801 |
{
|
802 |
CCScanHookDump dumper;
|
802 |
CCScanHookDump dumper;
|
803 |
|
803 |
|
804 |
// Start at oldest header. This is eof while the file is growing, scan will
|
804 |
// Start at oldest header. This is eof while the file is growing, scan will
|
805 |
// fold to bot at once.
|
805 |
// fold to bot at once.
|
806 |
off_t start = m_d->m_oheadoffs;
|
806 |
int64_t start = m_d->m_oheadoffs;
|
807 |
|
807 |
|
808 |
switch (m_d->scan(start, &dumper, true)) {
|
808 |
switch (m_d->scan(start, &dumper, true)) {
|
809 |
case CCScanHook::Stop:
|
809 |
case CCScanHook::Stop:
|
810 |
cout << "Scan returns Stop??" << endl;
|
810 |
cout << "Scan returns Stop??" << endl;
|
811 |
return false;
|
811 |
return false;
|
|
... |
|
... |
828 |
class CCScanHookGetter : public CCScanHook {
|
828 |
class CCScanHookGetter : public CCScanHook {
|
829 |
public:
|
829 |
public:
|
830 |
string m_udi;
|
830 |
string m_udi;
|
831 |
int m_targinstance;
|
831 |
int m_targinstance;
|
832 |
int m_instance;
|
832 |
int m_instance;
|
833 |
off_t m_offs;
|
833 |
int64_t m_offs;
|
834 |
EntryHeaderData m_hd;
|
834 |
EntryHeaderData m_hd;
|
835 |
|
835 |
|
836 |
CCScanHookGetter(const string& udi, int ti)
|
836 |
CCScanHookGetter(const string& udi, int ti)
|
837 |
: m_udi(udi), m_targinstance(ti), m_instance(0), m_offs(0) {}
|
837 |
: m_udi(udi), m_targinstance(ti), m_instance(0), m_offs(0) {}
|
838 |
|
838 |
|
839 |
virtual status takeone(off_t offs, const string& udi,
|
839 |
virtual status takeone(int64_t offs, const string& udi,
|
840 |
const EntryHeaderData& d) {
|
840 |
const EntryHeaderData& d) {
|
841 |
LOGDEB2("Circache:Scan: off " << (long(offs)) << " udi [" << (udi) << "] dcsz " << ((UINT)d.dicsize) << " dtsz " << ((UINT)d.datasize) << " pdsz " << ((UINT)d.padsize) << " flgs " << (d.flags) << "\n" );
|
841 |
LOGDEB2("Circache:Scan: off " << (long(offs)) << " udi [" << (udi) << "] dcsz " << ((UINT)d.dicsize) << " dtsz " << ((UINT)d.datasize) << " pdsz " << ((UINT)d.padsize) << " flgs " << (d.flags) << "\n" );
|
842 |
if (!m_udi.compare(udi)) {
|
842 |
if (!m_udi.compare(udi)) {
|
843 |
m_instance++;
|
843 |
m_instance++;
|
844 |
m_offs = offs;
|
844 |
m_offs = offs;
|
|
... |
|
... |
864 |
|
864 |
|
865 |
// If memory map is up to date, use it:
|
865 |
// If memory map is up to date, use it:
|
866 |
if (m_d->m_ofskhcplt) {
|
866 |
if (m_d->m_ofskhcplt) {
|
867 |
LOGDEB1("CirCache::get: using ofskh\n" );
|
867 |
LOGDEB1("CirCache::get: using ofskh\n" );
|
868 |
//m_d->khDump();
|
868 |
//m_d->khDump();
|
869 |
vector<off_t> ofss;
|
869 |
vector<int64_t> ofss;
|
870 |
if (m_d->khFind(udi, ofss)) {
|
870 |
if (m_d->khFind(udi, ofss)) {
|
871 |
LOGDEB1("Circache::get: h found, colls " << (ofss.size()) << "\n" );
|
871 |
LOGDEB1("Circache::get: h found, colls " << (ofss.size()) << "\n" );
|
872 |
int finst = 1;
|
872 |
int finst = 1;
|
873 |
EntryHeaderData d_good;
|
873 |
EntryHeaderData d_good;
|
874 |
off_t o_good = 0;
|
874 |
int64_t o_good = 0;
|
875 |
for (vector<off_t>::iterator it = ofss.begin();
|
875 |
for (vector<int64_t>::iterator it = ofss.begin();
|
876 |
it != ofss.end(); it++) {
|
876 |
it != ofss.end(); it++) {
|
877 |
LOGDEB1("Circache::get: trying offs " << ((ULONG)*it) << "\n" );
|
877 |
LOGDEB1("Circache::get: trying offs " << ((ULONG)*it) << "\n" );
|
878 |
EntryHeaderData d;
|
878 |
EntryHeaderData d;
|
879 |
string fudi;
|
879 |
string fudi;
|
880 |
if (!m_d->readHUdi(*it, d, fudi)) {
|
880 |
if (!m_d->readHUdi(*it, d, fudi)) {
|
|
... |
|
... |
902 |
// Else try to scan anyway.
|
902 |
// Else try to scan anyway.
|
903 |
}
|
903 |
}
|
904 |
}
|
904 |
}
|
905 |
|
905 |
|
906 |
CCScanHookGetter getter(udi, instance);
|
906 |
CCScanHookGetter getter(udi, instance);
|
907 |
off_t start = m_d->m_oheadoffs;
|
907 |
int64_t start = m_d->m_oheadoffs;
|
908 |
|
908 |
|
909 |
CCScanHook::status ret = m_d->scan(start, &getter, true);
|
909 |
CCScanHook::status ret = m_d->scan(start, &getter, true);
|
910 |
if (ret == CCScanHook::Eof) {
|
910 |
if (ret == CCScanHook::Eof) {
|
911 |
if (getter.m_instance == 0) {
|
911 |
if (getter.m_instance == 0) {
|
912 |
return false;
|
912 |
return false;
|
|
... |
|
... |
942 |
LOGERR("CirCache::erase : cache not updated after get\n" );
|
942 |
LOGERR("CirCache::erase : cache not updated after get\n" );
|
943 |
return false;
|
943 |
return false;
|
944 |
}
|
944 |
}
|
945 |
}
|
945 |
}
|
946 |
|
946 |
|
947 |
vector<off_t> ofss;
|
947 |
vector<int64_t> ofss;
|
948 |
if (!m_d->khFind(udi, ofss)) {
|
948 |
if (!m_d->khFind(udi, ofss)) {
|
949 |
// Udi not in there, erase ok
|
949 |
// Udi not in there, erase ok
|
950 |
LOGDEB("CirCache::erase: khFind returns none\n" );
|
950 |
LOGDEB("CirCache::erase: khFind returns none\n" );
|
951 |
return true;
|
951 |
return true;
|
952 |
}
|
952 |
}
|
953 |
|
953 |
|
954 |
for (vector<off_t>::iterator it = ofss.begin(); it != ofss.end(); it++) {
|
954 |
for (vector<int64_t>::iterator it = ofss.begin(); it != ofss.end(); it++) {
|
955 |
LOGDEB2("CirCache::erase: reading at " << ((unsigned long)*it) << "\n" );
|
955 |
LOGDEB2("CirCache::erase: reading at " << ((unsigned long)*it) << "\n" );
|
956 |
EntryHeaderData d;
|
956 |
EntryHeaderData d;
|
957 |
string fudi;
|
957 |
string fudi;
|
958 |
if (!m_d->readHUdi(*it, d, fudi)) {
|
958 |
if (!m_d->readHUdi(*it, d, fudi)) {
|
959 |
return false;
|
959 |
return false;
|
|
... |
|
... |
978 |
|
978 |
|
979 |
// Used to scan the file ahead until we accumulated enough space for the new
|
979 |
// Used to scan the file ahead until we accumulated enough space for the new
|
980 |
// entry.
|
980 |
// entry.
|
981 |
class CCScanHookSpacer : public CCScanHook {
|
981 |
class CCScanHookSpacer : public CCScanHook {
|
982 |
public:
|
982 |
public:
|
983 |
off_t sizewanted;
|
983 |
int64_t sizewanted;
|
984 |
off_t sizeseen;
|
984 |
int64_t sizeseen;
|
985 |
vector<pair<string, off_t> > squashed_udis;
|
985 |
vector<pair<string, int64_t> > squashed_udis;
|
986 |
CCScanHookSpacer(off_t sz)
|
986 |
CCScanHookSpacer(int64_t sz)
|
987 |
: sizewanted(sz), sizeseen(0) {
|
987 |
: sizewanted(sz), sizeseen(0) {
|
988 |
assert(sz > 0);
|
988 |
assert(sz > 0);
|
989 |
}
|
989 |
}
|
990 |
|
990 |
|
991 |
virtual status takeone(off_t offs, const string& udi,
|
991 |
virtual status takeone(int64_t offs, const string& udi,
|
992 |
const EntryHeaderData& d) {
|
992 |
const EntryHeaderData& d) {
|
993 |
LOGDEB2("Circache:ScanSpacer:off " << ((UINT)offs) << " dcsz " << (d.dicsize) << " dtsz " << (d.datasize) << " pdsz " << (d.padsize) << " udi[" << (udi) << "]\n" );
|
993 |
LOGDEB2("Circache:ScanSpacer:off " << ((UINT)offs) << " dcsz " << (d.dicsize) << " dtsz " << (d.datasize) << " pdsz " << (d.padsize) << " udi[" << (udi) << "]\n" );
|
994 |
sizeseen += CIRCACHE_HEADER_SIZE + d.dicsize + d.datasize + d.padsize;
|
994 |
sizeseen += CIRCACHE_HEADER_SIZE + d.dicsize + d.datasize + d.padsize;
|
995 |
squashed_udis.push_back(make_pair(udi, offs));
|
995 |
squashed_udis.push_back(make_pair(udi, offs));
|
996 |
if (sizeseen >= sizewanted) {
|
996 |
if (sizeseen >= sizewanted) {
|
|
... |
|
... |
1056 |
m_d->m_reason << "CirCache::put: fstat failed. errno " << errno;
|
1056 |
m_d->m_reason << "CirCache::put: fstat failed. errno " << errno;
|
1057 |
return false;
|
1057 |
return false;
|
1058 |
}
|
1058 |
}
|
1059 |
|
1059 |
|
1060 |
// Characteristics for the new entry.
|
1060 |
// Characteristics for the new entry.
|
1061 |
off_t nsize = CIRCACHE_HEADER_SIZE + dic.size() + datalen;
|
1061 |
int64_t nsize = CIRCACHE_HEADER_SIZE + dic.size() + datalen;
|
1062 |
off_t nwriteoffs = m_d->m_oheadoffs;
|
1062 |
int64_t nwriteoffs = m_d->m_oheadoffs;
|
1063 |
off_t npadsize = 0;
|
1063 |
int64_t npadsize = 0;
|
1064 |
bool extending = false;
|
1064 |
bool extending = false;
|
1065 |
|
1065 |
|
1066 |
LOGDEB("CirCache::put: nsz " << (nsize) << " oheadoffs " << (m_d->m_oheadoffs) << "\n" );
|
1066 |
LOGDEB("CirCache::put: nsz " << (nsize) << " oheadoffs " << (m_d->m_oheadoffs) << "\n" );
|
1067 |
|
1067 |
|
1068 |
// Check if we can recover some pad space from the (physically) previous
|
1068 |
// Check if we can recover some pad space from the (physically) previous
|
1069 |
// entry.
|
1069 |
// entry.
|
1070 |
off_t recovpadsize = m_d->m_oheadoffs == CIRCACHE_FIRSTBLOCK_SIZE ?
|
1070 |
int64_t recovpadsize = m_d->m_oheadoffs == CIRCACHE_FIRSTBLOCK_SIZE ?
|
1071 |
0 : m_d->m_npadsize;
|
1071 |
0 : m_d->m_npadsize;
|
1072 |
if (recovpadsize != 0) {
|
1072 |
if (recovpadsize != 0) {
|
1073 |
// Need to read the latest entry's header, to rewrite it with a
|
1073 |
// Need to read the latest entry's header, to rewrite it with a
|
1074 |
// zero pad size
|
1074 |
// zero pad size
|
1075 |
EntryHeaderData pd;
|
1075 |
EntryHeaderData pd;
|
|
... |
|
... |
1105 |
npadsize = 0;
|
1105 |
npadsize = 0;
|
1106 |
extending = true;
|
1106 |
extending = true;
|
1107 |
} else {
|
1107 |
} else {
|
1108 |
// Scan the file until we have enough space for the new entry,
|
1108 |
// Scan the file until we have enough space for the new entry,
|
1109 |
// and determine the pad size up to the 1st preserved entry
|
1109 |
// and determine the pad size up to the 1st preserved entry
|
1110 |
off_t scansize = nsize - recovpadsize;
|
1110 |
int64_t scansize = nsize - recovpadsize;
|
1111 |
LOGDEB("CirCache::put: scanning for size " << (scansize) << " from offs " << ((UINT)m_d->m_oheadoffs) << "\n" );
|
1111 |
LOGDEB("CirCache::put: scanning for size " << (scansize) << " from offs " << ((UINT)m_d->m_oheadoffs) << "\n" );
|
1112 |
CCScanHookSpacer spacer(scansize);
|
1112 |
CCScanHookSpacer spacer(scansize);
|
1113 |
switch (m_d->scan(m_d->m_oheadoffs, &spacer)) {
|
1113 |
switch (m_d->scan(m_d->m_oheadoffs, &spacer)) {
|
1114 |
case CCScanHook::Stop:
|
1114 |
case CCScanHook::Stop:
|
1115 |
LOGDEB("CirCache::put: Scan ok, sizeseen " << (spacer.sizeseen) << "\n" );
|
1115 |
LOGDEB("CirCache::put: Scan ok, sizeseen " << (spacer.sizeseen) << "\n" );
|
|
... |
|
... |
1175 |
return false;
|
1175 |
return false;
|
1176 |
}
|
1176 |
}
|
1177 |
|
1177 |
|
1178 |
eof = false;
|
1178 |
eof = false;
|
1179 |
|
1179 |
|
1180 |
off_t fsize = lseek(m_d->m_fd, 0, SEEK_END);
|
1180 |
int64_t fsize = lseek(m_d->m_fd, 0, SEEK_END);
|
1181 |
if (fsize == (off_t) - 1) {
|
1181 |
if (fsize == (int64_t) - 1) {
|
1182 |
LOGERR("CirCache::rewind: seek to EOF failed\n" );
|
1182 |
LOGERR("CirCache::rewind: seek to EOF failed\n" );
|
1183 |
return false;
|
1183 |
return false;
|
1184 |
}
|
1184 |
}
|
1185 |
// Read oldest header. This is either at the position pointed to
|
1185 |
// Read oldest header. This is either at the position pointed to
|
1186 |
// by oheadoffs, or after the first block if the file is still
|
1186 |
// by oheadoffs, or after the first block if the file is still
|
|
... |
|
... |
1562 |
|
1562 |
|
1563 |
if (op_flags & OPT_c) {
|
1563 |
if (op_flags & OPT_c) {
|
1564 |
if (argc != 1) {
|
1564 |
if (argc != 1) {
|
1565 |
Usage();
|
1565 |
Usage();
|
1566 |
}
|
1566 |
}
|
1567 |
off_t sizekb = atoi(*argv++);
|
1567 |
int64_t sizekb = atoi(*argv++);
|
1568 |
argc--;
|
1568 |
argc--;
|
1569 |
int flags = 0;
|
1569 |
int flags = 0;
|
1570 |
if (op_flags & OPT_u) {
|
1570 |
if (op_flags & OPT_u) {
|
1571 |
flags |= CirCache::CC_CRUNIQUE;
|
1571 |
flags |= CirCache::CC_CRUNIQUE;
|
1572 |
}
|
1572 |
}
|