diff --git a/lrzip_private.h b/lrzip_private.h index c7e5d49..7197747 100644 --- a/lrzip_private.h +++ b/lrzip_private.h @@ -351,8 +351,15 @@ struct checksum { typedef i64 tag; +struct node { + void *data; + struct node *prev; +}; + struct rzip_state { void *ss; + struct node *sslist; + struct node *head; struct level *level; tag hash_index[256]; struct hash_entry *hash_table; @@ -444,10 +451,6 @@ struct rzip_control { const char *util_infile; char delete_infile; const char *util_outfile; -#define STREAM_BUCKET_SIZE 20 - size_t sinfo_buckets; - size_t sinfo_idx; - struct stream_info **sinfo_queue; char delete_outfile; FILE *outputfile; char library_mode; diff --git a/rzip.c b/rzip.c index 25d134b..732d498 100644 --- a/rzip.c +++ b/rzip.c @@ -872,6 +872,17 @@ init_sliding_mmap(rzip_control *control, struct rzip_state *st, int fd_in, sb->fd = fd_in; } +static void add_to_sslist(rzip_control *control, struct rzip_state *st) +{ + struct node *node = calloc(sizeof(struct node), 1); + + if (unlikely(!node)) + failure("Failed to calloc struct node in add_to_sslist\n"); + node->data = st->ss; + node->prev = st->sslist; + st->head = node; +} + /* compress a chunk of an open file. Assumes that the file is able to be mmap'd and is seekable */ static inline void @@ -903,6 +914,23 @@ rzip_chunk(rzip_control *control, struct rzip_state *st, int fd_in, int fd_out, if (unlikely(close_stream_out(control, st->ss))) failure("Failed to flush/close streams in rzip_chunk\n"); + + /* Save the sinfo data to a list to be safely released after all + * threads have been shut down. */ + add_to_sslist(control, st); +} + +static void clear_sslist(struct rzip_state *st) +{ + while (st->head) { + struct node *node = st->head; + struct stream_info *sinfo = node->data; + + dealloc(sinfo->s); + dealloc(sinfo); + st->head = node->prev; + dealloc(node); + } } /* compress a whole file chunks at a time */ @@ -1225,12 +1253,12 @@ retry: print_progress("Compression Ratio: %.3f. Average Compression Speed: %6.3fMB/s.\n", 1.0 * s.st_size / s2.st_size, chunkmbs); + clear_sslist(st); dealloc(st); } void rzip_control_free(rzip_control *control) { - size_t x; if (!control) return; @@ -1240,10 +1268,5 @@ void rzip_control_free(rzip_control *control) if (control->suffix && control->suffix[0]) dealloc(control->suffix); - for (x = 0; x < control->sinfo_idx; x++) { - dealloc(control->sinfo_queue[x]->s); - dealloc(control->sinfo_queue[x]); - } - dealloc(control->sinfo_queue); dealloc(control); } diff --git a/stream.c b/stream.c index 407c550..4ca6db0 100644 --- a/stream.c +++ b/stream.c @@ -1812,37 +1812,12 @@ int close_stream_out(rzip_control *control, void *ss) for (i = 0; i < sinfo->num_streams; i++) rewrite_encrypted(control, sinfo, sinfo->s[i].last_headofs); } - if (control->library_mode) { - if (!control->sinfo_buckets) { - /* no streams added */ - control->sinfo_queue = calloc(STREAM_BUCKET_SIZE + 1, sizeof(void*)); - if (!control->sinfo_queue) { - print_err("Failed to calloc sinfo_queue in close_stream_out\n"); - return -1; - } - control->sinfo_buckets++; - } else if (control->sinfo_idx == STREAM_BUCKET_SIZE * control->sinfo_buckets + 1) { - /* all buckets full, create new bucket */ - void *tmp; - tmp = realloc(control->sinfo_queue, (++control->sinfo_buckets * STREAM_BUCKET_SIZE + 1) * sizeof(void*)); - if (!tmp) { - print_err("Failed to realloc sinfo_queue in close_stream_out\n"); - return -1; - } - control->sinfo_queue = tmp; - memset(control->sinfo_queue + control->sinfo_idx, 0, ((control->sinfo_buckets * STREAM_BUCKET_SIZE + 1) - control->sinfo_idx) * sizeof(void*)); - } - control->sinfo_queue[control->sinfo_idx++] = sinfo; - } -#if 0 - /* These cannot be freed immediately because their values are read after the next - * stream has started. Instead (in library mode), they are stored and only freed - * after the entire operation has completed. + /* Note that sinfo->s and sinfo are not released here but after compression + * has completed as they cannot be freed immediately because their values + * are read after the next stream has started. */ - dealloc(sinfo->s); - dealloc(sinfo); -#endif + return 0; }