Esempio n. 1
0
DFBResult dfb_surfacemanager_deallocate( SurfaceManager *manager,
                                         SurfaceBuffer  *buffer )
{
     int    loops = 0;
     Chunk *chunk = buffer->video.chunk;

     D_ASSERT( buffer->surface );

     D_MAGIC_ASSERT( manager, SurfaceManager );

     if (buffer->video.health == CSH_INVALID)
          return DFB_OK;

     buffer->video.health = CSH_INVALID;
     buffer->video.chunk = NULL;

     dfb_surface_notify_listeners( buffer->surface, CSNF_VIDEO );

     while (buffer->video.locked) {
          if (++loops > 1000)
               break;

          sched_yield();
     }

     if (buffer->video.locked)
          D_WARN( "Freeing chunk with a non-zero lock counter" );

     if (chunk)
          free_chunk( manager, chunk );

     return DFB_OK;
}
Esempio n. 2
0
void free_chunks (struct surface *srf)
{
	int component_index;
	long n_freed;
	char message[MAXLINE];
	struct chunk *head_chunk;
	struct chunk *this_chunk, *next_chunk;
	struct component *cmp_ptr;

	n_freed = 0;
	for (component_index = 0; component_index < srf -> n_component;
		component_index++) {
		cmp_ptr = get_component_ptr (srf, component_index+1);
		if (cmp_ptr == NULL) continue;
		head_chunk = cmp_ptr -> head_chunk;
		next_chunk = NULL;
		for (this_chunk = head_chunk; this_chunk != NULL;
			this_chunk = next_chunk) {
			next_chunk = this_chunk -> next[1];
			free_chunk (this_chunk); n_freed++;
		}	/* end of chunk loop */
	} /* end of component loop */

	sprintf (message,"%8ld chunks freed", n_freed);
	informd(message);
	free_cache (CHUNK);
}
Esempio n. 3
0
/**
 * @brief
 *		dup_chunk - copy constructor for chunk
 *
 * @param[in]	ochunk	-	old chunk structure
 *
 * @return	duplicate chunk structure.
 */
chunk *
dup_chunk(chunk *ochunk)
{
	chunk *nchunk;

	if (ochunk == NULL)
		return NULL;

	nchunk = new_chunk();

	if (nchunk == NULL)
		return NULL;

	nchunk->num_chunks = ochunk->num_chunks;
	nchunk->seq_num = ochunk->seq_num;
	nchunk->str_chunk = string_dup(ochunk->str_chunk);
	nchunk->req = dup_resource_req_list(ochunk->req);

	if (nchunk->req == NULL) {
		free_chunk(nchunk);
		return NULL;
	}

	return nchunk;
}
Esempio n. 4
0
inline static int build_iovec(rpc_ctx_t* ctx, struct iovec* v, int v_size) 
{
	struct text_chunk* p;
	int r_c_len;
	int r;
	
	
	
	/* reason code */
	v[0].iov_base=int2str(ctx->code, &r_c_len);
	v[0].iov_len=r_c_len;
	v[1].iov_base=" ";
	v[1].iov_len=1;
	/* reason txt */
	v[2].iov_base=ctx->reason;
	v[2].iov_len=strlen(ctx->reason);
	v[3].iov_base="\n";
	v[3].iov_len=1;
	r=4;
	/* Send the body */
	while(ctx->body) {
		p = ctx->body;
		ctx->body = ctx->body->next;
		if (p->s.len){
			if (r>=v_size) goto error_overflow;
			v[r].iov_base=p->s.s;
			v[r].iov_len=p->s.len;
			r++;
		}
		if (p->flags & CHUNK_POSITIONAL) {
			if (r>=v_size) goto error_overflow;
			v[r].iov_base="\n";
			v[r].iov_len=1;
			r++;
		} else if (p->flags & CHUNK_MEMBER_NAME) {
			if (r>=v_size) goto error_overflow;
			v[r].iov_base=":";
			v[r].iov_len=1;
			r++;
		} else if (p->flags & CHUNK_MEMBER_VALUE) {
			if (p->next && p->next->flags & CHUNK_MEMBER_NAME) {
				if (r>=MAX_MSG_CHUNKS) goto error_overflow;
				v[r].iov_base=",";
				v[r].iov_len=1;
				r++;
			} else {
				if (r>=v_size) goto error_overflow;
				v[r].iov_base="\n";
				v[r].iov_len=1;
				r++;
			}
		}
		free_chunk(p);
	}
	return r;
error_overflow:
	ERR("too many message chunks, iovec buffer overflow: %d/%d\n", r,
			MAX_MSG_CHUNKS);
	return -1;
}
Esempio n. 5
0
void glue_chunk(heap_t *chunk)
{
	//当释放之后chunk,这段代码检查chunk后面是否有释放的空间
	if (chunk->next && chunk->next->allocate == 0) {
		chunk->length = chunk->length + chunk->next->length;
		if (chunk->next->next) {
			chunk->next->next->prev = chunk;
		}
		chunk->next = chunk->next->next;
	}

	
	//当释放之后chunk,这段代码检查chunk前面是否有释放的空间
	if (chunk->prev && chunk->prev->allocate == 0) {
		chunk->prev->length = chunk->prev->length + chunk->length;
		if (chunk->next) {
			chunk->next->prev = chunk->prev;
		}
		//why
		chunk = chunk->prev;
	}
	
	if (chunk->next == 0) {
		free_chunk(chunk);
	}
}
Esempio n. 6
0
void glue_chunk(header_t * chunk){
  //glue together closed unused chunks
  //next
  if(chunk->next && chunk->next->allocated == 0){
    //printk("Glue Called\n");
    chunk->length = chunk->length + chunk->next->length;
    if(chunk->next->next){
      chunk->next->next->prev = chunk;
    }
    chunk->next = chunk->next->next;
  }
  //previous
  if(chunk->prev && chunk->prev->allocated == 0){
    //printk("Glue Called\n");
    chunk->prev->length = chunk->prev->length + chunk->length;
    chunk->prev->next = chunk->next;

    if(chunk->next){
      chunk->next->prev = chunk->prev;
    }
    chunk = chunk->prev;
  }

  if(chunk->next == 0){
    //printk("Glue Called and Unmap called\n");
    free_chunk(chunk);
  }
}
/* Free shared data: */
void unloadshared(void)
{
  int i;

  free_special_gfx();
  free_badguy_gfx();

  delete img_water;
  for (i = 0; i < 3; i++)
    delete img_waves[i];

  delete img_pole;
  delete img_poletop;

  for (i = 0; i < 2; i++)
    delete img_flag[i];

  for (i = 0; i < 4; i++)
    {
      delete img_distro[i];
      delete img_cloud[0][i];
      delete img_cloud[1][i];
    }

  delete tux_life;

  for (i = 0; i < NUM_SOUNDS; i++)
    free_chunk(sounds[i]);

  delete sprite_manager;
  sprite_manager = 0;
  delete music_manager;
  music_manager = 0;
}
Esempio n. 8
0
void glue_chunk(header_t *chunk)
{
	// 如果该内存块后面有链内存块且未被使用则拼合
	if (chunk->next && chunk->next->allocated == 0) {
		chunk->length = chunk->length + chunk->next->length;
		if (chunk->next->next) {
			chunk->next->next->prev = chunk;
		}
		chunk->next = chunk->next->next;
	}

	// 如果该内存块前面有链内存块且未被使用则拼合
	if (chunk->prev && chunk->prev->allocated == 0) {
		chunk->prev->length = chunk->prev->length + chunk->length;
		chunk->prev->next = chunk->next;
		if (chunk->next) {
			chunk->next->prev = chunk->prev;
		}
		chunk = chunk->prev;
	}

	// 假如该内存后面没有链表内存块了直接释放掉
	if (chunk->next == 0) {
		free_chunk(chunk);
	}
}
Esempio n. 9
0
void __for_each_chunk(nbt_node* node, void* context) {
    struct __for_each_chunk_struct* data = context;
    chunk* c = nbt_to_chunk(node, 0);
    if (c) {
        data->function(c, data->context);
        free_chunk(c);
    }
};
Esempio n. 10
0
static
void
empty_chunk_queue(chunk_list_t *l)
{
	while (l->begin() != l->end()) {
		free_chunk(*l->begin());
		l->erase(l->begin());
	}
}
Esempio n. 11
0
File: keys.c Progetto: jubalh/vifm
static void
free_tree(key_chunk_t *root)
{
	if(root->child != NULL)
	{
		free_tree(root->child);
		free_chunk(root->child);
	}

	if(root->next != NULL)
	{
		free_tree(root->next);
		free_chunk(root->next);
	}

	if(root->conf.type == USER_CMD || root->conf.type == BUILTIN_CMD)
		free(root->conf.data.cmd);
}
Esempio n. 12
0
	webpage_retriever::~webpage_retriever()
	{
		free_chunk();

		/* cleanup curl stuff */
		curl_easy_cleanup(curl_handle);

		/* we're done with libcurl, so clean it up */
		curl_global_cleanup();
	}
Esempio n. 13
0
static void free_struct(struct rpc_struct* s)
{
	struct text_chunk* c;

	if (!s) return;
	while(s->names) {
		c = s->names;
		s->names = s->names->next;
		free_chunk(c);
	}

	while(s->values) {
		c = s->values;
		s->values = s->values->next;
		free_chunk(c);
	}

	ctl_free(s);
}
Esempio n. 14
0
static void* lru_restore_thread(void *arg) {
	struct lruCache *cache;
	if (destor.simulation_level >= SIMULATION_RESTORE)
		cache = new_lru_cache(destor.restore_cache[1], free_container_meta,
				lookup_fingerprint_in_container_meta);
	else
		cache = new_lru_cache(destor.restore_cache[1], free_container,
				lookup_fingerprint_in_container);

	struct chunk* c;
	while ((c = sync_queue_pop(restore_recipe_queue))) {

		if (CHECK_CHUNK(c, CHUNK_FILE_START) || CHECK_CHUNK(c, CHUNK_FILE_END)) {
			sync_queue_push(restore_chunk_queue, c);
			continue;
		}

		TIMER_DECLARE(1);
		TIMER_BEGIN(1);

		if (destor.simulation_level >= SIMULATION_RESTORE) {
			struct containerMeta *cm = lru_cache_lookup(cache, &c->fp);
			if (!cm) {
				VERBOSE("Restore cache: container %lld is missed", c->id);
				cm = retrieve_container_meta_by_id(c->id);
				assert(lookup_fingerprint_in_container_meta(cm, &c->fp));
				lru_cache_insert(cache, cm, NULL, NULL);
				jcr.read_container_num++;
			}

			TIMER_END(1, jcr.read_chunk_time);
		} else {
			struct container *con = lru_cache_lookup(cache, &c->fp);
			if (!con) {
				VERBOSE("Restore cache: container %lld is missed", c->id);
				con = retrieve_container_by_id(c->id);
				lru_cache_insert(cache, con, NULL, NULL);
				jcr.read_container_num++;
			}
			struct chunk *rc = get_chunk_in_container(con, &c->fp);
			assert(rc);
			TIMER_END(1, jcr.read_chunk_time);
			sync_queue_push(restore_chunk_queue, rc);
		}

		free_chunk(c);
	}

	sync_queue_term(restore_chunk_queue);

	free_lru_cache(cache);

	return NULL;
}
Esempio n. 15
0
static void
heap_morecore(pic_state *pic)
{
  union header *bp, *np;
  struct heap_page *page;

  assert(PAGE_UNITS >= 2);

  page = pic_malloc(pic, PIC_HEAP_PAGE_SIZE);
  page->next = pic->heap->pages;

  bp = page->u.basep;
  bp->s.size = 0;      /* bp is never used for allocation */
  free_chunk(pic, bp);

  np = page->u.basep + 1;
  np->s.size = PAGE_UNITS - 1;
  free_chunk(pic, np);

  pic->heap->pages = page;
}
Esempio n. 16
0
/**
 * @brief
 *		free_chunk_array - array destructor for array of chunk ptrs
 *
 * @param[in,out]	chunk_arr	-	old array of chunk pointers
 *
 * @return	void
 */
void
free_chunk_array(chunk **chunk_arr)
{
	int i;

	if (chunk_arr == NULL)
		return;

	for (i = 0; chunk_arr[i] != NULL; i++)
		free_chunk(chunk_arr[i]);

	free(chunk_arr);
}
Esempio n. 17
0
void
lwan_tpl_free(lwan_tpl_t *tpl)
{
    if (!tpl)
        return;
    
    while (tpl->chunks) {
        lwan_tpl_chunk_t *next = tpl->chunks->next;
        free_chunk(tpl->chunks);
        tpl->chunks = next;
    }
    free(tpl);
}
Esempio n. 18
0
//Before running run: "ulimit -s unlimited"
int main(int argc, char* argv[]) {
    parse_opts(argc, argv);

    srand(time(NULL)); 
    int tick = 0;
    struct list **chunks_lifetime = (struct list **)malloc(sizeof(struct list*) * max_ticks);// The stack memory has somee restrictions
    for (int i = 0; i < max_ticks; i++) {
        chunks_lifetime[i] = create_list();
    }

    struct memory *mem = create_memory(memory_size);
    printf("Starting\n"); 
    while (1) {
        if (need_trace) {
            printf("Tick %d:\n", tick);
        }
        while (!is_list_empty(chunks_lifetime[tick])) {
            int8_t *ptr = get_and_remove(chunks_lifetime[tick]);
            if (need_trace) {
                printf("   Removing chunk with size %d bytes\n", get_chunk_size(ptr));
            }
            free_chunk(mem, ptr);
        }
        SIZE_TYPE chunk_size = rand_range(min_chunk_size, max_chunk_size) / 4 * 4;
        int8_t *ptr = allocate_chunk(mem, chunk_size);

        if (ptr == NULL) {
            printf("Oops. We have no free memory to allocate %d bytes on tick %d. Exiting\n", chunk_size, tick);
            break;
        }
        int chunk_lifetime = rand_range(min_lifetime, max_lifetime);
        if (tick + chunk_lifetime >= max_ticks) {
            printf("The maximum number of ticks(%d) reached. Exiting\n", max_ticks);
            break;
        }
        
        add_to_list(chunks_lifetime[tick + chunk_lifetime], ptr);
        if (need_trace){
            printf("   Allocating chunk with size %d bytes. Its lifetime is %d ticks\n", chunk_size, chunk_lifetime);
        }
        tick++;
    }

    for (int i = 0; i < max_ticks; i++) {
        free_list(chunks_lifetime[i]);
    }
    free_memory(mem);
    free(chunks_lifetime);
    return 0;
}
Esempio n. 19
0
void free_segment(struct segment* s) {
	GSequenceIter *begin = g_sequence_get_begin_iter(s->chunks);
	GSequenceIter *end = g_sequence_get_end_iter(s->chunks);
	for(; begin != end; begin = g_sequence_get_begin_iter(s->chunks)){
		free_chunk(g_sequence_get(begin));
		g_sequence_remove(begin);
	}
	g_sequence_free(s->chunks);

	if (s->features)
		g_hash_table_destroy(s->features);

	free(s);
}
Esempio n. 20
0
void glue_chunk(kheader_t *chunk) {
	if (chunk->next && chunk->next->allocated == 0) {
		chunk->length = chunk->length + chunk->next->length;
		chunk->next->next->prev = chunk;
		chunk->next = chunk->next->next;
	}
	if (chunk->prev && chunk->prev->allocated == 0) {
		chunk->prev->length = chunk->prev->length + chunk->length;
		chunk->prev->next = chunk->next;
		chunk->next->prev = chunk->prev;
		chunk = chunk->prev;
	}
	if (chunk->next == 0)
		free_chunk(chunk);
}
Esempio n. 21
0
void make_trace(char* path) {
	init_jcr(path);

	sds trace_file = sdsnew(path);

	char *p = trace_file + sdslen(trace_file) - 1;
	while (*p == '/')
		--p;
	*(p + 1) = 0;
	sdsupdatelen(trace_file);

	trace_file = sdscat(trace_file, ".trace");
	NOTICE("output to %s", trace_file);

	start_read_phase();
	start_chunk_phase();
	start_hash_phase();

	unsigned char code[41];

	FILE *fp = fopen(trace_file, "w");
	while (1) {
		struct chunk *c = sync_queue_pop(hash_queue);

		if (c == NULL) {
			break;
		}

		if (CHECK_CHUNK(c, CHUNK_FILE_START)) {
			destor_log(DESTOR_NOTICE, c->data);
			fprintf(fp, "file start %zd\n", strlen(c->data));
			fprintf(fp, "%s\n", c->data);

		} else if (CHECK_CHUNK(c, CHUNK_FILE_END)) {
			fprintf(fp, "file end\n");
		} else {
			hash2code(c->fp, code);
			code[40] = 0;
			fprintf(fp, "%s %d\n", code, c->size);
		}
		free_chunk(c);
	}

	fprintf(fp, "stream end");
	fclose(fp);

}
Esempio n. 22
0
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
{
	struct block_header *header;
	struct free_block* free_block;

	allocator_grab_lock();
	header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header));
	allocated_size -= header->size;

	/* Connecting free blocks together if possible. */

	/* If header->prev_size == 0, free_block will equal to header.
	   In this case, free_block->header.size will be > 0. */
	free_block = AS_FREE_BLOCK(header, -(sljit_sw)header->prev_size);
	if (SLJIT_UNLIKELY(!free_block->header.size)) {
		free_block->size += header->size;
		header = AS_BLOCK_HEADER(free_block, free_block->size);
		header->prev_size = free_block->size;
	}
	else {
		free_block = (struct free_block*)header;
		sljit_insert_free_block(free_block, header->size);
	}

	header = AS_BLOCK_HEADER(free_block, free_block->size);
	if (SLJIT_UNLIKELY(!header->size)) {
		free_block->size += ((struct free_block*)header)->size;
		sljit_remove_free_block((struct free_block*)header);
		header = AS_BLOCK_HEADER(free_block, free_block->size);
		header->prev_size = free_block->size;
	}

	/* The whole chunk is free. */
	if (SLJIT_UNLIKELY(!free_block->header.prev_size && header->size == 1)) {
		/* If this block is freed, we still have (allocated_size / 2) free space. */
		if (total_size - free_block->size > (allocated_size * 3 / 2)) {
			total_size -= free_block->size;
			sljit_remove_free_block(free_block);
			free_chunk(free_block, free_block->size + sizeof(struct block_header));
		}
	}

	allocator_release_lock();
}
Esempio n. 23
0
static size_t
gc_sweep_page(pic_state *pic, struct heap_page *page)
{
  union header *bp, *p, *head = NULL, *tail = NULL;
  struct object *obj;
  size_t alive = 0, nunits;

  for (bp = page->u.basep; ; bp = bp->s.ptr) {
    p = bp + (bp->s.size ? bp->s.size : 1); /* first bp's size is 0, so force advnce */
    while (p != bp->s.ptr) {
      if (p < page->u.basep || page->u.basep + PAGE_UNITS <= p) {
        goto escape;
      }
      obj = (struct object *) p;
      nunits = unitsof(obj_type(pic, obj));
      if (obj->u.basic.tt & GC_MARK) {
        obj->u.basic.tt &= ~GC_MARK;
        alive += nunits;
      } else {
        gc_finalize_object(pic, obj);
        if (head == NULL) {
          head = p;
        }
        if (tail != NULL) {
          tail->s.ptr = p;
        }
        tail = p;
        tail->s.size = nunits;
        tail->s.ptr = NULL; /* We can safely reuse ptr field of dead object */
      }
      p += nunits;
    }
  }
 escape:

  /* free! */
  while (head != NULL) {
    p = head;
    head = head->s.ptr;
    free_chunk(pic, p);
  }

  return alive;
}
Esempio n. 24
0
File: keys.c Progetto: jubalh/vifm
int
remove_user_keys(const wchar_t *keys, int mode)
{
	key_chunk_t *curr, *p;

	if((curr = find_user_keys(keys, mode)) == NULL)
		return -1;

	free(curr->conf.data.cmd);
	curr->conf.type = BUILTIN_WAIT_POINT;
	curr->conf.data.handler = NULL;

	p = curr;
	while(p->parent != NULL)
	{
		p->parent->children_count--;
		p = p->parent;
	}

	if(curr->children_count > 0)
		return 0;

	do
	{
		key_chunk_t *const parent = curr->parent;
		if(curr->prev != NULL)
			curr->prev->next = curr->next;
		else
			parent->child = curr->next;
		if(curr->next != NULL)
			curr->next->prev = curr->prev;
		free_chunk(curr);
		curr = parent;
	}
	while(curr->parent != NULL && curr->parent->conf.data.handler == NULL &&
			curr->parent->conf.type == BUILTIN_WAIT_POINT &&
			curr->parent->children_count == 0);

	return 0;
}
Esempio n. 25
0
	char *webpage_retriever::retrieve(const char *url, int *response_code)
	{
		free_chunk();

	  /* specify URL to get */
	  curl_easy_setopt(curl_handle, CURLOPT_URL, url);

	  /* get it! */
	  curl_easy_perform(curl_handle);
	  curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, response_code);
	  /*
	   * Now, our chunk.memory points to a memory block that is chunk.size
	   * bytes big and contains the remote file.
	   *
	   * Do something nice with it!
	   *
	   * You should be aware of the fact that at this point we might have an
	   * allocated data block, and nothing has yet deallocated that data. So when
	   * you're done with it, you should free() it as a nice application.
	   */
	  return chunk.memory;
	}
Esempio n. 26
0
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
{
	struct free_block* free_block;
	struct free_block* next_free_block;

	allocator_grab_lock();

	free_block = free_blocks;
	while (free_block) {
		next_free_block = free_block->next;
		if (!free_block->header.prev_size && 
				AS_BLOCK_HEADER(free_block, free_block->size)->size == 1) {
			total_size -= free_block->size;
			sljit_remove_free_block(free_block);
			free_chunk(free_block, free_block->size + sizeof(struct block_header));
		}
		free_block = next_free_block;
	}

	SLJIT_ASSERT((total_size && free_blocks) || (!total_size && !free_blocks));
	allocator_release_lock();
}
Esempio n. 27
0
static void glue_chunk(heap_header_t *chunk)
{
	if (chunk->next && chunk->next->allocated == 0) {
		chunk->length += chunk->next->length;
		if (chunk->next->next) {
			chunk->next->next->prev = chunk;
		}
		chunk->next = chunk->next->next;
	}

	if (chunk->prev && chunk->prev->allocated == 0) {
		chunk->prev->length += chunk->length;
		chunk->prev->next = chunk->next;
		if (chunk->next) {
			chunk->next->prev = chunk->prev;
		}
		chunk = chunk->prev;
	}

	if (chunk->next == 0) {
		free_chunk(chunk);
	}
}
Esempio n. 28
0
File: heap.c Progetto: Morainy/AOS
void glue_chunk(header_t *chunk)
{
	//如果内存块前后有内存块且未被使用则拼合
	if(chunk->next && chunk->next->allocated == 0){
		chunk->length = chunk->length + chunk->next->length;
		if(chunk->next->next){
			chunk->next->next->prev = chunk;
		}
		chunk->next = chunk->next->next;
	}
	if(chunk->prev && chunk->prev->allocated == 0){
		chunk->prev->length = chunk->prev->length + chunk->length;
		chunk->prev->next = chunk->next;
		if(chunk->next){
			chunk->next->prev = chunk->prev;
		}
		chunk = chunk->prev;
	}

	//假设内存块后面没有链表内存块   则直接释放
	if(chunk->next == 0){
		free_chunk(chunk);
	}
}
Esempio n. 29
0
/*
 * Invoked from our compress helper thread, when logging would have exceeded
 * the specified memory limitation. Compresses the previously stored
 * entries.
 */
static int gz_work(struct tp_work *work)
{
	struct iolog_flush_data *data;
	struct iolog_compress *c;
	struct flist_head list;
	unsigned int seq;
	z_stream stream;
	size_t total = 0;
	int ret;

	INIT_FLIST_HEAD(&list);

	data = container_of(work, struct iolog_flush_data, work);

	stream.zalloc = Z_NULL;
	stream.zfree = Z_NULL;
	stream.opaque = Z_NULL;

	ret = deflateInit(&stream, Z_DEFAULT_COMPRESSION);
	if (ret != Z_OK) {
		log_err("fio: failed to init gz stream\n");
		return 0;
	}

	seq = ++data->log->chunk_seq;

	stream.next_in = (void *) data->samples;
	stream.avail_in = data->nr_samples * log_entry_sz(data->log);

	dprint(FD_COMPRESS, "deflate input size=%lu, seq=%u\n",
				(unsigned long) stream.avail_in, seq);
	do {
		c = get_new_chunk(seq);
		stream.avail_out = GZ_CHUNK;
		stream.next_out = c->buf;
		ret = deflate(&stream, Z_NO_FLUSH);
		if (ret < 0) {
			log_err("fio: deflate log (%d)\n", ret);
			free_chunk(c);
			goto err;
		}

		c->len = GZ_CHUNK - stream.avail_out;
		flist_add_tail(&c->list, &list);
		total += c->len;
	} while (stream.avail_in);

	stream.next_out = c->buf + c->len;
	stream.avail_out = GZ_CHUNK - c->len;

	ret = deflate(&stream, Z_FINISH);
	if (ret == Z_STREAM_END)
		c->len = GZ_CHUNK - stream.avail_out;
	else {
		do {
			c = get_new_chunk(seq);
			stream.avail_out = GZ_CHUNK;
			stream.next_out = c->buf;
			ret = deflate(&stream, Z_FINISH);
			c->len = GZ_CHUNK - stream.avail_out;
			total += c->len;
			flist_add_tail(&c->list, &list);
		} while (ret != Z_STREAM_END);
	}

	dprint(FD_COMPRESS, "deflated to size=%lu\n", (unsigned long) total);

	ret = deflateEnd(&stream);
	if (ret != Z_OK)
		log_err("fio: deflateEnd %d\n", ret);

	free(data->samples);

	if (!flist_empty(&list)) {
		pthread_mutex_lock(&data->log->chunk_lock);
		flist_splice_tail(&list, &data->log->chunk_list);
		pthread_mutex_unlock(&data->log->chunk_lock);
	}

	ret = 0;
done:
	if (work->wait) {
		work->done = 1;
		pthread_cond_signal(&work->cv);
	} else
		free(data);

	return ret;
err:
	while (!flist_empty(&list)) {
		c = flist_first_entry(list.next, struct iolog_compress, list);
		flist_del(&c->list);
		free_chunk(c);
	}
	ret = 1;
	goto done;
}
Esempio n. 30
0
/*
 * Inflate stored compressed chunks, or write them directly to the log
 * file if so instructed.
 */
static int inflate_gz_chunks(struct io_log *log, FILE *f)
{
	struct inflate_chunk_iter iter = { .chunk_sz = log->log_gz, };
	z_stream stream;

	while (!flist_empty(&log->chunk_list)) {
		struct iolog_compress *ic;

		ic = flist_first_entry(&log->chunk_list, struct iolog_compress, list);
		flist_del(&ic->list);

		if (log->log_gz_store) {
			size_t ret;

			dprint(FD_COMPRESS, "log write chunk size=%lu, "
				"seq=%u\n", (unsigned long) ic->len, ic->seq);

			ret = fwrite(ic->buf, ic->len, 1, f);
			if (ret != 1 || ferror(f)) {
				iter.err = errno;
				log_err("fio: error writing compressed log\n");
			}
		} else
			inflate_chunk(ic, log->log_gz_store, f, &stream, &iter);

		free_chunk(ic);
	}

	if (iter.seq) {
		finish_chunk(&stream, f, &iter);
		free(iter.buf);
	}

	return iter.err;
}

/*
 * Open compressed log file and decompress the stored chunks and
 * write them to stdout. The chunks are stored sequentially in the
 * file, so we iterate over them and do them one-by-one.
 */
int iolog_file_inflate(const char *file)
{
	struct inflate_chunk_iter iter = { .chunk_sz = 64 * 1024 * 1024, };
	struct iolog_compress ic;
	z_stream stream;
	struct stat sb;
	ssize_t ret;
	size_t total;
	void *buf;
	FILE *f;

	f = fopen(file, "r");
	if (!f) {
		perror("fopen");
		return 1;
	}

	if (stat(file, &sb) < 0) {
		fclose(f);
		perror("stat");
		return 1;
	}

	ic.buf = buf = malloc(sb.st_size);
	ic.len = sb.st_size;
	ic.seq = 1;

	ret = fread(ic.buf, ic.len, 1, f);
	if (ret < 0) {
		perror("fread");
		fclose(f);
		return 1;
	} else if (ret != 1) {
		log_err("fio: short read on reading log\n");
		fclose(f);
		return 1;
	}

	fclose(f);

	/*
	 * Each chunk will return Z_STREAM_END. We don't know how many
	 * chunks are in the file, so we just keep looping and incrementing
	 * the sequence number until we have consumed the whole compressed
	 * file.
	 */
	total = ic.len;
	do {
		size_t ret;

		ret = inflate_chunk(&ic,  1, stdout, &stream, &iter);
		total -= ret;
		if (!total)
			break;
		if (iter.err)
			break;

		ic.seq++;
		ic.len -= ret;
		ic.buf += ret;
	} while (1);

	if (iter.seq) {
		finish_chunk(&stream, stdout, &iter);
		free(iter.buf);
	}

	free(buf);
	return iter.err;
}

#else

static int inflate_gz_chunks(struct io_log *log, FILE *f)
{
	return 0;
}

int iolog_file_inflate(const char *file)
{
	log_err("fio: log inflation not possible without zlib\n");
	return 1;
}

#endif

void flush_log(struct io_log *log)
{
	void *buf;
	FILE *f;

	f = fopen(log->filename, "w");
	if (!f) {
		perror("fopen log");
		return;
	}

	buf = set_file_buffer(f);

	inflate_gz_chunks(log, f);

	flush_samples(f, log->log, log->nr_samples * log_entry_sz(log));

	fclose(f);
	clear_file_buffer(buf);
}