|
a/src/utils/circache.cpp |
|
b/src/utils/circache.cpp |
|
... |
|
... |
154 |
public:
|
154 |
public:
|
155 |
int m_fd;
|
155 |
int m_fd;
|
156 |
////// These are cache persistent state and written to the first block:
|
156 |
////// These are cache persistent state and written to the first block:
|
157 |
// Maximum file size, after which we begin reusing old space
|
157 |
// Maximum file size, after which we begin reusing old space
|
158 |
off_t m_maxsize;
|
158 |
off_t m_maxsize;
|
159 |
// Offset of the oldest header.
|
159 |
// Offset of the oldest header, or max file offset (file size)
|
|
|
160 |
// while the file is growing. This is the next write position.
|
160 |
off_t m_oheadoffs;
|
161 |
off_t m_oheadoffs;
|
161 |
// Offset of last write (newest header)
|
162 |
// Offset of last write (newest header)
|
162 |
off_t m_nheadoffs;
|
163 |
off_t m_nheadoffs;
|
163 |
// Pad size for newest entry.
|
164 |
// Pad size for newest entry.
|
164 |
int m_npadsize;
|
165 |
int m_npadsize;
|
|
... |
|
... |
186 |
bool khEnter(const string& udi, off_t ofs)
|
187 |
bool khEnter(const string& udi, off_t ofs)
|
187 |
{
|
188 |
{
|
188 |
UdiH h(udi);
|
189 |
UdiH h(udi);
|
189 |
|
190 |
|
190 |
LOGDEB2(("Circache::khEnter: h %s offs %lu udi [%s]\n",
|
191 |
LOGDEB2(("Circache::khEnter: h %s offs %lu udi [%s]\n",
|
191 |
h.asHexString().c_str(), (ULONG)ofs, udi.c_str()));
|
192 |
h.asHexString().c_str(), (ULONG)ofs, udi.c_str()));
|
192 |
|
193 |
|
193 |
pair<kh_type::iterator, kh_type::iterator> p = m_ofskh.equal_range(h);
|
194 |
pair<kh_type::iterator, kh_type::iterator> p = m_ofskh.equal_range(h);
|
194 |
|
195 |
|
195 |
if (p.first != m_ofskh.end() && p.first->first == h) {
|
196 |
if (p.first != m_ofskh.end() && p.first->first == h) {
|
196 |
for (kh_type::iterator it = p.first; it != p.second; it++) {
|
197 |
for (kh_type::iterator it = p.first; it != p.second; it++) {
|
197 |
LOGDEB2(("Circache::khEnter: col h %s, ofs %lu\n",
|
198 |
LOGDEB2(("Circache::khEnter: col h %s, ofs %lu\n",
|
198 |
it->first.asHexString().c_str(),
|
199 |
it->first.asHexString().c_str(),
|
199 |
(ULONG)it->second));
|
200 |
(ULONG)it->second));
|
200 |
if (it->second == ofs) {
|
201 |
if (it->second == ofs) {
|
201 |
// (h,offs) already there. Happens
|
202 |
// (h,offs) already there. Happens
|
202 |
LOGDEB2(("Circache::khEnter: already there\n"));
|
203 |
LOGDEB2(("Circache::khEnter: already there\n"));
|
203 |
return true;
|
204 |
return true;
|
204 |
}
|
205 |
}
|
|
... |
|
... |
225 |
ofss.clear();
|
226 |
ofss.clear();
|
226 |
|
227 |
|
227 |
UdiH h(udi);
|
228 |
UdiH h(udi);
|
228 |
|
229 |
|
229 |
LOGDEB2(("Circache::khFind: h %s udi [%s]\n",
|
230 |
LOGDEB2(("Circache::khFind: h %s udi [%s]\n",
|
230 |
h.asHexString().c_str(), udi.c_str()));
|
231 |
h.asHexString().c_str(), udi.c_str()));
|
231 |
|
232 |
|
232 |
pair<kh_type::iterator, kh_type::iterator> p = m_ofskh.equal_range(h);
|
233 |
pair<kh_type::iterator, kh_type::iterator> p = m_ofskh.equal_range(h);
|
233 |
|
234 |
|
234 |
#if 0
|
235 |
#if 0
|
235 |
if (p.first == m_ofskh.end()) LOGDEB(("KHFIND: FIRST END()\n"));
|
236 |
if (p.first == m_ofskh.end()) LOGDEB(("KHFIND: FIRST END()\n"));
|
|
... |
|
... |
316 |
return path_cat(d, "circache.crch");
|
317 |
return path_cat(d, "circache.crch");
|
317 |
}
|
318 |
}
|
318 |
|
319 |
|
319 |
bool writefirstblock()
|
320 |
bool writefirstblock()
|
320 |
{
|
321 |
{
|
321 |
if (m_fd < 0) {
|
322 |
if (m_fd < 0) {
|
322 |
m_reason << "writefirstblock: not open ";
|
323 |
m_reason << "writefirstblock: not open ";
|
323 |
return false;
|
324 |
return false;
|
324 |
}
|
325 |
}
|
325 |
|
326 |
|
326 |
ostringstream s;
|
327 |
ostringstream s;
|
327 |
s <<
|
328 |
s <<
|
328 |
"maxsize = " << m_maxsize << "\n" <<
|
329 |
"maxsize = " << m_maxsize << "\n" <<
|
329 |
"oheadoffs = " << m_oheadoffs << "\n" <<
|
330 |
"oheadoffs = " << m_oheadoffs << "\n" <<
|
|
... |
|
... |
345 |
return true;
|
346 |
return true;
|
346 |
}
|
347 |
}
|
347 |
|
348 |
|
348 |
bool readfirstblock()
|
349 |
bool readfirstblock()
|
349 |
{
|
350 |
{
|
350 |
if (m_fd < 0) {
|
351 |
if (m_fd < 0) {
|
351 |
m_reason << "readfirstblock: not open ";
|
352 |
m_reason << "readfirstblock: not open ";
|
352 |
return false;
|
353 |
return false;
|
353 |
}
|
354 |
}
|
354 |
|
355 |
|
355 |
char bf[CIRCACHE_FIRSTBLOCK_SIZE];
|
356 |
char bf[CIRCACHE_FIRSTBLOCK_SIZE];
|
356 |
|
357 |
|
357 |
lseek(m_fd, 0, 0);
|
358 |
lseek(m_fd, 0, 0);
|
358 |
if (read(m_fd, bf, CIRCACHE_FIRSTBLOCK_SIZE) !=
|
359 |
if (read(m_fd, bf, CIRCACHE_FIRSTBLOCK_SIZE) !=
|
|
... |
|
... |
391 |
return true;
|
392 |
return true;
|
392 |
}
|
393 |
}
|
393 |
|
394 |
|
394 |
bool writeEntryHeader(off_t offset, const EntryHeaderData& d)
|
395 |
bool writeEntryHeader(off_t offset, const EntryHeaderData& d)
|
395 |
{
|
396 |
{
|
396 |
if (m_fd < 0) {
|
397 |
if (m_fd < 0) {
|
397 |
m_reason << "writeEntryHeader: not open ";
|
398 |
m_reason << "writeEntryHeader: not open ";
|
398 |
return false;
|
399 |
return false;
|
399 |
}
|
400 |
}
|
400 |
char bf[CIRCACHE_HEADER_SIZE];
|
401 |
char bf[CIRCACHE_HEADER_SIZE];
|
401 |
memset(bf, 0, CIRCACHE_HEADER_SIZE);
|
402 |
memset(bf, 0, CIRCACHE_HEADER_SIZE);
|
402 |
snprintf(bf, CIRCACHE_HEADER_SIZE,
|
403 |
snprintf(bf, CIRCACHE_HEADER_SIZE,
|
403 |
headerformat, d.dicsize, d.datasize, d.padsize, d.flags);
|
404 |
headerformat, d.dicsize, d.datasize, d.padsize, d.flags);
|
404 |
if (lseek(m_fd, offset, 0) != offset) {
|
405 |
if (lseek(m_fd, offset, 0) != offset) {
|
405 |
m_reason << "CirCache::weh: lseek(" << offset <<
|
406 |
m_reason << "CirCache::weh: lseek(" << offset <<
|
406 |
") failed: errno " << errno;
|
407 |
") failed: errno " << errno;
|
407 |
return false;
|
408 |
return false;
|
408 |
}
|
409 |
}
|
|
... |
|
... |
413 |
return true;
|
414 |
return true;
|
414 |
}
|
415 |
}
|
415 |
|
416 |
|
416 |
CCScanHook::status readEntryHeader(off_t offset, EntryHeaderData& d)
|
417 |
CCScanHook::status readEntryHeader(off_t offset, EntryHeaderData& d)
|
417 |
{
|
418 |
{
|
418 |
if (m_fd < 0) {
|
419 |
if (m_fd < 0) {
|
419 |
m_reason << "readEntryHeader: not open ";
|
420 |
m_reason << "readEntryHeader: not open ";
|
420 |
return CCScanHook::Error;
|
421 |
return CCScanHook::Error;
|
421 |
}
|
422 |
}
|
422 |
|
423 |
|
423 |
if (lseek(m_fd, offset, 0) != offset) {
|
424 |
if (lseek(m_fd, offset, 0) != offset) {
|
424 |
m_reason << "readEntryHeader: lseek(" << offset <<
|
425 |
m_reason << "readEntryHeader: lseek(" << offset <<
|
425 |
") failed: errno " << errno;
|
426 |
") failed: errno " << errno;
|
426 |
return CCScanHook::Error;
|
427 |
return CCScanHook::Error;
|
|
... |
|
... |
449 |
}
|
450 |
}
|
450 |
|
451 |
|
451 |
CCScanHook::status scan(off_t startoffset, CCScanHook *user,
|
452 |
CCScanHook::status scan(off_t startoffset, CCScanHook *user,
|
452 |
bool fold = false)
|
453 |
bool fold = false)
|
453 |
{
|
454 |
{
|
454 |
if (m_fd < 0) {
|
455 |
if (m_fd < 0) {
|
455 |
m_reason << "scan: not open ";
|
456 |
m_reason << "scan: not open ";
|
456 |
return CCScanHook::Error;
|
457 |
return CCScanHook::Error;
|
457 |
}
|
458 |
}
|
458 |
|
459 |
|
459 |
off_t so0 = startoffset;
|
460 |
off_t so0 = startoffset;
|
460 |
bool already_folded = false;
|
461 |
bool already_folded = false;
|
461 |
|
462 |
|
462 |
while (true) {
|
463 |
while (true) {
|
|
... |
|
... |
620 |
class CCScanHookRecord : public CCScanHook {
|
621 |
class CCScanHookRecord : public CCScanHook {
|
621 |
public:
|
622 |
public:
|
622 |
off_t headoffs;
|
623 |
off_t headoffs;
|
623 |
off_t padsize;
|
624 |
off_t padsize;
|
624 |
CCScanHookRecord()
|
625 |
CCScanHookRecord()
|
625 |
: headoffs(0), padsize(0)
|
626 |
: headoffs(0), padsize(0)
|
626 |
{
|
627 |
{
|
627 |
}
|
628 |
}
|
628 |
virtual status takeone(off_t offs, const string& udi,
|
629 |
virtual status takeone(off_t offs, const string& udi,
|
629 |
const EntryHeaderData& d)
|
630 |
const EntryHeaderData& d)
|
630 |
{
|
631 |
{
|
631 |
headoffs = offs;
|
632 |
headoffs = offs;
|
632 |
padsize = d.padsize;
|
633 |
padsize = d.padsize;
|
633 |
LOGDEB2(("CCScanHookRecord::takeone: offs %lld padsize %lld\n",
|
634 |
LOGDEB2(("CCScanHookRecord::takeone: offs %lld padsize %lld\n",
|
634 |
headoffs, padsize));
|
635 |
headoffs, padsize));
|
635 |
return Continue;
|
636 |
return Continue;
|
636 |
}
|
637 |
}
|
637 |
};
|
638 |
};
|
638 |
|
639 |
|
639 |
string CirCache::getpath()
|
640 |
string CirCache::getpath()
|
|
... |
|
... |
642 |
}
|
643 |
}
|
643 |
|
644 |
|
644 |
bool CirCache::create(off_t maxsize, int flags)
|
645 |
bool CirCache::create(off_t maxsize, int flags)
|
645 |
{
|
646 |
{
|
646 |
LOGDEB(("CirCache::create: [%s] maxsz %lld flags 0x%x\n",
|
647 |
LOGDEB(("CirCache::create: [%s] maxsz %lld flags 0x%x\n",
|
647 |
m_dir.c_str(), maxsize, flags));
|
648 |
m_dir.c_str(), maxsize, flags));
|
648 |
if (m_d == 0) {
|
649 |
if (m_d == 0) {
|
649 |
LOGERR(("CirCache::create: null data\n"));
|
650 |
LOGERR(("CirCache::create: null data\n"));
|
650 |
return false;
|
651 |
return false;
|
651 |
}
|
652 |
}
|
652 |
|
653 |
|
653 |
struct stat st;
|
654 |
struct stat st;
|
654 |
if (stat(m_dir.c_str(), &st) < 0) {
|
655 |
if (stat(m_dir.c_str(), &st) < 0) {
|
655 |
// Directory does not exist, create it
|
656 |
// Directory does not exist, create it
|
656 |
if (mkdir(m_dir.c_str(), 0777) < 0) {
|
657 |
if (mkdir(m_dir.c_str(), 0777) < 0) {
|
657 |
m_d->m_reason << "CirCache::create: mkdir(" << m_dir <<
|
658 |
m_d->m_reason << "CirCache::create: mkdir(" << m_dir <<
|
658 |
") failed" << " errno " << errno;
|
659 |
") failed" << " errno " << errno;
|
659 |
return false;
|
660 |
return false;
|
660 |
}
|
661 |
}
|
661 |
} else {
|
662 |
} else {
|
662 |
// If the file exists too, and truncate is not set, switch
|
663 |
// If the file exists too, and truncate is not set, switch
|
663 |
// to open-mode. Still may need to update header params.
|
664 |
// to open-mode. Still may need to update header params.
|
664 |
if (access(m_d->datafn(m_dir).c_str(), 0) >= 0 &&
|
665 |
if (access(m_d->datafn(m_dir).c_str(), 0) >= 0 &&
|
665 |
!(flags & CC_CRTRUNCATE)) {
|
666 |
!(flags & CC_CRTRUNCATE)) {
|
666 |
if (!open(CC_OPWRITE)) {
|
667 |
if (!open(CC_OPWRITE)) {
|
667 |
return false;
|
668 |
return false;
|
668 |
}
|
669 |
}
|
669 |
if (maxsize == m_d->m_maxsize &&
|
670 |
if (maxsize == m_d->m_maxsize &&
|
670 |
((flags & CC_CRUNIQUE) != 0) == m_d->m_uniquentries) {
|
671 |
((flags & CC_CRUNIQUE) != 0) == m_d->m_uniquentries) {
|
671 |
LOGDEB(("Header unchanged, no rewrite\n"));
|
672 |
LOGDEB(("Header unchanged, no rewrite\n"));
|
672 |
return true;
|
673 |
return true;
|
673 |
}
|
674 |
}
|
674 |
// If the new maxsize is bigger than current size, we need
|
675 |
// If the new maxsize is bigger than current size, we need
|
675 |
// to stop recycling if this is what we are doing.
|
676 |
// to stop recycling if this is what we are doing.
|
676 |
if (maxsize > m_d->m_maxsize && maxsize > st.st_size) {
|
677 |
if (maxsize > m_d->m_maxsize && maxsize > st.st_size) {
|
677 |
// Scan the file to find the last physical record. The
|
678 |
// Scan the file to find the last physical record. The
|
678 |
// ohead is set at physical eof, and nhead is the last
|
679 |
// ohead is set at physical eof, and nhead is the last
|
679 |
// scanned record
|
680 |
// scanned record
|
680 |
CCScanHookRecord rec;
|
681 |
CCScanHookRecord rec;
|
681 |
m_d->scan(CIRCACHE_FIRSTBLOCK_SIZE, &rec, false);
|
682 |
m_d->scan(CIRCACHE_FIRSTBLOCK_SIZE, &rec, false);
|
682 |
m_d->m_oheadoffs = lseek(m_d->m_fd, 0, SEEK_END);
|
683 |
m_d->m_oheadoffs = lseek(m_d->m_fd, 0, SEEK_END);
|
683 |
m_d->m_nheadoffs = rec.headoffs;
|
684 |
m_d->m_nheadoffs = rec.headoffs;
|
684 |
m_d->m_npadsize = rec.padsize;
|
685 |
m_d->m_npadsize = rec.padsize;
|
685 |
}
|
686 |
}
|
686 |
m_d->m_maxsize = maxsize;
|
687 |
m_d->m_maxsize = maxsize;
|
687 |
m_d->m_uniquentries = ((flags & CC_CRUNIQUE) != 0);
|
688 |
m_d->m_uniquentries = ((flags & CC_CRUNIQUE) != 0);
|
688 |
LOGDEB(("CirCache::create: rewriting header with "
|
689 |
LOGDEB(("CirCache::create: rewriting header with "
|
689 |
"maxsize %lld oheadoffs %lld nheadoffs %lld "
|
690 |
"maxsize %lld oheadoffs %lld nheadoffs %lld "
|
690 |
"npadsize %d unient %d\n",
|
691 |
"npadsize %d unient %d\n",
|
691 |
m_d->m_maxsize, m_d->m_oheadoffs, m_d->m_nheadoffs,
|
692 |
m_d->m_maxsize, m_d->m_oheadoffs, m_d->m_nheadoffs,
|
692 |
m_d->m_npadsize, int(m_d->m_uniquentries)));
|
693 |
m_d->m_npadsize, int(m_d->m_uniquentries)));
|
693 |
return m_d->writefirstblock();
|
694 |
return m_d->writefirstblock();
|
694 |
}
|
695 |
}
|
695 |
// Else fallthrough to create file
|
696 |
// Else fallthrough to create file
|
696 |
}
|
697 |
}
|
697 |
|
698 |
|
698 |
if ((m_d->m_fd = ::open(m_d->datafn(m_dir).c_str(),
|
699 |
if ((m_d->m_fd = ::open(m_d->datafn(m_dir).c_str(),
|
699 |
O_CREAT | O_RDWR | O_TRUNC, 0666)) < 0) {
|
700 |
O_CREAT | O_RDWR | O_TRUNC, 0666)) < 0) {
|
700 |
m_d->m_reason << "CirCache::create: open/creat(" <<
|
701 |
m_d->m_reason << "CirCache::create: open/creat(" <<
|
701 |
m_d->datafn(m_dir) << ") failed " << "errno " << errno;
|
702 |
m_d->datafn(m_dir) << ") failed " << "errno " << errno;
|
702 |
return false;
|
703 |
return false;
|
703 |
}
|
704 |
}
|
704 |
|
705 |
|
705 |
m_d->m_maxsize = maxsize;
|
706 |
m_d->m_maxsize = maxsize;
|
706 |
m_d->m_oheadoffs = CIRCACHE_FIRSTBLOCK_SIZE;
|
707 |
m_d->m_oheadoffs = CIRCACHE_FIRSTBLOCK_SIZE;
|
707 |
m_d->m_uniquentries = ((flags & CC_CRUNIQUE) != 0);
|
708 |
m_d->m_uniquentries = ((flags & CC_CRUNIQUE) != 0);
|
|
... |
|
... |
718 |
}
|
719 |
}
|
719 |
|
720 |
|
720 |
bool CirCache::open(OpMode mode)
|
721 |
bool CirCache::open(OpMode mode)
|
721 |
{
|
722 |
{
|
722 |
if (m_d == 0) {
|
723 |
if (m_d == 0) {
|
723 |
LOGERR(("CirCache::open: null data\n"));
|
724 |
LOGERR(("CirCache::open: null data\n"));
|
724 |
return false;
|
725 |
return false;
|
725 |
}
|
726 |
}
|
726 |
|
727 |
|
727 |
if (m_d->m_fd >= 0)
|
728 |
if (m_d->m_fd >= 0)
|
728 |
::close(m_d->m_fd);
|
729 |
::close(m_d->m_fd);
|
729 |
|
730 |
|
730 |
if ((m_d->m_fd = ::open(m_d->datafn(m_dir).c_str(),
|
731 |
if ((m_d->m_fd = ::open(m_d->datafn(m_dir).c_str(),
|
731 |
mode == CC_OPREAD ? O_RDONLY : O_RDWR)) < 0) {
|
732 |
mode == CC_OPREAD ? O_RDONLY : O_RDWR)) < 0) {
|
732 |
m_d->m_reason << "CirCache::open: open(" << m_d->datafn(m_dir) <<
|
733 |
m_d->m_reason << "CirCache::open: open(" << m_d->datafn(m_dir) <<
|
733 |
") failed " << "errno " << errno;
|
734 |
") failed " << "errno " << errno;
|
734 |
return false;
|
735 |
return false;
|
735 |
}
|
736 |
}
|
736 |
return m_d->readfirstblock();
|
737 |
return m_d->readfirstblock();
|
|
... |
|
... |
935 |
public:
|
936 |
public:
|
936 |
UINT sizewanted;
|
937 |
UINT sizewanted;
|
937 |
UINT sizeseen;
|
938 |
UINT sizeseen;
|
938 |
vector<pair<string, off_t> > squashed_udis;
|
939 |
vector<pair<string, off_t> > squashed_udis;
|
939 |
CCScanHookSpacer(int sz)
|
940 |
CCScanHookSpacer(int sz)
|
940 |
: sizewanted(sz), sizeseen(0) {assert(sz > 0);}
|
941 |
: sizewanted(sz), sizeseen(0) {assert(sz > 0);}
|
941 |
|
942 |
|
942 |
virtual status takeone(off_t offs, const string& udi,
|
943 |
virtual status takeone(off_t offs, const string& udi,
|
943 |
const EntryHeaderData& d)
|
944 |
const EntryHeaderData& d)
|
944 |
{
|
945 |
{
|
945 |
LOGDEB2(("Circache:ScanSpacer:off %u dcsz %u dtsz %u pdsz %u udi[%s]\n",
|
946 |
LOGDEB2(("Circache:ScanSpacer:off %u dcsz %u dtsz %u pdsz %u udi[%s]\n",
|
946 |
(UINT)offs, d.dicsize, d.datasize, d.padsize, udi.c_str()));
|
947 |
(UINT)offs, d.dicsize, d.datasize, d.padsize, udi.c_str()));
|
947 |
sizeseen += CIRCACHE_HEADER_SIZE + d.dicsize + d.datasize + d.padsize;
|
948 |
sizeseen += CIRCACHE_HEADER_SIZE + d.dicsize + d.datasize + d.padsize;
|
948 |
squashed_udis.push_back(make_pair(udi, offs));
|
949 |
squashed_udis.push_back(make_pair(udi, offs));
|
949 |
if (sizeseen >= sizewanted)
|
950 |
if (sizeseen >= sizewanted)
|
950 |
return Stop;
|
951 |
return Stop;
|
951 |
return Continue;
|
952 |
return Continue;
|
|
... |
|
... |
1027 |
// zero pad size
|
1028 |
// zero pad size
|
1028 |
EntryHeaderData pd;
|
1029 |
EntryHeaderData pd;
|
1029 |
if (m_d->readEntryHeader(m_d->m_nheadoffs, pd) != CCScanHook::Continue){
|
1030 |
if (m_d->readEntryHeader(m_d->m_nheadoffs, pd) != CCScanHook::Continue){
|
1030 |
return false;
|
1031 |
return false;
|
1031 |
}
|
1032 |
}
|
1032 |
if (int(pd.padsize) != m_d->m_npadsize) {
|
1033 |
if (int(pd.padsize) != m_d->m_npadsize) {
|
1033 |
m_d->m_reason << "CirCache::put: logic error: bad padsize ";
|
1034 |
m_d->m_reason << "CirCache::put: logic error: bad padsize ";
|
1034 |
return false;
|
1035 |
return false;
|
1035 |
}
|
1036 |
}
|
1036 |
if (pd.dicsize == 0) {
|
1037 |
if (pd.dicsize == 0) {
|
1037 |
// erased entry. Also recover the header space, no need to rewrite
|
1038 |
// erased entry. Also recover the header space, no need to rewrite
|
1038 |
// the header, we're going to write on it.
|
1039 |
// the header, we're going to write on it.
|
1039 |
recovpadsize += CIRCACHE_HEADER_SIZE;
|
1040 |
recovpadsize += CIRCACHE_HEADER_SIZE;
|
1040 |
} else {
|
1041 |
} else {
|
|
... |
|
... |
1090 |
}
|
1091 |
}
|
1091 |
|
1092 |
|
1092 |
char head[CIRCACHE_HEADER_SIZE];
|
1093 |
char head[CIRCACHE_HEADER_SIZE];
|
1093 |
memset(head, 0, CIRCACHE_HEADER_SIZE);
|
1094 |
memset(head, 0, CIRCACHE_HEADER_SIZE);
|
1094 |
snprintf(head, CIRCACHE_HEADER_SIZE,
|
1095 |
snprintf(head, CIRCACHE_HEADER_SIZE,
|
1095 |
headerformat, dic.size(), datalen, npadsize, flags);
|
1096 |
headerformat, dic.size(), datalen, npadsize, flags);
|
1096 |
struct iovec vecs[3];
|
1097 |
struct iovec vecs[3];
|
1097 |
vecs[0].iov_base = head;
|
1098 |
vecs[0].iov_base = head;
|
1098 |
vecs[0].iov_len = CIRCACHE_HEADER_SIZE;
|
1099 |
vecs[0].iov_len = CIRCACHE_HEADER_SIZE;
|
1099 |
vecs[1].iov_base = (void *)dic.c_str();
|
1100 |
vecs[1].iov_base = (void *)dic.c_str();
|
1100 |
vecs[1].iov_len = dic.size();
|
1101 |
vecs[1].iov_len = dic.size();
|
|
... |
|
... |
1130 |
return false;
|
1131 |
return false;
|
1131 |
}
|
1132 |
}
|
1132 |
|
1133 |
|
1133 |
eof = false;
|
1134 |
eof = false;
|
1134 |
|
1135 |
|
1135 |
// Read oldest header
|
1136 |
off_t fsize = lseek(m_d->m_fd, 0, SEEK_END);
|
|
|
1137 |
if (fsize == (off_t)-1) {
|
|
|
1138 |
LOGERR(("CirCache::rewind: seek to EOF failed\n"));
|
|
|
1139 |
return false;
|
|
|
1140 |
}
|
|
|
1141 |
// Read oldest header. This is either at the position pointed to
|
|
|
1142 |
// by oheadoffs, or after the first block if the file is still
|
|
|
1143 |
// growing.
|
|
|
1144 |
if (m_d->m_oheadoffs == fsize) {
|
|
|
1145 |
m_d->m_itoffs = CIRCACHE_FIRSTBLOCK_SIZE;
|
|
|
1146 |
} else {
|
1136 |
m_d->m_itoffs = m_d->m_oheadoffs;
|
1147 |
m_d->m_itoffs = m_d->m_oheadoffs;
|
|
|
1148 |
}
|
1137 |
CCScanHook::status st = m_d->readEntryHeader(m_d->m_itoffs, m_d->m_ithd);
|
1149 |
CCScanHook::status st = m_d->readEntryHeader(m_d->m_itoffs, m_d->m_ithd);
|
1138 |
|
1150 |
|
1139 |
switch(st) {
|
1151 |
switch(st) {
|
1140 |
case CCScanHook::Eof:
|
1152 |
case CCScanHook::Eof:
|
1141 |
eof = true;
|
1153 |
eof = true;
|
|
... |
|
... |
1260 |
LOGDEB2(("InflateToDynBuf: avail_in %d total_in %d avail_out %d "
|
1272 |
LOGDEB2(("InflateToDynBuf: avail_in %d total_in %d avail_out %d "
|
1261 |
"total_out %d\n", d_stream.avail_in, d_stream.total_in,
|
1273 |
"total_out %d\n", d_stream.avail_in, d_stream.total_in,
|
1262 |
d_stream.avail_out, d_stream.total_out));
|
1274 |
d_stream.avail_out, d_stream.total_out));
|
1263 |
if (d_stream.avail_out == 0) {
|
1275 |
if (d_stream.avail_out == 0) {
|
1264 |
if ((outp = (char*)allocmem(outp, inlen, &alloc,
|
1276 |
if ((outp = (char*)allocmem(outp, inlen, &alloc,
|
1265 |
imul, mxinc)) == 0) {
|
1277 |
imul, mxinc)) == 0) {
|
1266 |
LOGERR(("Inflate: out of memory, current alloc %d\n",
|
1278 |
LOGERR(("Inflate: out of memory, current alloc %d\n",
|
1267 |
alloc*inlen));
|
1279 |
alloc*inlen));
|
1268 |
inflateEnd(&d_stream);
|
1280 |
inflateEnd(&d_stream);
|
1269 |
return false;
|
1281 |
return false;
|
1270 |
} else {
|
1282 |
} else {
|
|
... |
|
... |
1345 |
string nfn = ncc->getpath();
|
1357 |
string nfn = ncc->getpath();
|
1346 |
if (!ncc->create(off_t(newmbs) * 1000 * 1024,
|
1358 |
if (!ncc->create(off_t(newmbs) * 1000 * 1024,
|
1347 |
CirCache::CC_CRUNIQUE | CirCache::CC_CRTRUNCATE)) {
|
1359 |
CirCache::CC_CRUNIQUE | CirCache::CC_CRTRUNCATE)) {
|
1348 |
cerr << "Cant create new file in " << tmpdir << " : " <<
|
1360 |
cerr << "Cant create new file in " << tmpdir << " : " <<
|
1349 |
ncc->getReason() << endl;
|
1361 |
ncc->getReason() << endl;
|
1350 |
return false;
|
1362 |
return false;
|
1351 |
}
|
1363 |
}
|
1352 |
|
1364 |
|
1353 |
bool eof = false;
|
1365 |
bool eof = false;
|
1354 |
occ->rewind(eof);
|
1366 |
if (!occ->rewind(eof)) {
|
|
|
1367 |
if (!eof) {
|
|
|
1368 |
cerr << "Initial rewind failed" << endl;
|
|
|
1369 |
return false;
|
|
|
1370 |
}
|
|
|
1371 |
}
|
1355 |
int nentries = 0;
|
1372 |
int nentries = 0;
|
1356 |
while (!eof) {
|
1373 |
while (!eof) {
|
1357 |
string udi, sdic, data;
|
1374 |
string udi, sdic, data;
|
1358 |
if (!occ->getCurrent(udi, sdic, data)) {
|
1375 |
if (!occ->getCurrent(udi, sdic, data)) {
|
1359 |
cerr << "getCurrent failed: " << occ->getReason() << endl;
|
1376 |
cerr << "getCurrent failed: " << occ->getReason() << endl;
|
|
... |
|
... |
1400 |
}
|
1417 |
}
|
1401 |
|
1418 |
|
1402 |
|
1419 |
|
1403 |
static char *thisprog;
|
1420 |
static char *thisprog;
|
1404 |
|
1421 |
|
1405 |
static char usage [] =
|
1422 |
static char usage [] =
|
1406 |
" -c [-u] <dirname> : create\n"
|
1423 |
" -c [-u] <dirname> : create\n"
|
1407 |
" -p <dirname> <apath> [apath ...] : put files\n"
|
1424 |
" -p <dirname> <apath> [apath ...] : put files\n"
|
1408 |
" -d <dirname> : dump\n"
|
1425 |
" -d <dirname> : dump\n"
|
1409 |
" -g [-i instance] [-D] <dirname> <udi>: get\n"
|
1426 |
" -g [-i instance] [-D] <dirname> <udi>: get\n"
|
1410 |
" -D: also dump data\n"
|
1427 |
" -D: also dump data\n"
|
1411 |
" -e <dirname> <udi> : erase\n"
|
1428 |
" -e <dirname> <udi> : erase\n"
|
1412 |
" -s <dirname> <newmbs> : resize\n"
|
1429 |
" -s <dirname> <newmbs> : resize\n"
|
1413 |
;
|
1430 |
;
|
1414 |
static void
|
1431 |
static void
|
1415 |
Usage(FILE *fp = stderr)
|
1432 |
Usage(FILE *fp = stderr)
|
1416 |
{
|
1433 |
{
|
1417 |
fprintf(fp, "%s: usage:\n%s", thisprog, usage);
|
1434 |
fprintf(fp, "%s: usage:\n%s", thisprog, usage);
|
1418 |
exit(1);
|
1435 |
exit(1);
|
|
... |
|
... |
1436 |
|
1453 |
|
1437 |
thisprog = argv[0];
|
1454 |
thisprog = argv[0];
|
1438 |
argc--; argv++;
|
1455 |
argc--; argv++;
|
1439 |
|
1456 |
|
1440 |
while (argc > 0 && **argv == '-') {
|
1457 |
while (argc > 0 && **argv == '-') {
|
1441 |
(*argv)++;
|
1458 |
(*argv)++;
|
1442 |
if (!(**argv))
|
1459 |
if (!(**argv))
|
1443 |
/* Cas du "adb - core" */
|
1460 |
/* Cas du "adb - core" */
|
1444 |
Usage();
|
1461 |
Usage();
|
1445 |
while (**argv)
|
1462 |
while (**argv)
|
1446 |
switch (*(*argv)++) {
|
1463 |
switch (*(*argv)++) {
|
1447 |
case 'c': op_flags |= OPT_c; break;
|
1464 |
case 'c': op_flags |= OPT_c; break;
|
1448 |
case 'D': op_flags |= OPT_D; break;
|
1465 |
case 'D': op_flags |= OPT_D; break;
|
1449 |
case 'd': op_flags |= OPT_d; break;
|
1466 |
case 'd': op_flags |= OPT_d; break;
|
1450 |
case 'e': op_flags |= OPT_e; break;
|
1467 |
case 'e': op_flags |= OPT_e; break;
|
1451 |
case 'g': op_flags |= OPT_g; break;
|
1468 |
case 'g': op_flags |= OPT_g; break;
|
1452 |
case 'i': op_flags |= OPT_i; if (argc < 2) Usage();
|
1469 |
case 'i': op_flags |= OPT_i; if (argc < 2) Usage();
|
1453 |
if ((sscanf(*(++argv), "%d", &instance)) != 1)
|
1470 |
if ((sscanf(*(++argv), "%d", &instance)) != 1)
|
1454 |
Usage();
|
1471 |
Usage();
|
1455 |
argc--;
|
1472 |
argc--;
|
1456 |
goto b1;
|
1473 |
goto b1;
|
1457 |
case 'p': op_flags |= OPT_p; break;
|
1474 |
case 'p': op_flags |= OPT_p; break;
|
1458 |
case 's': op_flags |= OPT_s; break;
|
1475 |
case 's': op_flags |= OPT_s; break;
|
1459 |
case 'u': op_flags |= OPT_u; break;
|
1476 |
case 'u': op_flags |= OPT_u; break;
|
1460 |
default: Usage(); break;
|
1477 |
default: Usage(); break;
|
1461 |
}
|
1478 |
}
|
1462 |
b1: argc--; argv++;
|
1479 |
b1: argc--; argv++;
|
1463 |
}
|
1480 |
}
|
1464 |
|
1481 |
|
1465 |
DebugLog::getdbl()->setloglevel(DEBERR);
|
1482 |
DebugLog::getdbl()->setloglevel(DEBERR);
|
1466 |
DebugLog::setfilename("stderr");
|
1483 |
DebugLog::setfilename("stderr");
|
1467 |
|
1484 |
|
1468 |
if (argc < 1)
|
1485 |
if (argc < 1)
|
1469 |
Usage();
|
1486 |
Usage();
|
1470 |
string dir = *argv++;argc--;
|
1487 |
string dir = *argv++;argc--;
|
1471 |
|
1488 |
|
1472 |
CirCache cc(dir);
|
1489 |
CirCache cc(dir);
|
1473 |
|
1490 |
|
1474 |
if (op_flags & OPT_c) {
|
1491 |
if (op_flags & OPT_c) {
|
1475 |
int flags = 0;
|
1492 |
int flags = 0;
|
1476 |
if (op_flags & OPT_u)
|
1493 |
if (op_flags & OPT_u)
|
1477 |
flags |= CirCache::CC_CRUNIQUE;
|
1494 |
flags |= CirCache::CC_CRUNIQUE;
|
1478 |
if (!cc.create(100*1024, flags)) {
|
1495 |
if (!cc.create(100*1024, flags)) {
|
1479 |
cerr << "Create failed:" << cc.getReason() << endl;
|
1496 |
cerr << "Create failed:" << cc.getReason() << endl;
|
1480 |
exit(1);
|
1497 |
exit(1);
|
1481 |
}
|
1498 |
}
|
1482 |
} else if (op_flags & OPT_s) {
|
1499 |
} else if (op_flags & OPT_s) {
|
1483 |
if (argc != 1) {
|
1500 |
if (argc != 1) {
|
1484 |
Usage();
|
1501 |
Usage();
|
1485 |
}
|
1502 |
}
|
1486 |
int newmbs = atoi(*argv++);argc--;
|
1503 |
int newmbs = atoi(*argv++);argc--;
|
1487 |
if (!resizecc(dir, newmbs)) {
|
1504 |
if (!resizecc(dir, newmbs)) {
|
1488 |
exit(1);
|
1505 |
exit(1);
|
1489 |
}
|
1506 |
}
|
1490 |
} else if (op_flags & OPT_p) {
|
1507 |
} else if (op_flags & OPT_p) {
|
1491 |
if (argc < 1)
|
1508 |
if (argc < 1)
|
1492 |
Usage();
|
1509 |
Usage();
|
1493 |
if (!cc.open(CirCache::CC_OPWRITE)) {
|
1510 |
if (!cc.open(CirCache::CC_OPWRITE)) {
|
1494 |
cerr << "Open failed: " << cc.getReason() << endl;
|
1511 |
cerr << "Open failed: " << cc.getReason() << endl;
|
1495 |
exit(1);
|
1512 |
exit(1);
|
1496 |
}
|
1513 |
}
|
1497 |
while (argc) {
|
1514 |
while (argc) {
|
1498 |
string fn = *argv++;argc--;
|
1515 |
string fn = *argv++;argc--;
|
1499 |
char dic[1000];
|
1516 |
char dic[1000];
|
1500 |
string data, reason;
|
1517 |
string data, reason;
|
1501 |
if (!file_to_string(fn, data, &reason)) {
|
1518 |
if (!file_to_string(fn, data, &reason)) {
|
1502 |
cerr << "File_to_string: " << reason << endl;
|
1519 |
cerr << "File_to_string: " << reason << endl;
|
1503 |
exit(1);
|
1520 |
exit(1);
|
1504 |
}
|
1521 |
}
|
1505 |
string udi;
|
1522 |
string udi;
|
1506 |
make_udi(fn, "", udi);
|
1523 |
make_udi(fn, "", udi);
|
1507 |
sprintf(dic, "#whatever...\nmimetype = text/plain\nudi=%s\n",
|
1524 |
sprintf(dic, "#whatever...\nmimetype = text/plain\nudi=%s\n",
|
1508 |
udi.c_str());
|
1525 |
udi.c_str());
|
1509 |
string sdic;
|
1526 |
string sdic;
|
1510 |
sdic.assign(dic, strlen(dic));
|
1527 |
sdic.assign(dic, strlen(dic));
|
1511 |
ConfSimple conf(sdic);
|
1528 |
ConfSimple conf(sdic);
|
1512 |
|
1529 |
|
1513 |
if (!cc.put(udi, &conf, data, 0)) {
|
1530 |
if (!cc.put(udi, &conf, data, 0)) {
|
1514 |
cerr << "Put failed: " << cc.getReason() << endl;
|
1531 |
cerr << "Put failed: " << cc.getReason() << endl;
|
1515 |
cerr << "conf: ["; conf.write(cerr); cerr << "]" << endl;
|
1532 |
cerr << "conf: ["; conf.write(cerr); cerr << "]" << endl;
|
1516 |
exit(1);
|
1533 |
exit(1);
|
1517 |
}
|
1534 |
}
|
1518 |
}
|
1535 |
}
|
1519 |
cc.open(CirCache::CC_OPREAD);
|
1536 |
cc.open(CirCache::CC_OPREAD);
|
1520 |
} else if (op_flags & OPT_g) {
|
1537 |
} else if (op_flags & OPT_g) {
|
1521 |
if (!cc.open(CirCache::CC_OPREAD)) {
|
1538 |
if (!cc.open(CirCache::CC_OPREAD)) {
|
1522 |
cerr << "Open failed: " << cc.getReason() << endl;
|
1539 |
cerr << "Open failed: " << cc.getReason() << endl;
|
1523 |
exit(1);
|
1540 |
exit(1);
|
1524 |
}
|
1541 |
}
|
1525 |
while (argc) {
|
1542 |
while (argc) {
|
1526 |
string udi = *argv++;argc--;
|
1543 |
string udi = *argv++;argc--;
|
1527 |
string dic, data;
|
1544 |
string dic, data;
|
1528 |
if (!cc.get(udi, dic, data, instance)) {
|
1545 |
if (!cc.get(udi, dic, data, instance)) {
|
1529 |
cerr << "Get failed: " << cc.getReason() << endl;
|
1546 |
cerr << "Get failed: " << cc.getReason() << endl;
|
1530 |
exit(1);
|
1547 |
exit(1);
|
1531 |
}
|
1548 |
}
|
1532 |
cout << "Dict: [" << dic << "]" << endl;
|
1549 |
cout << "Dict: [" << dic << "]" << endl;
|
1533 |
if (op_flags & OPT_D)
|
1550 |
if (op_flags & OPT_D)
|
1534 |
cout << "Data: [" << data << "]" << endl;
|
1551 |
cout << "Data: [" << data << "]" << endl;
|
1535 |
}
|
1552 |
}
|
1536 |
} else if (op_flags & OPT_e) {
|
1553 |
} else if (op_flags & OPT_e) {
|
1537 |
if (!cc.open(CirCache::CC_OPWRITE)) {
|
1554 |
if (!cc.open(CirCache::CC_OPWRITE)) {
|
1538 |
cerr << "Open failed: " << cc.getReason() << endl;
|
1555 |
cerr << "Open failed: " << cc.getReason() << endl;
|
1539 |
exit(1);
|
1556 |
exit(1);
|
1540 |
}
|
1557 |
}
|
1541 |
while (argc) {
|
1558 |
while (argc) {
|
1542 |
string udi = *argv++;argc--;
|
1559 |
string udi = *argv++;argc--;
|
1543 |
string dic, data;
|
1560 |
string dic, data;
|
1544 |
if (!cc.erase(udi)) {
|
1561 |
if (!cc.erase(udi)) {
|
1545 |
cerr << "Erase failed: " << cc.getReason() << endl;
|
1562 |
cerr << "Erase failed: " << cc.getReason() << endl;
|
1546 |
exit(1);
|
1563 |
exit(1);
|
1547 |
}
|
1564 |
}
|
1548 |
}
|
1565 |
}
|
1549 |
} else if (op_flags & OPT_d) {
|
1566 |
} else if (op_flags & OPT_d) {
|
1550 |
if (!cc.open(CirCache::CC_OPREAD)) {
|
1567 |
if (!cc.open(CirCache::CC_OPREAD)) {
|
1551 |
cerr << "Open failed: " << cc.getReason() << endl;
|
1568 |
cerr << "Open failed: " << cc.getReason() << endl;
|
1552 |
exit(1);
|
1569 |
exit(1);
|
1553 |
}
|
1570 |
}
|
1554 |
cc.dump();
|
1571 |
cc.dump();
|
1555 |
} else
|
1572 |
} else
|
1556 |
Usage();
|
1573 |
Usage();
|
1557 |
|
1574 |
|
1558 |
exit(0);
|
1575 |
exit(0);
|
1559 |
}
|
1576 |
}
|
1560 |
|
1577 |
|
1561 |
#endif
|
1578 |
#endif
|