mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
Reduces memory usage, with new array growing by fixed size and not exponential.
This commit is contained in:
parent
7f02cd068f
commit
d525b4a14a
18 changed files with 497 additions and 53 deletions
13
HISTORY
13
HISTORY
|
|
@ -1,21 +1,22 @@
|
|||
SnapRAID HISTORY
|
||||
================
|
||||
|
||||
5.0 2013/9 (BETA)
|
||||
=================
|
||||
* Adds support for RAIDTP (Triple Parity) and RAIDQP (Quad Parity).
|
||||
5.0 2013/10
|
||||
===========
|
||||
* Added support for RAIDTP (Triple Parity) and RAIDQP (Quad Parity).
|
||||
For Quad Parity, and only for Quad Parity, there is a limitation of
|
||||
using no more than 21 data disks. This is a conseguence of the
|
||||
high performant parity generator matrix used. An extension supporting
|
||||
up to 89 disks with Hexa (6) parity is possible, but not yet implemented.
|
||||
Note that more general approaches without these limitations are also
|
||||
possible, but they would affect badly the performance.
|
||||
* Reduced memory usage avoiding to allocate unnecessary memory.
|
||||
|
||||
4.1 2013/9 (BETA)
|
||||
=================
|
||||
4.1 2013/9
|
||||
==========
|
||||
* If the underline filesystem doesn't support the FIEMAP command,
|
||||
automatically fallback to use FIBMAP for sorting files.
|
||||
* Fixes the import of content files from previous version of SnapRAID that
|
||||
* Fixed the import of content files from previous version of SnapRAID that
|
||||
are the result of an incomplete sync.
|
||||
* Added a new -C, --gen-conf option to generate a dummy configuration
|
||||
file from the info in the content file.
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ noinst_HEADERS = \
|
|||
spooky2test.c \
|
||||
tommyarray.h \
|
||||
tommyarrayof.h \
|
||||
tommyarrayblk.h \
|
||||
tommyarrayblkof.h \
|
||||
tommychain.h \
|
||||
tommyhash.h \
|
||||
tommyhashdyn.h \
|
||||
|
|
@ -51,6 +53,8 @@ noinst_HEADERS = \
|
|||
tommytypes.h \
|
||||
tommyarray.c \
|
||||
tommyarrayof.c \
|
||||
tommyarrayblk.c \
|
||||
tommyarrayblkof.c \
|
||||
tommyhash.c \
|
||||
tommyhashdyn.c \
|
||||
tommylist.c \
|
||||
|
|
|
|||
12
elem.c
12
elem.c
|
|
@ -252,7 +252,7 @@ int filter_existence(int filter_missing, const char* dir, const char* sub)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int filter_correctness(int filter_error, tommy_arrayof* infoarr, struct snapraid_file* file)
|
||||
int filter_correctness(int filter_error, tommy_arrayblkof* infoarr, struct snapraid_file* file)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
|
|
@ -534,7 +534,7 @@ struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev
|
|||
tommy_hashdyn_init(&disk->linkset);
|
||||
tommy_list_init(&disk->dirlist);
|
||||
tommy_hashdyn_init(&disk->dirset);
|
||||
tommy_array_init(&disk->blockarr);
|
||||
tommy_arrayblk_init(&disk->blockarr);
|
||||
|
||||
return disk;
|
||||
}
|
||||
|
|
@ -549,7 +549,7 @@ void disk_free(struct snapraid_disk* disk)
|
|||
tommy_hashdyn_done(&disk->linkset);
|
||||
tommy_list_foreach(&disk->dirlist, (tommy_foreach_func*)dir_free);
|
||||
tommy_hashdyn_done(&disk->dirset);
|
||||
tommy_array_done(&disk->blockarr);
|
||||
tommy_arrayblk_done(&disk->blockarr);
|
||||
free(disk);
|
||||
}
|
||||
|
||||
|
|
@ -567,13 +567,13 @@ int disk_is_empty(struct snapraid_disk* disk, block_off_t blockmax)
|
|||
return 0;
|
||||
|
||||
/* limit the search to the size of the disk */
|
||||
if (blockmax > tommy_array_size(&disk->blockarr))
|
||||
blockmax = tommy_array_size(&disk->blockarr);
|
||||
if (blockmax > tommy_arrayblk_size(&disk->blockarr))
|
||||
blockmax = tommy_arrayblk_size(&disk->blockarr);
|
||||
|
||||
/* checks all the blocks to search for deleted ones */
|
||||
/* this search is slow, but it's done only if no file is present */
|
||||
for(i=0;i<blockmax;++i) {
|
||||
struct snapraid_block* block = tommy_array_get(&disk->blockarr, i);
|
||||
struct snapraid_block* block = tommy_arrayblk_get(&disk->blockarr, i);
|
||||
unsigned block_state = block_state_get(block);
|
||||
|
||||
switch (block_state) {
|
||||
|
|
|
|||
22
elem.h
22
elem.h
|
|
@ -24,6 +24,8 @@
|
|||
#include "tommyhashdyn.h"
|
||||
#include "tommyarray.h"
|
||||
#include "tommyarrayof.h"
|
||||
#include "tommyarrayblk.h"
|
||||
#include "tommyarrayblkof.h"
|
||||
|
||||
/****************************************************************************/
|
||||
/* snapraid */
|
||||
|
|
@ -282,7 +284,7 @@ struct snapraid_disk {
|
|||
*
|
||||
* Each element points to a snapraid_block structure, or it's BLOCK_EMPTY.
|
||||
*/
|
||||
tommy_array blockarr;
|
||||
tommy_arrayblk blockarr;
|
||||
|
||||
/**
|
||||
* List of all the snapraid_file for the disk.
|
||||
|
|
@ -386,7 +388,7 @@ int filter_existence(int filter_missing, const char* dir, const char* sub);
|
|||
* Filter a file if bad.
|
||||
* Return !=0 if the file is correct and it should be excluded.
|
||||
*/
|
||||
int filter_correctness(int filter_error, tommy_arrayof* infoarr, struct snapraid_file* file);
|
||||
int filter_correctness(int filter_error, tommy_arrayblkof* infoarr, struct snapraid_file* file);
|
||||
|
||||
/**
|
||||
* Filters a dir using a list of filters.
|
||||
|
|
@ -724,8 +726,8 @@ void disk_free(struct snapraid_disk* disk);
|
|||
*/
|
||||
static inline struct snapraid_block* disk_block_get(struct snapraid_disk* disk, block_off_t pos)
|
||||
{
|
||||
if (pos < tommy_array_size(&disk->blockarr))
|
||||
return tommy_array_get(&disk->blockarr, pos);
|
||||
if (pos < tommy_arrayblk_size(&disk->blockarr))
|
||||
return tommy_arrayblk_get(&disk->blockarr, pos);
|
||||
else
|
||||
return BLOCK_EMPTY;
|
||||
}
|
||||
|
|
@ -811,25 +813,25 @@ static inline snapraid_info info_set_rehash(snapraid_info info)
|
|||
* Sets the info at the specified position.
|
||||
* The position is allocated if not yet done.
|
||||
*/
|
||||
static inline void info_set(tommy_arrayof* array, unsigned pos, snapraid_info info)
|
||||
static inline void info_set(tommy_arrayblkof* array, unsigned pos, snapraid_info info)
|
||||
{
|
||||
tommy_arrayof_grow(array, pos + 1);
|
||||
tommy_arrayblkof_grow(array, pos + 1);
|
||||
|
||||
memcpy(tommy_arrayof_ref(array, pos), &info, sizeof(snapraid_info));
|
||||
memcpy(tommy_arrayblkof_ref(array, pos), &info, sizeof(snapraid_info));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the info at the specified position.
|
||||
* For not allocated position, 0 is returned.
|
||||
*/
|
||||
static inline snapraid_info info_get(tommy_arrayof* array, unsigned pos)
|
||||
static inline snapraid_info info_get(tommy_arrayblkof* array, unsigned pos)
|
||||
{
|
||||
snapraid_info info;
|
||||
|
||||
if (pos >= tommy_arrayof_size(array))
|
||||
if (pos >= tommy_arrayblkof_size(array))
|
||||
return 0;
|
||||
|
||||
memcpy(&info, tommy_arrayof_ref(array, pos), sizeof(snapraid_info));
|
||||
memcpy(&info, tommy_arrayblkof_ref(array, pos), sizeof(snapraid_info));
|
||||
|
||||
return info;
|
||||
}
|
||||
|
|
|
|||
4
parity.c
4
parity.c
|
|
@ -35,12 +35,12 @@ block_off_t parity_size(struct snapraid_state* state)
|
|||
struct snapraid_disk* disk = i->data;
|
||||
|
||||
/* start from the declared size */
|
||||
block_off_t block = tommy_array_size(&disk->blockarr);
|
||||
block_off_t block = tommy_arrayblk_size(&disk->blockarr);
|
||||
|
||||
/* decrease the block until an used one */
|
||||
/* we don't stop at deleted blocks, because we want to have them cleared */
|
||||
/* if they are at the end of the parity */
|
||||
while (block > parity_block && !block_has_file(tommy_array_get(&disk->blockarr, block - 1)))
|
||||
while (block > parity_block && !block_has_file(tommy_arrayblk_get(&disk->blockarr, block - 1)))
|
||||
--block;
|
||||
|
||||
/* get the highest value */
|
||||
|
|
|
|||
14
scan.c
14
scan.c
|
|
@ -201,7 +201,7 @@ static void scan_file_remove(struct snapraid_state* state, struct snapraid_disk*
|
|||
tommy_list_insert_tail(&disk->deletedlist, &deleted->node, deleted);
|
||||
|
||||
/* set the deleted block in the block array */
|
||||
tommy_array_set(&disk->blockarr, block_pos, &deleted->block);
|
||||
tommy_arrayblk_set(&disk->blockarr, block_pos, &deleted->block);
|
||||
}
|
||||
|
||||
/* remove the file from the file containers */
|
||||
|
|
@ -229,25 +229,25 @@ static void scan_file_insert(struct snapraid_state* state, struct snapraid_disk*
|
|||
|
||||
/* allocate the blocks of the file */
|
||||
block_pos = disk->first_free_block;
|
||||
block_max = tommy_array_size(&disk->blockarr);
|
||||
block_max = tommy_arrayblk_size(&disk->blockarr);
|
||||
for(i=0;i<file->blockmax;++i) {
|
||||
struct snapraid_block* block;
|
||||
|
||||
/* find a free block */
|
||||
while (block_pos < block_max && block_has_file(tommy_array_get(&disk->blockarr, block_pos)))
|
||||
while (block_pos < block_max && block_has_file(tommy_arrayblk_get(&disk->blockarr, block_pos)))
|
||||
++block_pos;
|
||||
|
||||
/* if not found, allocate a new one */
|
||||
if (block_pos == block_max) {
|
||||
++block_max;
|
||||
tommy_array_grow(&disk->blockarr, block_max);
|
||||
tommy_arrayblk_grow(&disk->blockarr, block_max);
|
||||
}
|
||||
|
||||
/* set the position */
|
||||
file->blockvec[i].parity_pos = block_pos;
|
||||
|
||||
/* block to overwrite */
|
||||
block = tommy_array_get(&disk->blockarr, block_pos);
|
||||
block = tommy_arrayblk_get(&disk->blockarr, block_pos);
|
||||
|
||||
/* if the block is an empty one */
|
||||
if (block == BLOCK_EMPTY) {
|
||||
|
|
@ -260,7 +260,7 @@ static void scan_file_insert(struct snapraid_state* state, struct snapraid_disk*
|
|||
}
|
||||
|
||||
/* store in the disk map, after invalidating all the other blocks */
|
||||
tommy_array_set(&disk->blockarr, block_pos, &file->blockvec[i]);
|
||||
tommy_arrayblk_set(&disk->blockarr, block_pos, &file->blockvec[i]);
|
||||
}
|
||||
if (file->blockmax) {
|
||||
/* set the new free position, but only if allocated something */
|
||||
|
|
@ -1122,7 +1122,5 @@ void state_scan(struct snapraid_state* state, int output)
|
|||
}
|
||||
|
||||
tommy_list_foreach(&scanlist, (tommy_foreach_func*)free);
|
||||
|
||||
printf("Using %u MiB of memory.\n", (unsigned)(malloc_counter() / 1024 / 1024));
|
||||
}
|
||||
|
||||
|
|
|
|||
23
snapraid.c
23
snapraid.c
|
|
@ -79,6 +79,15 @@ void usage(void)
|
|||
printf(" " SWITCH_GETOPT_LONG("-V, --version ", "-V") " Version\n");
|
||||
}
|
||||
|
||||
void memory(struct snapraid_state* state)
|
||||
{
|
||||
if (state->opt.gui) {
|
||||
fprintf(stdlog, "memory:used:%"PRIu64"\n", (uint64_t)malloc_counter());
|
||||
} else {
|
||||
printf("Using %u MiB of memory.\n", (unsigned)(malloc_counter() / 1024 / 1024));
|
||||
}
|
||||
}
|
||||
|
||||
#define OPT_TEST_SKIP_SELF 256
|
||||
#define OPT_TEST_KILL_AFTER_SYNC 257
|
||||
#define OPT_TEST_EXPECT_UNRECOVERABLE 258
|
||||
|
|
@ -564,11 +573,15 @@ int main(int argc, char* argv[])
|
|||
state_read(&state);
|
||||
|
||||
state_scan(&state, 1);
|
||||
|
||||
memory(&state);
|
||||
} else if (operation == OPERATION_SYNC) {
|
||||
state_read(&state);
|
||||
|
||||
state_scan(&state, 0);
|
||||
|
||||
memory(&state);
|
||||
|
||||
/* intercept Ctrl+C */
|
||||
signal(SIGINT, &signal_handler);
|
||||
|
||||
|
|
@ -614,6 +627,8 @@ int main(int argc, char* argv[])
|
|||
/* apply the command line filter */
|
||||
state_filter(&state, &filterlist_file, &filterlist_disk, filter_missing, filter_error);
|
||||
|
||||
memory(&state);
|
||||
|
||||
/* intercept Ctrl+C */
|
||||
signal(SIGINT, &signal_handler);
|
||||
|
||||
|
|
@ -632,6 +647,8 @@ int main(int argc, char* argv[])
|
|||
} else if (operation == OPERATION_SCRUB) {
|
||||
state_read(&state);
|
||||
|
||||
memory(&state);
|
||||
|
||||
/* intercept Ctrl+C */
|
||||
signal(SIGINT, &signal_handler);
|
||||
|
||||
|
|
@ -648,9 +665,13 @@ int main(int argc, char* argv[])
|
|||
state_read(&state);
|
||||
|
||||
state_write(&state);
|
||||
|
||||
memory(&state);
|
||||
} else if (operation == OPERATION_STATUS) {
|
||||
state_read(&state);
|
||||
|
||||
memory(&state);
|
||||
|
||||
state_status(&state);
|
||||
} else if (operation == OPERATION_DUP) {
|
||||
state_read(&state);
|
||||
|
|
@ -669,6 +690,8 @@ int main(int argc, char* argv[])
|
|||
/* apply the command line filter */
|
||||
state_filter(&state, &filterlist_file, &filterlist_disk, filter_missing, filter_error);
|
||||
|
||||
memory(&state);
|
||||
|
||||
/* intercept Ctrl+C */
|
||||
signal(SIGINT, &signal_handler);
|
||||
|
||||
|
|
|
|||
20
state.c
20
state.c
|
|
@ -75,7 +75,7 @@ void state_init(struct snapraid_state* state)
|
|||
tommy_list_init(&state->importlist);
|
||||
tommy_hashdyn_init(&state->importset);
|
||||
tommy_hashdyn_init(&state->previmportset);
|
||||
tommy_arrayof_init(&state->infoarr, sizeof(snapraid_info));
|
||||
tommy_arrayblkof_init(&state->infoarr, sizeof(snapraid_info));
|
||||
}
|
||||
|
||||
void state_done(struct snapraid_state* state)
|
||||
|
|
@ -87,7 +87,7 @@ void state_done(struct snapraid_state* state)
|
|||
tommy_list_foreach(&state->importlist, (tommy_foreach_func*)import_file_free);
|
||||
tommy_hashdyn_done(&state->importset);
|
||||
tommy_hashdyn_done(&state->previmportset);
|
||||
tommy_arrayof_done(&state->infoarr);
|
||||
tommy_arrayblkof_done(&state->infoarr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1003,8 +1003,8 @@ static void state_read_text(struct snapraid_state* state, const char* path, STRE
|
|||
}
|
||||
|
||||
/* insert the block in the block array */
|
||||
tommy_array_grow(&disk->blockarr, v_pos + 1);
|
||||
tommy_array_set(&disk->blockarr, v_pos, block);
|
||||
tommy_arrayblk_grow(&disk->blockarr, v_pos + 1);
|
||||
tommy_arrayblk_set(&disk->blockarr, v_pos, block);
|
||||
|
||||
/* check for termination of the block list */
|
||||
++blockidx;
|
||||
|
|
@ -1136,8 +1136,8 @@ static void state_read_text(struct snapraid_state* state, const char* path, STRE
|
|||
}
|
||||
|
||||
/* insert the block in the block array */
|
||||
tommy_array_grow(&disk->blockarr, v_pos + 1);
|
||||
tommy_array_set(&disk->blockarr, v_pos, &deleted->block);
|
||||
tommy_arrayblk_grow(&disk->blockarr, v_pos + 1);
|
||||
tommy_arrayblk_set(&disk->blockarr, v_pos, &deleted->block);
|
||||
|
||||
/* if the block has an hash */
|
||||
if (block_has_any_hash(&deleted->block)) {
|
||||
|
|
@ -2186,7 +2186,7 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST
|
|||
}
|
||||
|
||||
/* grow the array */
|
||||
tommy_array_grow(&disk->blockarr, v_pos + v_count);
|
||||
tommy_arrayblk_grow(&disk->blockarr, v_pos + v_count);
|
||||
|
||||
/* fill the blocks in the run */
|
||||
while (v_count) {
|
||||
|
|
@ -2234,7 +2234,7 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST
|
|||
}
|
||||
|
||||
/* insert the block in the block array */
|
||||
tommy_array_set(&disk->blockarr, v_pos, block);
|
||||
tommy_arrayblk_set(&disk->blockarr, v_pos, block);
|
||||
|
||||
/* stat */
|
||||
++count_block;
|
||||
|
|
@ -2369,7 +2369,7 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST
|
|||
switch (c) {
|
||||
case 'o' :
|
||||
/* grow the array */
|
||||
tommy_array_grow(&disk->blockarr, v_pos + v_count);
|
||||
tommy_arrayblk_grow(&disk->blockarr, v_pos + v_count);
|
||||
|
||||
/* if it's a run of deleted blocks */
|
||||
while (v_count) {
|
||||
|
|
@ -2399,7 +2399,7 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST
|
|||
}
|
||||
|
||||
/* insert the block in the block array */
|
||||
tommy_array_set(&disk->blockarr, v_pos, &deleted->block);
|
||||
tommy_arrayblk_set(&disk->blockarr, v_pos, &deleted->block);
|
||||
|
||||
/* go to next block */
|
||||
++v_pos;
|
||||
|
|
|
|||
2
state.h
2
state.h
|
|
@ -103,7 +103,7 @@ struct snapraid_state {
|
|||
tommy_list importlist; /**< List of import file. */
|
||||
tommy_hashdyn importset; /**< Hashtable by hash of all the import blocks. */
|
||||
tommy_hashdyn previmportset; /**< Hashtable by prevhash of all the import blocks. Valid only if we are in a rehash state. */
|
||||
tommy_arrayof infoarr; /**< Block information array. */
|
||||
tommy_arrayblkof infoarr; /**< Block information array. */
|
||||
block_off_t loaded_blockmax; /**< Previous size of the parity file, computed from the loaded state. */
|
||||
time_t progress_start; /**< Start of processing for progress visualization. */
|
||||
time_t progress_last; /**< Last update of progress visualization. */
|
||||
|
|
|
|||
4
sync.c
4
sync.c
|
|
@ -150,7 +150,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
/* if the block is deleted */
|
||||
if (block_state_get(block) == BLOCK_STATE_DELETED) {
|
||||
/* set it to empty */
|
||||
tommy_array_set(&handle[j].disk->blockarr, i, BLOCK_EMPTY);
|
||||
tommy_arrayblk_set(&handle[j].disk->blockarr, i, BLOCK_EMPTY);
|
||||
|
||||
/* mark the state as needing write */
|
||||
state->need_write = 1;
|
||||
|
|
@ -328,7 +328,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
/* if it's a deleted block */
|
||||
if (block_state_get(block) == BLOCK_STATE_DELETED) {
|
||||
/* the parity is now updated without this block, so it's now empty */
|
||||
tommy_array_set(&handle[j].disk->blockarr, i, BLOCK_EMPTY);
|
||||
tommy_arrayblk_set(&handle[j].disk->blockarr, i, BLOCK_EMPTY);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
2
tommy.c
2
tommy.c
|
|
@ -29,4 +29,6 @@
|
|||
#include "tommyhashdyn.c"
|
||||
#include "tommyarray.c"
|
||||
#include "tommyarrayof.c"
|
||||
#include "tommyarrayblk.c"
|
||||
#include "tommyarrayblkof.c"
|
||||
|
||||
|
|
|
|||
|
|
@ -26,13 +26,15 @@
|
|||
*/
|
||||
|
||||
/** \file
|
||||
* Dynamic array.
|
||||
* Dynamic array based on segments of exponential growing size.
|
||||
*
|
||||
* This array is able to grow dynamically upon request.
|
||||
*
|
||||
* The resize involve an allocation of a new array segment, without reallocating
|
||||
* the already allocated memory, and then not increasing the heap fragmentation.
|
||||
*
|
||||
* Allocated segments grow in size exponentially.
|
||||
*
|
||||
* This means that the address of the allocated segments never change.
|
||||
*/
|
||||
|
||||
|
|
|
|||
83
tommyarrayblk.c
Normal file
83
tommyarrayblk.c
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright 2013 Andrea Mazzoleni. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANDREA MAZZOLENI AND CONTRIBUTORS ``AS IS''
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL ANDREA MAZZOLENI OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "tommyarrayblk.h"
|
||||
|
||||
#include <string.h> /* for memset */
|
||||
|
||||
/******************************************************************************/
|
||||
/* array */
|
||||
|
||||
void tommy_arrayblk_init(tommy_arrayblk* array)
|
||||
{
|
||||
tommy_array_init(&array->block);
|
||||
|
||||
array->size = 0;
|
||||
}
|
||||
|
||||
void tommy_arrayblk_done(tommy_arrayblk* array)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for(i=0;i<tommy_array_size(&array->block);++i)
|
||||
tommy_free(tommy_array_get(&array->block, i));
|
||||
|
||||
tommy_array_done(&array->block);
|
||||
}
|
||||
|
||||
void tommy_arrayblk_grow(tommy_arrayblk* array, unsigned size)
|
||||
{
|
||||
unsigned block_max = (size + TOMMY_ARRAYBLK_SIZE - 1) / TOMMY_ARRAYBLK_SIZE;
|
||||
unsigned block_mac = tommy_array_size(&array->block);
|
||||
|
||||
if (block_mac < block_max) {
|
||||
/* grow the block array */
|
||||
tommy_array_grow(&array->block, block_max);
|
||||
|
||||
/* allocate new blocks */
|
||||
while (block_mac < block_max) {
|
||||
void* ptr = tommy_malloc(TOMMY_ARRAYBLK_SIZE * sizeof(void*));
|
||||
|
||||
/* initializes it with zeros */
|
||||
memset(ptr, 0, TOMMY_ARRAYBLK_SIZE * sizeof(void*));
|
||||
|
||||
/* set the new block */
|
||||
tommy_array_set(&array->block, block_mac, ptr);
|
||||
|
||||
++block_mac;
|
||||
}
|
||||
}
|
||||
|
||||
if (array->size < size)
|
||||
array->size = size;
|
||||
}
|
||||
|
||||
tommy_size_t tommy_arrayblk_memory_usage(tommy_arrayblk* array)
|
||||
{
|
||||
return tommy_array_memory_usage(&array->block) + tommy_array_size(&array->block) * TOMMY_ARRAYBLK_SIZE * sizeof(void*);
|
||||
}
|
||||
|
||||
143
tommyarrayblk.h
Normal file
143
tommyarrayblk.h
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright 2013 Andrea Mazzoleni. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANDREA MAZZOLENI AND CONTRIBUTORS ``AS IS''
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL ANDREA MAZZOLENI OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Dynamic array based on blocks of fixed sizes.
|
||||
*
|
||||
* This array is able to grow dynamically upon request.
|
||||
*
|
||||
* The resize involve an allocation of a new array block, without reallocating
|
||||
* the already allocated memory, and then not increasing the heap fragmentation.
|
||||
*
|
||||
* Allocated blocks are always of the same size.
|
||||
*
|
||||
* This means that the address of the allocated blocks never change.
|
||||
*/
|
||||
|
||||
#ifndef __TOMMYARRAYBLK_H
|
||||
#define __TOMMYARRAYBLK_H
|
||||
|
||||
#include "tommytypes.h"
|
||||
#include "tommyarray.h"
|
||||
|
||||
#include <assert.h> /* for assert */
|
||||
|
||||
/******************************************************************************/
|
||||
/* array */
|
||||
|
||||
/**
|
||||
* Elements for each block.
|
||||
*/
|
||||
#define TOMMY_ARRAYBLK_SIZE (64 * 1024)
|
||||
|
||||
/**
|
||||
* Array.
|
||||
*/
|
||||
typedef struct tommy_arrayblk_struct {
|
||||
tommy_array block; /**< Array of blocks. */
|
||||
unsigned size; /**< Currently allocated and initialized size. */
|
||||
} tommy_arrayblk;
|
||||
|
||||
/**
|
||||
* Initializes the array.
|
||||
*/
|
||||
void tommy_arrayblk_init(tommy_arrayblk* array);
|
||||
|
||||
/**
|
||||
* Deinitializes the array.
|
||||
*/
|
||||
void tommy_arrayblk_done(tommy_arrayblk* array);
|
||||
|
||||
/**
|
||||
* Grow the size up to the specified value.
|
||||
* All the new elements in the array are initialized with the 0 value.
|
||||
*/
|
||||
void tommy_arrayblk_grow(tommy_arrayblk* array, unsigned size);
|
||||
|
||||
/**
|
||||
* Gets a reference of the element at the specified position.
|
||||
* You must be sure that space for this position is already
|
||||
* allocated calling tommy_arrayblk_grow().
|
||||
*/
|
||||
tommy_inline void** tommy_arrayblk_ref(tommy_arrayblk* array, unsigned pos)
|
||||
{
|
||||
void** ptr;
|
||||
|
||||
assert(pos < array->size);
|
||||
|
||||
ptr = tommy_array_get(&array->block, pos / TOMMY_ARRAYBLK_SIZE);
|
||||
|
||||
return &ptr[pos % TOMMY_ARRAYBLK_SIZE];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the element at the specified position.
|
||||
* You must be sure that space for this position is already
|
||||
* allocated calling tommy_arrayblk_grow().
|
||||
*/
|
||||
tommy_inline void tommy_arrayblk_set(tommy_arrayblk* array, unsigned pos, void* element)
|
||||
{
|
||||
*tommy_arrayblk_ref(array, pos) = element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the element at the specified position.
|
||||
* You must be sure that space for this position is already
|
||||
* allocated calling tommy_arrayblk_grow().
|
||||
*/
|
||||
tommy_inline void* tommy_arrayblk_get(tommy_arrayblk* array, unsigned pos)
|
||||
{
|
||||
return *tommy_arrayblk_ref(array, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grows and inserts a new element at the end of the array.
|
||||
*/
|
||||
tommy_inline void tommy_arrayblk_insert(tommy_arrayblk* array, void* element)
|
||||
{
|
||||
unsigned pos = array->size;
|
||||
|
||||
tommy_arrayblk_grow(array, pos + 1);
|
||||
|
||||
tommy_arrayblk_set(array, pos, element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the initialized size of the array.
|
||||
*/
|
||||
tommy_inline unsigned tommy_arrayblk_size(tommy_arrayblk* array)
|
||||
{
|
||||
return array->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of allocated memory.
|
||||
*/
|
||||
tommy_size_t tommy_arrayblk_memory_usage(tommy_arrayblk* array);
|
||||
|
||||
#endif
|
||||
|
||||
83
tommyarrayblkof.c
Normal file
83
tommyarrayblkof.c
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright 2013 Andrea Mazzoleni. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANDREA MAZZOLENI AND CONTRIBUTORS ``AS IS''
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL ANDREA MAZZOLENI OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "tommyarrayblkof.h"
|
||||
|
||||
#include <string.h> /* for memset */
|
||||
|
||||
/******************************************************************************/
|
||||
/* array */
|
||||
|
||||
void tommy_arrayblkof_init(tommy_arrayblkof* array, unsigned element_size)
|
||||
{
|
||||
tommy_array_init(&array->block);
|
||||
array->element_size = element_size;
|
||||
array->size = 0;
|
||||
}
|
||||
|
||||
void tommy_arrayblkof_done(tommy_arrayblkof* array)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for(i=0;i<tommy_array_size(&array->block);++i)
|
||||
tommy_free(tommy_array_get(&array->block, i));
|
||||
|
||||
tommy_array_done(&array->block);
|
||||
}
|
||||
|
||||
void tommy_arrayblkof_grow(tommy_arrayblkof* array, unsigned size)
|
||||
{
|
||||
unsigned block_max = (size + TOMMY_ARRAYBLK_SIZE - 1) / TOMMY_ARRAYBLK_SIZE;
|
||||
unsigned block_mac = tommy_array_size(&array->block);
|
||||
|
||||
if (block_mac < block_max) {
|
||||
/* grow the block array */
|
||||
tommy_array_grow(&array->block, block_max);
|
||||
|
||||
/* allocate new blocks */
|
||||
while (block_mac < block_max) {
|
||||
void* ptr = tommy_malloc(TOMMY_ARRAYBLK_SIZE * array->element_size);
|
||||
|
||||
/* initializes it with zeros */
|
||||
memset(ptr, 0, TOMMY_ARRAYBLK_SIZE * array->element_size);
|
||||
|
||||
/* set the new block */
|
||||
tommy_array_set(&array->block, block_mac, ptr);
|
||||
|
||||
++block_mac;
|
||||
}
|
||||
}
|
||||
|
||||
if (array->size < size)
|
||||
array->size = size;
|
||||
}
|
||||
|
||||
tommy_size_t tommy_arrayblkof_memory_usage(tommy_arrayblkof* array)
|
||||
{
|
||||
return tommy_array_memory_usage(&array->block) + tommy_array_size(&array->block) * TOMMY_ARRAYBLKOF_SIZE * array->element_size;
|
||||
}
|
||||
|
||||
108
tommyarrayblkof.h
Normal file
108
tommyarrayblkof.h
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright 2013 Andrea Mazzoleni. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANDREA MAZZOLENI AND CONTRIBUTORS ``AS IS''
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL ANDREA MAZZOLENI OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Dynamic array based on blocks of fixed sizes.
|
||||
*
|
||||
* This array is able to grow dynamically upon request.
|
||||
*
|
||||
* This is very similar at ::tommy_arrayblk, but it allows to store elements of any
|
||||
* size and not just pointers.
|
||||
*/
|
||||
|
||||
#ifndef __TOMMYARRAYBLKOF_H
|
||||
#define __TOMMYARRAYBLKOF_H
|
||||
|
||||
#include "tommytypes.h"
|
||||
#include "tommyarray.h"
|
||||
|
||||
#include <assert.h> /* for assert */
|
||||
|
||||
/******************************************************************************/
|
||||
/* array */
|
||||
|
||||
/**
|
||||
* Elements for each block.
|
||||
*/
|
||||
#define TOMMY_ARRAYBLKOF_SIZE (64 * 1024)
|
||||
|
||||
/**
|
||||
* Array.
|
||||
*/
|
||||
typedef struct tommy_arrayblkof_struct {
|
||||
tommy_array block; /**< Array of blocks. */
|
||||
unsigned element_size; /**< Size of the stored element in bytes. */
|
||||
unsigned size; /**< Currently allocated and initialized size. */
|
||||
} tommy_arrayblkof;
|
||||
|
||||
/**
|
||||
* Initializes the array.
|
||||
*/
|
||||
void tommy_arrayblkof_init(tommy_arrayblkof* array, unsigned element_size);
|
||||
|
||||
/**
|
||||
* Deinitializes the array.
|
||||
*/
|
||||
void tommy_arrayblkof_done(tommy_arrayblkof* array);
|
||||
|
||||
/**
|
||||
* Grow the size up to the specified value.
|
||||
* All the new elements in the array are initialized with the 0 value.
|
||||
*/
|
||||
void tommy_arrayblkof_grow(tommy_arrayblkof* array, unsigned size);
|
||||
|
||||
/**
|
||||
* Gets a reference of the element at the specified position.
|
||||
* You must be sure that space for this position is already
|
||||
* allocated calling tommy_arrayblkof_grow().
|
||||
*/
|
||||
tommy_inline void* tommy_arrayblkof_ref(tommy_arrayblkof* array, unsigned pos)
|
||||
{
|
||||
unsigned char* base;
|
||||
|
||||
assert(pos < array->size);
|
||||
|
||||
base = tommy_array_get(&array->block, pos / TOMMY_ARRAYBLKOF_SIZE);
|
||||
|
||||
return base + (pos % TOMMY_ARRAYBLKOF_SIZE) * array->element_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the initialized size of the array.
|
||||
*/
|
||||
tommy_inline unsigned tommy_arrayblkof_size(tommy_arrayblkof* array)
|
||||
{
|
||||
return array->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of allocated memory.
|
||||
*/
|
||||
tommy_size_t tommy_arrayblkof_memory_usage(tommy_arrayblkof* array);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2011 Andrea Mazzoleni. All rights reserved.
|
||||
* Copyright 2013 Andrea Mazzoleni. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
|
|
|||
|
|
@ -26,17 +26,12 @@
|
|||
*/
|
||||
|
||||
/** \file
|
||||
* Dynamic array.
|
||||
* Dynamic array based on segments of exponential growing size.
|
||||
*
|
||||
* This array is able to grow dynamically upon request.
|
||||
*
|
||||
* This is very similar at ::tommy_array, but it allows to store elements of any
|
||||
* size and not just pointers.
|
||||
*
|
||||
* The resize involve an allocation of a new array segment, without reallocating
|
||||
* the already allocated memory, and then not increasing the heap fragmentation.
|
||||
*
|
||||
* This means that the address of the allocated segments never change.
|
||||
*/
|
||||
|
||||
#ifndef __TOMMYARRAYOF_H
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue