Switch to side-by-side view

--- a/src/utils/circache.cpp
+++ b/src/utils/circache.cpp
@@ -156,7 +156,8 @@
     ////// These are cache persistent state and written to the first block:
     // Maximum file size, after which we begin reusing old space
     off_t m_maxsize; 
-    // Offset of the oldest header. 
+    // Offset of the oldest header, or max file offset (file size)
+    // while the file is growing. This is the next write position.
     off_t m_oheadoffs;
     // Offset of last write (newest header)
     off_t m_nheadoffs;
@@ -188,15 +189,15 @@
         UdiH h(udi);
 
         LOGDEB2(("Circache::khEnter: h %s offs %lu udi [%s]\n", 
-		 h.asHexString().c_str(), (ULONG)ofs, udi.c_str()));
+				 h.asHexString().c_str(), (ULONG)ofs, udi.c_str()));
 
         pair<kh_type::iterator, kh_type::iterator> p = m_ofskh.equal_range(h);
 
         if (p.first != m_ofskh.end() && p.first->first == h) {
             for (kh_type::iterator it = p.first; it != p.second; it++) {
                 LOGDEB2(("Circache::khEnter: col h %s, ofs %lu\n", 
-			 it->first.asHexString().c_str(),
-			 (ULONG)it->second));
+						 it->first.asHexString().c_str(),
+						 (ULONG)it->second));
                 if (it->second == ofs) {
                     // (h,offs) already there. Happens
                     LOGDEB2(("Circache::khEnter: already there\n"));
@@ -227,7 +228,7 @@
         UdiH h(udi);
 
         LOGDEB2(("Circache::khFind: h %s udi [%s]\n", 
-		 h.asHexString().c_str(), udi.c_str()));
+				 h.asHexString().c_str(), udi.c_str()));
 
         pair<kh_type::iterator, kh_type::iterator> p = m_ofskh.equal_range(h);
 
@@ -318,10 +319,10 @@
 
     bool writefirstblock()
     {
-	if (m_fd < 0) {
-	    m_reason << "writefirstblock: not open ";
-	    return false;
-	}
+		if (m_fd < 0) {
+			m_reason << "writefirstblock: not open ";
+			return false;
+		}
 
         ostringstream s;
         s << 
@@ -347,10 +348,10 @@
 
     bool readfirstblock()
     {
-	if (m_fd < 0) {
-	    m_reason << "readfirstblock: not open ";
-	    return false;
-	}
+		if (m_fd < 0) {
+			m_reason << "readfirstblock: not open ";
+			return false;
+		}
 
         char bf[CIRCACHE_FIRSTBLOCK_SIZE];
 
@@ -393,14 +394,14 @@
 
     bool writeEntryHeader(off_t offset, const EntryHeaderData& d)
     {
-	if (m_fd < 0) {
-	    m_reason << "writeEntryHeader: not open ";
-	    return false;
-	}
+		if (m_fd < 0) {
+			m_reason << "writeEntryHeader: not open ";
+			return false;
+		}
         char bf[CIRCACHE_HEADER_SIZE];
         memset(bf, 0, CIRCACHE_HEADER_SIZE);
         snprintf(bf, CIRCACHE_HEADER_SIZE, 
-		 headerformat, d.dicsize, d.datasize, d.padsize, d.flags);
+				 headerformat, d.dicsize, d.datasize, d.padsize, d.flags);
         if (lseek(m_fd, offset, 0) != offset) {
             m_reason << "CirCache::weh: lseek(" << offset << 
                 ") failed: errno " << errno;
@@ -415,10 +416,10 @@
 
     CCScanHook::status readEntryHeader(off_t offset, EntryHeaderData& d)
     {
-	if (m_fd < 0) {
-	    m_reason << "readEntryHeader: not open ";
+		if (m_fd < 0) {
+			m_reason << "readEntryHeader: not open ";
             return CCScanHook::Error;
-	}
+		}
 
         if (lseek(m_fd, offset, 0) != offset) {
             m_reason << "readEntryHeader: lseek(" << offset << 
@@ -451,10 +452,10 @@
     CCScanHook::status scan(off_t startoffset, CCScanHook *user, 
                             bool fold = false)
     {
-	if (m_fd < 0) {
-	    m_reason << "scan: not open ";
+		if (m_fd < 0) {
+			m_reason << "scan: not open ";
             return CCScanHook::Error;
-	}
+		}
 
         off_t so0 = startoffset;
         bool already_folded = false;
@@ -622,16 +623,16 @@
     off_t headoffs;
     off_t padsize;
     CCScanHookRecord()
-	: headoffs(0), padsize(0)
+		: headoffs(0), padsize(0)
     {
     }
     virtual status takeone(off_t offs, const string& udi, 
-			   const EntryHeaderData& d)
-    {
-	headoffs = offs;
-	padsize = d.padsize;
-	LOGDEB2(("CCScanHookRecord::takeone: offs %lld padsize %lld\n", 
-		 headoffs, padsize));
+						   const EntryHeaderData& d)
+    {
+		headoffs = offs;
+		padsize = d.padsize;
+		LOGDEB2(("CCScanHookRecord::takeone: offs %lld padsize %lld\n", 
+				 headoffs, padsize));
         return Continue;
     }
 };
@@ -644,62 +645,62 @@
 bool CirCache::create(off_t maxsize, int flags)
 {
     LOGDEB(("CirCache::create: [%s] maxsz %lld flags 0x%x\n", 
-	    m_dir.c_str(), maxsize, flags));
+			m_dir.c_str(), maxsize, flags));
     if (m_d == 0) {
-	LOGERR(("CirCache::create: null data\n"));
-	return false;
+		LOGERR(("CirCache::create: null data\n"));
+		return false;
     }
 
     struct stat st;
     if (stat(m_dir.c_str(), &st) < 0) {
-	// Directory does not exist, create it
-	if (mkdir(m_dir.c_str(), 0777) < 0) {
-	    m_d->m_reason << "CirCache::create: mkdir(" << m_dir << 
-		") failed" << " errno " << errno;
-	    return false;
-	}
+		// Directory does not exist, create it
+		if (mkdir(m_dir.c_str(), 0777) < 0) {
+			m_d->m_reason << "CirCache::create: mkdir(" << m_dir << 
+				") failed" << " errno " << errno;
+			return false;
+		}
     } else {
-	// If the file exists too, and truncate is not set, switch
-	// to open-mode. Still may need to update header params.
-	if (access(m_d->datafn(m_dir).c_str(), 0) >= 0 &&
-	    !(flags & CC_CRTRUNCATE)) {
-	    if (!open(CC_OPWRITE)) {
-		return false;
-	    }
-	    if (maxsize == m_d->m_maxsize &&
-		((flags & CC_CRUNIQUE) != 0) == m_d->m_uniquentries) {
-		LOGDEB(("Header unchanged, no rewrite\n"));
-		return true;
-	    }
-	    // If the new maxsize is bigger than current size, we need
-	    // to stop recycling if this is what we are doing.
-	    if (maxsize > m_d->m_maxsize && maxsize > st.st_size) {
-		// Scan the file to find the last physical record. The
-		// ohead is set at physical eof, and nhead is the last
-		// scanned record
-		CCScanHookRecord rec;
-		m_d->scan(CIRCACHE_FIRSTBLOCK_SIZE, &rec, false);
-		m_d->m_oheadoffs = lseek(m_d->m_fd, 0, SEEK_END);
-		m_d->m_nheadoffs = rec.headoffs;
-		m_d->m_npadsize = rec.padsize;
-	    }
-	    m_d->m_maxsize = maxsize;
-	    m_d->m_uniquentries = ((flags & CC_CRUNIQUE) != 0);
-	    LOGDEB(("CirCache::create: rewriting header with "
-		    "maxsize %lld oheadoffs %lld nheadoffs %lld "
-		    "npadsize %d unient %d\n",
-		    m_d->m_maxsize, m_d->m_oheadoffs, m_d->m_nheadoffs,
-		    m_d->m_npadsize, int(m_d->m_uniquentries)));
-	    return m_d->writefirstblock();
-	}
-	// Else fallthrough to create file
+		// If the file exists too, and truncate is not set, switch
+		// to open-mode. Still may need to update header params.
+		if (access(m_d->datafn(m_dir).c_str(), 0) >= 0 &&
+			!(flags & CC_CRTRUNCATE)) {
+			if (!open(CC_OPWRITE)) {
+				return false;
+			}
+			if (maxsize == m_d->m_maxsize &&
+				((flags & CC_CRUNIQUE) != 0) == m_d->m_uniquentries) {
+				LOGDEB(("Header unchanged, no rewrite\n"));
+				return true;
+			}
+			// If the new maxsize is bigger than current size, we need
+			// to stop recycling if this is what we are doing.
+			if (maxsize > m_d->m_maxsize && maxsize > st.st_size) {
+				// Scan the file to find the last physical record. The
+				// ohead is set at physical eof, and nhead is the last
+				// scanned record
+				CCScanHookRecord rec;
+				m_d->scan(CIRCACHE_FIRSTBLOCK_SIZE, &rec, false);
+				m_d->m_oheadoffs = lseek(m_d->m_fd, 0, SEEK_END);
+				m_d->m_nheadoffs = rec.headoffs;
+				m_d->m_npadsize = rec.padsize;
+			}
+			m_d->m_maxsize = maxsize;
+			m_d->m_uniquentries = ((flags & CC_CRUNIQUE) != 0);
+			LOGDEB(("CirCache::create: rewriting header with "
+					"maxsize %lld oheadoffs %lld nheadoffs %lld "
+					"npadsize %d unient %d\n",
+					m_d->m_maxsize, m_d->m_oheadoffs, m_d->m_nheadoffs,
+					m_d->m_npadsize, int(m_d->m_uniquentries)));
+			return m_d->writefirstblock();
+		}
+		// Else fallthrough to create file
     }
 
     if ((m_d->m_fd = ::open(m_d->datafn(m_dir).c_str(), 
-			    O_CREAT | O_RDWR | O_TRUNC, 0666)) < 0) {
+							O_CREAT | O_RDWR | O_TRUNC, 0666)) < 0) {
         m_d->m_reason << "CirCache::create: open/creat(" << 
             m_d->datafn(m_dir) << ") failed " << "errno " << errno;
-	return false;
+		return false;
     }
 
     m_d->m_maxsize = maxsize;
@@ -720,15 +721,15 @@
 bool CirCache::open(OpMode mode)
 {
     if (m_d == 0) {
-	LOGERR(("CirCache::open: null data\n"));
-	return false;
+		LOGERR(("CirCache::open: null data\n"));
+		return false;
     }
 
     if (m_d->m_fd >= 0)
         ::close(m_d->m_fd);
 
     if ((m_d->m_fd = ::open(m_d->datafn(m_dir).c_str(), 
-			    mode == CC_OPREAD ? O_RDONLY : O_RDWR)) < 0) {
+							mode == CC_OPREAD ? O_RDONLY : O_RDWR)) < 0) {
         m_d->m_reason << "CirCache::open: open(" << m_d->datafn(m_dir) << 
             ") failed " << "errno " << errno;
         return false;
@@ -937,13 +938,13 @@
     UINT sizeseen;
     vector<pair<string, off_t> > squashed_udis;
     CCScanHookSpacer(int sz)
-    : sizewanted(sz), sizeseen(0) {assert(sz > 0);}
+		: sizewanted(sz), sizeseen(0) {assert(sz > 0);}
 
     virtual status takeone(off_t offs, const string& udi, 
                            const EntryHeaderData& d)
     {
         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;
         squashed_udis.push_back(make_pair(udi, offs));
         if (sizeseen >= sizewanted)
@@ -1029,10 +1030,10 @@
         if (m_d->readEntryHeader(m_d->m_nheadoffs, pd) != CCScanHook::Continue){
             return false;
         }
-	if (int(pd.padsize) != m_d->m_npadsize) {
-	    m_d->m_reason << "CirCache::put: logic error: bad padsize ";
-	    return false;
-	}
+		if (int(pd.padsize) != m_d->m_npadsize) {
+			m_d->m_reason << "CirCache::put: logic error: bad padsize ";
+			return false;
+		}
         if (pd.dicsize == 0) {
             // erased entry. Also recover the header space, no need to rewrite
             // the header, we're going to write on it.
@@ -1092,7 +1093,7 @@
     char head[CIRCACHE_HEADER_SIZE];
     memset(head, 0, CIRCACHE_HEADER_SIZE);
     snprintf(head, CIRCACHE_HEADER_SIZE, 
-	     headerformat, dic.size(), datalen, npadsize, flags);
+			 headerformat, dic.size(), datalen, npadsize, flags);
     struct iovec vecs[3];
     vecs[0].iov_base = head;
     vecs[0].iov_len = CIRCACHE_HEADER_SIZE;
@@ -1132,8 +1133,19 @@
 
     eof = false;
 
-    // Read oldest header
-    m_d->m_itoffs = m_d->m_oheadoffs;
+	off_t fsize = lseek(m_d->m_fd, 0, SEEK_END);
+	if (fsize == (off_t)-1) {
+		LOGERR(("CirCache::rewind: seek to EOF failed\n"));
+		return false;
+	}
+    // Read oldest header. This is either at the position pointed to
+    // by oheadoffs, or after the first block if the file is still
+    // growing.
+	if (m_d->m_oheadoffs == fsize) {
+		m_d->m_itoffs = CIRCACHE_FIRSTBLOCK_SIZE;
+	} else {
+		m_d->m_itoffs = m_d->m_oheadoffs;
+	}
     CCScanHook::status st = m_d->readEntryHeader(m_d->m_itoffs, m_d->m_ithd);
 
     switch(st) {
@@ -1262,7 +1274,7 @@
                  d_stream.avail_out, d_stream.total_out));
         if (d_stream.avail_out == 0) {
             if ((outp = (char*)allocmem(outp, inlen, &alloc, 
-					imul, mxinc)) == 0) {
+										imul, mxinc)) == 0) {
                 LOGERR(("Inflate: out of memory, current alloc %d\n", 
                         alloc*inlen));
                 inflateEnd(&d_stream);
@@ -1347,11 +1359,16 @@
                      CirCache::CC_CRUNIQUE | CirCache::CC_CRTRUNCATE)) {
         cerr << "Cant create new file in " << tmpdir << " : " << 
             ncc->getReason() << endl;
-	return false;
+		return false;
     }
 
     bool eof = false;
-    occ->rewind(eof);
+	if (!occ->rewind(eof)) {
+		if (!eof) {
+			cerr << "Initial rewind failed" << endl;
+			return false;
+		}
+	}
     int nentries = 0;
     while (!eof) {
         string udi, sdic, data;
@@ -1402,15 +1419,15 @@
 
 static char *thisprog;
 
-static char usage [] =
-    " -c [-u] <dirname> : create\n"
-    " -p <dirname> <apath> [apath ...] : put files\n"
-    " -d <dirname> : dump\n"
-    " -g [-i instance] [-D] <dirname> <udi>: get\n"
-    "   -D: also dump data\n"
-    " -e <dirname> <udi> : erase\n"
-    " -s <dirname> <newmbs> : resize\n"
-    ;
+static char usage [] = 
+" -c [-u] <dirname> : create\n"
+" -p <dirname> <apath> [apath ...] : put files\n"
+" -d <dirname> : dump\n"
+" -g [-i instance] [-D] <dirname> <udi>: get\n"
+"   -D: also dump data\n"
+" -e <dirname> <udi> : erase\n"
+" -s <dirname> <newmbs> : resize\n"
+;
 static void
 Usage(FILE *fp = stderr)
 {
@@ -1438,27 +1455,27 @@
     argc--; argv++;
 
     while (argc > 0 && **argv == '-') {
-	(*argv)++;
-	if (!(**argv))
-	    /* Cas du "adb - core" */
-	    Usage();
-	while (**argv)
-	    switch (*(*argv)++) {
-	    case 'c':	op_flags |= OPT_c; break;
-	    case 'D':	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();
-		if ((sscanf(*(++argv), "%d", &instance)) != 1) 
-		    Usage(); 
-		argc--; 
-		goto b1;
-	    case 'p':	op_flags |= OPT_p; break;
-	    case 's':	op_flags |= OPT_s; break;
-	    case 'u':	op_flags |= OPT_u; break;
-	    default: Usage();	break;
-	    }
+		(*argv)++;
+		if (!(**argv))
+			/* Cas du "adb - core" */
+			Usage();
+		while (**argv)
+			switch (*(*argv)++) {
+			case 'c':	op_flags |= OPT_c; break;
+			case 'D':	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();
+				if ((sscanf(*(++argv), "%d", &instance)) != 1) 
+					Usage(); 
+				argc--; 
+				goto b1;
+			case 'p':	op_flags |= OPT_p; break;
+			case 's':	op_flags |= OPT_s; break;
+			case 'u':	op_flags |= OPT_u; break;
+			default: Usage();	break;
+			}
     b1: argc--; argv++;
     }
 
@@ -1466,19 +1483,19 @@
     DebugLog::setfilename("stderr");
 
     if (argc < 1)
-	Usage();
+		Usage();
     string dir = *argv++;argc--;
 
     CirCache cc(dir);
 
     if (op_flags & OPT_c) {
-	int flags = 0;
-	if (op_flags & OPT_u)
-	    flags |= CirCache::CC_CRUNIQUE;
-	if (!cc.create(100*1024, flags)) {
-	    cerr << "Create failed:" << cc.getReason() << endl;
-	    exit(1);
-	}
+		int flags = 0;
+		if (op_flags & OPT_u)
+			flags |= CirCache::CC_CRUNIQUE;
+		if (!cc.create(100*1024, flags)) {
+			cerr << "Create failed:" << cc.getReason() << endl;
+			exit(1);
+		}
     } else if (op_flags & OPT_s) {
         if (argc != 1) {
             Usage();
@@ -1488,72 +1505,72 @@
             exit(1);
         }
     } else if (op_flags & OPT_p) {
-	if (argc < 1)
-	    Usage();
-	if (!cc.open(CirCache::CC_OPWRITE)) {
-	    cerr << "Open failed: " << cc.getReason() << endl;
-	    exit(1);
-	}
-	while (argc) {
-	    string fn = *argv++;argc--;
-	    char dic[1000];
-	    string data, reason;
-	    if (!file_to_string(fn, data, &reason)) {
-		cerr << "File_to_string: " << reason << endl;
-		exit(1);
-	    }
-	    string udi;
-	    make_udi(fn, "", udi);
-	    sprintf(dic, "#whatever...\nmimetype = text/plain\nudi=%s\n", 
-		    udi.c_str());
-	    string sdic;
-	    sdic.assign(dic, strlen(dic));
-	    ConfSimple conf(sdic);
+		if (argc < 1)
+			Usage();
+		if (!cc.open(CirCache::CC_OPWRITE)) {
+			cerr << "Open failed: " << cc.getReason() << endl;
+			exit(1);
+		}
+		while (argc) {
+			string fn = *argv++;argc--;
+			char dic[1000];
+			string data, reason;
+			if (!file_to_string(fn, data, &reason)) {
+				cerr << "File_to_string: " << reason << endl;
+				exit(1);
+			}
+			string udi;
+			make_udi(fn, "", udi);
+			sprintf(dic, "#whatever...\nmimetype = text/plain\nudi=%s\n", 
+					udi.c_str());
+			string sdic;
+			sdic.assign(dic, strlen(dic));
+			ConfSimple conf(sdic);
    
-	    if (!cc.put(udi, &conf, data, 0)) {
-		cerr << "Put failed: " << cc.getReason() << endl;
-		cerr << "conf: ["; conf.write(cerr); cerr << "]" << endl;
-		exit(1);
-	    }
-	}
-	cc.open(CirCache::CC_OPREAD);
+			if (!cc.put(udi, &conf, data, 0)) {
+				cerr << "Put failed: " << cc.getReason() << endl;
+				cerr << "conf: ["; conf.write(cerr); cerr << "]" << endl;
+				exit(1);
+			}
+		}
+		cc.open(CirCache::CC_OPREAD);
     } else if (op_flags & OPT_g) {
-	if (!cc.open(CirCache::CC_OPREAD)) {
-	    cerr << "Open failed: " << cc.getReason() << endl;
-	    exit(1);
-	}
-	while (argc) {
-	    string udi = *argv++;argc--;
-	    string dic, data;
-	    if (!cc.get(udi, dic, data, instance)) {
-		cerr << "Get failed: " << cc.getReason() << endl;
-		exit(1);
-	    }
-	    cout << "Dict: [" << dic << "]" << endl;
-	    if (op_flags & OPT_D)
-		cout << "Data: [" << data << "]" << endl;
-	}
+		if (!cc.open(CirCache::CC_OPREAD)) {
+			cerr << "Open failed: " << cc.getReason() << endl;
+			exit(1);
+		}
+		while (argc) {
+			string udi = *argv++;argc--;
+			string dic, data;
+			if (!cc.get(udi, dic, data, instance)) {
+				cerr << "Get failed: " << cc.getReason() << endl;
+				exit(1);
+			}
+			cout << "Dict: [" << dic << "]" << endl;
+			if (op_flags & OPT_D)
+				cout << "Data: [" << data << "]" << endl;
+		}
     } else if (op_flags & OPT_e) {
-	if (!cc.open(CirCache::CC_OPWRITE)) {
-	    cerr << "Open failed: " << cc.getReason() << endl;
-	    exit(1);
-	}
-	while (argc) {
-	    string udi = *argv++;argc--;
-	    string dic, data;
-	    if (!cc.erase(udi)) {
-		cerr << "Erase failed: " << cc.getReason() << endl;
-		exit(1);
-	    }
-	}
+		if (!cc.open(CirCache::CC_OPWRITE)) {
+			cerr << "Open failed: " << cc.getReason() << endl;
+			exit(1);
+		}
+		while (argc) {
+			string udi = *argv++;argc--;
+			string dic, data;
+			if (!cc.erase(udi)) {
+				cerr << "Erase failed: " << cc.getReason() << endl;
+				exit(1);
+			}
+		}
     } else if (op_flags & OPT_d) {
-	if (!cc.open(CirCache::CC_OPREAD)) {
-	    cerr << "Open failed: " << cc.getReason() << endl;
-	    exit(1);
-	}
-	cc.dump();
+		if (!cc.open(CirCache::CC_OPREAD)) {
+			cerr << "Open failed: " << cc.getReason() << endl;
+			exit(1);
+		}
+		cc.dump();
     } else
-	Usage();
+		Usage();
 
     exit(0);
 }