in components/constdb/tinycdb.hpp [230:299]
const failable<bool> rewrite(const lambda<const failable<bool>(buffer& buf, const unsigned int klen, const unsigned int vlen)>& update, const lambda<const failable<bool>(struct cdb_make&)>& finish, buffer& buf, const int tmpfd, const TinyCDB& cdb) {
// Initialize new db structure
struct cdb_make cdbm;
cdb_make_start(&cdbm, tmpfd);
// Open existing db
failable<int> ffd = cdbopen(cdb);
if (!hasContent(ffd))
return mkfailure<bool>(ffd);
const int fd = content(ffd);
// Read the db header
unsigned int pos = 0;
if (lseek(fd, 0, SEEK_SET) != 0)
return mkfailure<bool>("Couldn't seek to tinycdb database start");
if (::read(fd, buf, 2048) != 2048)
return mkfailure<bool>("Couldn't read tinycdb database header");
pos += 2048;
const unsigned int eod = cdb_unpack(buf);
debug(pos, "tinycdb::rewrite::eod");
// Read and add the existing entries
while(pos < eod) {
if (eod - pos < 8)
return mkfailure<bool>("Invalid tinycdb database format, couldn't read entry header");
if (::read(fd, buf, 8) != 8)
return mkfailure<bool>("Couldn't read tinycdb entry header");
pos += 8;
const unsigned int klen = cdb_unpack(buf);
const unsigned int vlen = cdb_unpack(((unsigned char*)buf) + 4);
const unsigned int elen = klen + vlen;
// Read existing entry
buf = mkbuffer(buf, elen);
if (eod - pos < elen)
return mkfailure<bool>("Invalid tinycdb database format, couldn't read entry");
if ((unsigned int)::read(fd, buf, elen) != elen)
return mkfailure<bool>("Couldn't read tinycdb entry");
pos += elen;
// Apply the update function to the entry
debug(string((const char* const)buf, klen), "tinycdb::rewrite::existing key");
debug(string(((const char* const)buf) + klen, vlen), "tinycdb::rewrite::existing value");
const failable<bool> u = update(buf, klen, vlen);
if (!hasContent(u))
return u;
// Skip the entry if the update function returned false
if (u == false)
continue;
// Add the entry to the new db
if (cdb_make_add(&cdbm, buf, klen, ((unsigned char*)buf)+klen, vlen) == -1)
return mkfailure<bool>("Couldn'tt add tinycdb entry");
}
if (pos != eod)
return mkfailure<bool>("Invalid tinycdb database format");
// Call the finish function
const failable<bool> f = finish(cdbm);
if (!hasContent(f))
return f;
// Save the new db
if (cdb_make_finish(&cdbm) == -1)
return mkfailure<bool>("Couldn't save tinycdb database");
return true;
}