BOOL FileManager::seek(off_t offset) { if (!_compressed) { _file->seek(offset); _stream->avail_in = 0; return TRUE; } /* if seek backwards, simply start from the beginning */ if (offset < _stream->total_out) { _file->seek(0); inflateEnd(_stream); _reset(); /* this resets total_out to 0! */ inflateInit2(_stream, -15); _stream->next_in = _inbuf; _check_header(); /* skip the .gz header */ } /* to seek forwards, throw away data */ if (offset > _stream->total_out) { off_t toskip = offset - _stream->total_out; size_t skipped = _skip_compressed(toskip); if (skipped != toskip) return FALSE; } return TRUE; }
/** * fast version of write the database * * @param d database handle */ void fast_writedb(struct db *d) { // when you create a new database, // you don't know the size of it, // so we can't write all stuffs once // what we could make it fast is, // not free the list, left it to OS FILE *f = NULL; if ((f = fopen(d->fname, "wb")) == NULL) { hooks.log("failed to open file %s!\n", d->fname); return ; } // simple safety check if(!d) if ( _check_header(&(d->hdr))) { hooks.log("invalid databse!\n"); fclose(f); return ; } // first write header fwrite(&(d->hdr), sizeof(struct db_header), 1, f); // write content struct db_node *curr = d->head; int i = 0; int num = d->hdr.num; for(; i < num; ++i) { if (curr == NULL ) break; fwrite(curr->data, sizeof(char)*(d->hdr.len), 1, f); curr = curr->next; } if (i != num) { hooks.log("unexpected error happens!\n"); } fclose(f); // no memory free here, leave it to OS }
BOOL FileManager::open(const TCHAR *name, uint32_t flags) { if (!_file->open(name, flags)) return FALSE; _reset(); if (inflateInit2(_stream, -15) != Z_OK) goto errout; _stream->next_in = _inbuf; _check_header(); // skip the .gz header return TRUE; errout: _file->close(); return FALSE; }
/** * write data base into disk * * @param d database handle */ void writedb(struct db *d) { FILE *f = NULL; if ((f = fopen(d->fname, "wb")) == NULL) { hooks.log("failed to open file %s!\n", d->fname); return ; } // simple safety check if(d) if ( _check_header(&(d->hdr))) { hooks.log("invalid databse!\n"); fclose(f); return ; } // first write header fwrite(&(d->hdr), sizeof(struct db_header), 1, f); // write content struct db_node *curr = d->head; int i = 0; int num = d->hdr.num; for(; i < num; ++i) { if (curr == NULL ) break; fwrite(curr->data, sizeof(char)*(d->hdr.len), 1, f); curr = curr->next; } if (i != num) { hooks.log("unexpected error happens!\n"); } fclose(f); _free_db(d); }
/** * fast version of open database * * @param fname * * @return */ struct db* fast_opendb(const char* fname) { // get the header FILE *f; struct db *d = NULL; if ((f = fopen(fname, "r")) == NULL) { hooks.log("can not open file %s!\n", fname); return NULL; } d = (struct db*)hooks.malloc(sizeof(struct db)); strncpy(d->fname, fname, DB_NAME_LEN-1); d->head = NULL; d->tail = NULL; d->curr = NULL; d->hdr.len = 0; d->hdr.magic = 0; d->hdr.num = 0; d->hdr.reserved = 0; // constuct database handle if (0 == fread(&(d->hdr), sizeof(struct db_header), 1, f)) { hooks.log("invalid database file!\n"); hooks.free(d); d = NULL; } if (d) if ( _check_header(&(d->hdr)) ) { hooks.log("invalid databse header!\n"); hooks.free(d); d = NULL; } // because the len of every node is fixed, we could // read all nodes' data once, and link them to a list if (d) { int len_total = d->hdr.num * d->hdr.len; // for all nodes int node_total = d->hdr.num * sizeof(struct db_node); void *nodes = hooks.malloc(node_total); void *chunk = hooks.malloc(len_total); if (chunk == NULL || nodes == NULL) { hooks.log("insufficient memory!\n"); hooks.exit(-1); } // read all data at once fread(chunk, len_total, 1, f); // constuct database linked list int cnt = d->hdr.num; int len = d->hdr.len; // init every node struct db_node *curr = (struct db_node*)nodes; int i = 0; for(; i < cnt-1; ++i) { curr->len = len; curr->data = NULL; curr->next = (curr + 1); curr = curr->next; } d->head = (struct db_node*)nodes; d->tail = curr; curr->len = len; curr->data = NULL; curr->next = NULL; d->curr = NULL; curr = d->head; void *data_head = chunk; for(i = 0; i < cnt; ++i) { if (curr == NULL) break; curr->data = data_head; curr = curr->next; data_head = (unsigned char*)data_head + len; } curr = NULL; data_head = NULL; } return d; }
/** * open an exist database with its name * * @param fname name of database * * @return opened database handle */ struct db* opendb(const char *fname) { FILE *f; struct db *d = NULL; if ((f = fopen(fname, "r")) == NULL) { hooks.log("can not open file %s!\n", fname); return NULL; } d = (struct db*)hooks.malloc(sizeof(struct db)); strncpy(d->fname, fname, DB_NAME_LEN-1); d->head = NULL; d->tail = NULL; d->curr = NULL; d->hdr.len = 0; d->hdr.magic = 0; d->hdr.num = 0; d->hdr.reserved = 0; // constuct database handle if (0 == fread(&(d->hdr), sizeof(struct db_header), 1, f)) { hooks.log("invalid database file!\n"); hooks.free(d); d = NULL; } if (d) if ( _check_header(&(d->hdr)) ) { hooks.log("invalid databse header!\n"); hooks.free(d); d = NULL; } if (d) { // construct node list int cnt = d->hdr.num; while(!feof(f) && cnt > 0) { struct db_node *n = new_node(d->hdr.len); fread(n->data, sizeof(char)*(d->hdr.len), 1, f); dump(d, n);d->hdr.num--; --cnt; } if (cnt != 0) { hooks.log("unexpected file end!\n"); hooks.free(d); d = NULL; } } fclose(f); return d; }
size_t FileManager::_read(void *buf, size_t len) { // starting point for crc computation uint8_t *start = reinterpret_cast<uint8_t *>(buf); if (_z_err == Z_DATA_ERROR || _z_err == Z_ERRNO) { return -1; } if (_z_err == Z_STREAM_END) { return 0; // EOF } _stream->next_out = reinterpret_cast<uint8_t *>(buf); _stream->avail_out = len; int got; while (_stream->avail_out != 0) { if (!_compressed) { // Copy first the lookahead bytes uint32_t n = _stream->avail_in; if (n > _stream->avail_out) n = _stream->avail_out; if (n > 0) { memcpy(_stream->next_out, _stream->next_in, n); _stream->next_out += n; _stream->next_in += n; _stream->avail_out -= n; _stream->avail_in -= n; } if (_stream->avail_out > 0) { got = _file->read(_stream->next_out, _stream->avail_out); if (got == -1) { return(got); } _stream->avail_out -= got; } return(int)(len - _stream->avail_out); } if (_stream->avail_in == 0 && !_z_eof) { got = _file->read(_inbuf, Z_BUFSIZE); if (got <= 0) _z_eof = 1; _stream->avail_in = got; _stream->next_in = _inbuf; } _z_err = inflate(_stream, Z_NO_FLUSH); if (_z_err == Z_STREAM_END) { /* Check CRC and original size */ _crc = crc32(_crc, start,(unsigned int) (_stream->next_out - start)); start = _stream->next_out; if (_get_long() != _crc || _get_long() != _stream->total_out) { _z_err = Z_DATA_ERROR; } else { /* Check for concatenated .gz files: */ _check_header(); if (_z_err == Z_OK) { inflateReset(_stream); _crc = crc32(0L, Z_NULL, 0); } } } if (_z_err != Z_OK || _z_eof) break; } _crc = crc32(_crc, start,(unsigned int)(_stream->next_out - start)); return(int)(len - _stream->avail_out); }