From 7e66fe43ce177c4b0a1d08f1c1e67788d7d8afb8 Mon Sep 17 00:00:00 2001 From: Vreixo Formoso Date: Sat, 29 Dec 2007 18:30:59 +0100 Subject: [PATCH] Reduce memory usage in low level tree, by storing dir info separately. --- demo/ecma119_tree.c | 4 +-- src/ecma119.c | 38 ++++++++++++------------ src/ecma119_tree.c | 72 ++++++++++++++++++++++++++------------------- src/ecma119_tree.h | 4 +-- src/rockridge.c | 10 +++---- test/mocked_fsrc.c | 8 +++++ 6 files changed, 76 insertions(+), 60 deletions(-) diff --git a/demo/ecma119_tree.c b/demo/ecma119_tree.c index 9984ab2..7569243 100644 --- a/demo/ecma119_tree.c +++ b/demo/ecma119_tree.c @@ -51,8 +51,8 @@ print_dir(Ecma119Node *dir, int level) sp[level * 2-1] = '-'; sp[level * 2] = '\0'; - for (i = 0; i < dir->info.dir.nchildren; i++) { - Ecma119Node *child = dir->info.dir.children[i]; + for (i = 0; i < dir->info.dir->nchildren; i++) { + Ecma119Node *child = dir->info.dir->children[i]; if (child->type == ECMA119_DIR) { printf("%s+[D] ", sp); diff --git a/src/ecma119.c b/src/ecma119.c index 9223208..68e4375 100644 --- a/src/ecma119.c +++ b/src/ecma119.c @@ -106,9 +106,9 @@ size_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce) *ce += ce_len; } - for (i = 0; i < dir->info.dir.nchildren; ++i) { + for (i = 0; i < dir->info.dir->nchildren; ++i) { size_t remaining; - Ecma119Node *child = dir->info.dir.children[i]; + Ecma119Node *child = dir->info.dir->children[i]; size_t dirent_len = calc_dirent_len(t, child); if (t->rockridge) { dirent_len += rrip_calc_len(t, child, 0, 255 - dirent_len, &ce_len); @@ -123,7 +123,7 @@ size_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce) } } /* cache the len */ - dir->info.dir.len = len; + dir->info.dir->len = len; return len; } @@ -134,14 +134,14 @@ void calc_dir_pos(Ecma119Image *t, Ecma119Node *dir) size_t ce_len = 0; t->ndirs++; - dir->info.dir.block = t->curblock; + dir->info.dir->block = t->curblock; len = calc_dir_size(t, dir, &ce_len); t->curblock += div_up(len, BLOCK_SIZE); if (t->rockridge) { t->curblock += div_up(ce_len, BLOCK_SIZE); } - for (i = 0; i < dir->info.dir.nchildren; i++) { - Ecma119Node *child = dir->info.dir.children[i]; + for (i = 0; i < dir->info.dir->nchildren; i++) { + Ecma119Node *child = dir->info.dir->children[i]; if (child->type == ECMA119_DIR) { calc_dir_pos(t, child); } @@ -163,8 +163,8 @@ uint32_t calc_path_table_size(Ecma119Node *dir) size += (size % 2); /* and recurse */ - for (i = 0; i < dir->info.dir.nchildren; i++) { - Ecma119Node *child = dir->info.dir.children[i]; + for (i = 0; i < dir->info.dir->nchildren; i++) { + Ecma119Node *child = dir->info.dir->children[i]; if (child->type == ECMA119_DIR) { size += calc_path_table_size(child); } @@ -240,8 +240,8 @@ void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id, if (node->type == ECMA119_DIR) { /* use the cached length */ - len = node->info.dir.len; - block = node->info.dir.block; + len = node->info.dir->len; + block = node->info.dir->block; } else if (node->type == ECMA119_FILE) { len = iso_file_src_get_size(node->info.file); block = node->info.file->block; @@ -389,8 +389,8 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir) memset(&info, 0, sizeof(struct susp_info)); if (t->rockridge) { /* initialize the ce_block, it might be needed */ - info.ce_block = dir->info.dir.block + div_up(dir->info.dir.len, - BLOCK_SIZE); + info.ce_block = dir->info.dir->block + div_up(dir->info.dir->len, + BLOCK_SIZE); } /* write the "." and ".." entries first */ @@ -414,8 +414,8 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir) write_one_dir_record(t, dir, 1, buf, 1, &info); buf += len; - for (i = 0; i < dir->info.dir.nchildren; i++) { - Ecma119Node *child = dir->info.dir.children[i]; + for (i = 0; i < dir->info.dir->nchildren; i++) { + Ecma119Node *child = dir->info.dir->children[i]; /* compute len of directory entry */ fi_len = strlen(child->iso_name); @@ -474,8 +474,8 @@ int write_dirs(Ecma119Image *t, Ecma119Node *root) } /* recurse */ - for (i = 0; i < root->info.dir.nchildren; i++) { - Ecma119Node *child = root->info.dir.children[i]; + for (i = 0; i < root->info.dir->nchildren; i++) { + Ecma119Node *child = root->info.dir->children[i]; if (child->type == ECMA119_DIR) { ret = write_dirs(t, child); if (ret < 0) { @@ -514,7 +514,7 @@ int write_path_table(Ecma119Image *t, Ecma119Node **pathlist, int l_type) rec = (struct ecma119_path_table_record*) buf; rec->len_di[0] = dir->parent ? (uint8_t) strlen(dir->iso_name) : 1; rec->len_xa[0] = 0; - write_int(rec->block, dir->info.dir.block, 4); + write_int(rec->block, dir->info.dir->block, 4); write_int(rec->parent, parent + 1, 2); if (dir->parent) { memcpy(rec->dir_id, dir->iso_name, rec->len_di[0]); @@ -558,8 +558,8 @@ int write_path_tables(Ecma119Image *t) for (i = 0; i < t->ndirs; i++) { Ecma119Node *dir = pathlist[i]; - for (j = 0; j < dir->info.dir.nchildren; j++) { - Ecma119Node *child = dir->info.dir.children[j]; + for (j = 0; j < dir->info.dir->nchildren; j++) { + Ecma119Node *child = dir->info.dir->children[j]; if (child->type == ECMA119_DIR) { pathlist[cur++] = child; } diff --git a/src/ecma119_tree.c b/src/ecma119_tree.c index 6652c20..2376bad 100644 --- a/src/ecma119_tree.c +++ b/src/ecma119_tree.c @@ -96,20 +96,29 @@ int create_dir(Ecma119Image *img, IsoDir *iso, Ecma119Node **node) { int ret; Ecma119Node **children; + struct ecma119_dir_info *dir_info; children = calloc(1, sizeof(void*) * iso->nchildren); if (children == NULL) { return ISO_MEM_ERROR; } + + dir_info = calloc(1, sizeof(struct ecma119_dir_info)); + if (dir_info == NULL) { + free(children); + return ISO_MEM_ERROR; + } ret = create_ecma119_node(img, (IsoNode*)iso, node); if (ret < 0) { free(children); + free(dir_info); return ret; } (*node)->type = ECMA119_DIR; - (*node)->info.dir.nchildren = 0; - (*node)->info.dir.children = children; + (*node)->info.dir = dir_info; + (*node)->info.dir->nchildren = 0; + (*node)->info.dir->children = children; return ISO_SUCCESS; } @@ -191,10 +200,11 @@ void ecma119_node_free(Ecma119Node *node) } if (node->type == ECMA119_DIR) { int i; - for (i = 0; i < node->info.dir.nchildren; i++) { - ecma119_node_free(node->info.dir.children[i]); + for (i = 0; i < node->info.dir->nchildren; i++) { + ecma119_node_free(node->info.dir->children[i]); } - free(node->info.dir.children); + free(node->info.dir->children); + free(node->info.dir); } free(node->iso_name); iso_node_unref(node->node); @@ -288,8 +298,8 @@ int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree, break; } else if (cret == ISO_SUCCESS) { /* add child to this node */ - int nchildren = node->info.dir.nchildren++; - node->info.dir.children[nchildren] = child; + int nchildren = node->info.dir->nchildren++; + node->info.dir->children[nchildren] = child; child->parent = node; } pos = pos->next; @@ -329,11 +339,11 @@ void sort_tree(Ecma119Node *root) { size_t i; - qsort(root->info.dir.children, root->info.dir.nchildren, sizeof(void*), + qsort(root->info.dir->children, root->info.dir->nchildren, sizeof(void*), cmp_node_name); - for (i = 0; i < root->info.dir.nchildren; i++) { - if (root->info.dir.children[i]->type == ECMA119_DIR) - sort_tree(root->info.dir.children[i]); + for (i = 0; i < root->info.dir->nchildren; i++) { + if (root->info.dir->children[i]->type == ECMA119_DIR) + sort_tree(root->info.dir->children[i]); } } @@ -341,8 +351,8 @@ static int contains_name(Ecma119Node *dir, const char *name) { int i; - for (i = 0; i < dir->info.dir.nchildren; i++) { - Ecma119Node *child = dir->info.dir.children[i]; + for (i = 0; i < dir->info.dir->nchildren; i++) { + Ecma119Node *child = dir->info.dir->children[i]; if (!strcmp(child->iso_name, name)) { return 1; } @@ -365,8 +375,8 @@ int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len, Ecma119Node **children; int need_sort = 0; - nchildren = dir->info.dir.nchildren; - children = dir->info.dir.children; + nchildren = dir->info.dir->nchildren; + children = dir->info.dir->children; for (i = 0; i < nchildren; ++i) { char *name, *ext; @@ -534,9 +544,9 @@ int mangle_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len, } /* recurse */ - for (i = 0; i < dir->info.dir.nchildren; ++i) { - if (dir->info.dir.children[i]->type == ECMA119_DIR) { - ret = mangle_dir(img, dir->info.dir.children[i], max_file_len, + for (i = 0; i < dir->info.dir->nchildren; ++i) { + if (dir->info.dir->children[i]->type == ECMA119_DIR) { + ret = mangle_dir(img, dir->info.dir->children[i], max_file_len, max_dir_len); if (ret < 0) { /* error */ @@ -611,8 +621,8 @@ static size_t max_child_name_len(Ecma119Node *dir) { size_t ret = 0, i; - for (i = 0; i < dir->info.dir.nchildren; i++) { - size_t len = strlen(dir->info.dir.children[i]->iso_name); + for (i = 0; i < dir->info.dir->nchildren; i++) { + size_t len = strlen(dir->info.dir->children[i]->iso_name); ret = MAX(ret, len); } return ret; @@ -632,31 +642,31 @@ int reparent(Ecma119Node *child, Ecma119Node *parent) Ecma119Node *placeholder; /* replace the child in the original parent with a placeholder */ - for (i = 0; i < child->parent->info.dir.nchildren; i++) { - if (child->parent->info.dir.children[i] == child) { + for (i = 0; i < child->parent->info.dir->nchildren; i++) { + if (child->parent->info.dir->children[i] == child) { ret = create_placeholder(child->parent, child, &placeholder); if (ret < 0) { return ret; } - child->parent->info.dir.children[i] = placeholder; + child->parent->info.dir->children[i] = placeholder; break; } } /* just for debug, this should never happen... */ - if (i == child->parent->info.dir.nchildren) { + if (i == child->parent->info.dir->nchildren) { return ISO_ERROR; } /* keep track of the real parent */ - child->info.dir.real_parent = child->parent; + child->info.dir->real_parent = child->parent; /* add the child to its new parent */ child->parent = parent; - parent->info.dir.nchildren++; - parent->info.dir.children = realloc(parent->info.dir.children, - sizeof(void*) * parent->info.dir.nchildren); - parent->info.dir.children[parent->info.dir.nchildren - 1] = child; + parent->info.dir->nchildren++; + parent->info.dir->children = realloc(parent->info.dir->children, + sizeof(void*) * parent->info.dir->nchildren); + parent->info.dir->children[parent->info.dir->nchildren - 1] = child; return ISO_SUCCESS; } @@ -696,8 +706,8 @@ int reorder_tree(Ecma119Image *img, Ecma119Node *dir, int level, int pathlen) } else { size_t i; - for (i = 0; i < dir->info.dir.nchildren; i++) { - Ecma119Node *child = dir->info.dir.children[i]; + for (i = 0; i < dir->info.dir->nchildren; i++) { + Ecma119Node *child = dir->info.dir->children[i]; if (child->type == ECMA119_DIR) { int newpathlen = pathlen + 1 + strlen(child->iso_name); ret = reorder_tree(img, child, level + 1, newpathlen); diff --git a/src/ecma119_tree.h b/src/ecma119_tree.h index 032fe68..fc53f92 100644 --- a/src/ecma119_tree.h +++ b/src/ecma119_tree.h @@ -71,9 +71,7 @@ struct ecma119_node union { IsoFileSrc *file; - // TODO this wastes too much memory, as dirs have much more - // atts than other kind of files. Replace with a pointer. - struct ecma119_dir_info dir; + struct ecma119_dir_info *dir; /** this field points to the relocated directory. */ Ecma119Node *real_me; } info; diff --git a/src/rockridge.c b/src/rockridge.c index 3f2f06f..6a975e4 100644 --- a/src/rockridge.c +++ b/src/rockridge.c @@ -143,7 +143,7 @@ int rrip_add_PL(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp) { uint8_t *PL; - if (n->type != ECMA119_DIR || n->info.dir.real_parent == NULL) { + if (n->type != ECMA119_DIR || n->info.dir->real_parent == NULL) { /* should never occur */ return ISO_ERROR; } @@ -159,7 +159,7 @@ int rrip_add_PL(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp) PL[3] = 1; /* write the location of the real parent, already computed */ - iso_bb(&PL[4], n->info.dir.real_parent->info.dir.block, 4); + iso_bb(&PL[4], n->info.dir->real_parent->info.dir->block, 4); return susp_append(t, susp, PL); } @@ -243,7 +243,7 @@ int rrip_add_CL(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp) CL[1] = 'L'; CL[2] = 12; CL[3] = 1; - iso_bb(&CL[4], n->info.real_me->info.dir.block, 4); + iso_bb(&CL[4], n->info.real_me->info.dir->block, 4); return susp_append(t, susp, CL); } @@ -547,7 +547,7 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t space, su_size = 44 + 26; if (n->type == ECMA119_DIR) { - if (n->info.dir.real_parent != NULL) { + if (n->info.dir->real_parent != NULL) { /* it is a reallocated entry */ if (type == 2) { /* we need to add a PL entry */ @@ -798,7 +798,7 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type, } if (n->type == ECMA119_DIR) { - if (n->info.dir.real_parent != NULL) { + if (n->info.dir->real_parent != NULL) { /* it is a reallocated entry */ if (type == 2) { /* diff --git a/test/mocked_fsrc.c b/test/mocked_fsrc.c index 618ad17..70d9d4a 100644 --- a/test/mocked_fsrc.c +++ b/test/mocked_fsrc.c @@ -97,6 +97,13 @@ int mfs_stat(IsoFileSource *src, struct stat *info) return ISO_SUCCESS; } +static +int mfs_access(IsoFileSource *src) +{ + // TODO not implemented + return ISO_SUCCESS; +} + static int mfs_open(IsoFileSource *src) { @@ -176,6 +183,7 @@ IsoFileSourceIface mfs_class = { mfs_get_name, mfs_lstat, mfs_stat, + mfs_access, mfs_open, mfs_close, mfs_read,