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;
}
Пример #2
0
/** 
 * 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;
}
Пример #4
0
/** 
 * 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);
}
Пример #5
0
/** 
 * 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;
}
Пример #6
0
/** 
 * 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);
}