From 41f4642b858a8225f4442c098344318bcc3fbfe1 Mon Sep 17 00:00:00 2001 From: shankar Date: Tue, 23 Mar 2010 13:22:09 +0000 Subject: Refactor to increase performace git-svn-id: http://svn.apache.org/repos/asf/axis/axis2/c/core/trunk@926564 13f79535-47bb-0310-9956-ffa450edef68 --- axiom/src/om/axiom_node_internal.h | 43 +++-- axiom/src/om/axiom_stax_builder_internal.h | 5 + axiom/src/om/om_node.c | 131 ++++++++------- axiom/src/om/om_stax_builder.c | 246 ++++++++++++++++------------- 4 files changed, 243 insertions(+), 182 deletions(-) (limited to 'axiom/src/om') diff --git a/axiom/src/om/axiom_node_internal.h b/axiom/src/om/axiom_node_internal.h index 6e9adb4..b266bb5 100644 --- a/axiom/src/om/axiom_node_internal.h +++ b/axiom/src/om/axiom_node_internal.h @@ -49,7 +49,7 @@ extern "C" * @param parent_node the node that will be set as parent. , cannot be NULL. * @return satus of the op. AXIS2_SUCCESS on success else AXIS2_FAILURE */ - AXIS2_EXTERN axis2_status_t AXIS2_CALL + axis2_status_t AXIS2_CALL axiom_node_set_parent( axiom_node_t * om_node, const axutil_env_t * env, @@ -61,7 +61,7 @@ extern "C" * @param env environment, MUST NOT be NULL. * @param first_child child to be set as first child */ - AXIS2_EXTERN axis2_status_t AXIS2_CALL + axis2_status_t AXIS2_CALL axiom_node_set_first_child( axiom_node_t * om_node, const axutil_env_t * env, @@ -75,7 +75,7 @@ extern "C" * @return status of the op, AXIS2_SUCCESS on success * AXIS2_FAILURE on error */ - AXIS2_EXTERN axis2_status_t AXIS2_CALL + axis2_status_t AXIS2_CALL axiom_node_set_previous_sibling( axiom_node_t * om_node, const axutil_env_t * env, @@ -89,7 +89,7 @@ extern "C" * @return status of the op, AXIS2_SUCCESS on success, * AXIS2_FAILURE on error */ - AXIS2_EXTERN axis2_status_t AXIS2_CALL + axis2_status_t AXIS2_CALL axiom_node_set_next_sibling( axiom_node_t * om_node, const axutil_env_t * env, @@ -103,7 +103,7 @@ extern "C" * @return status code of the op AXIS2_SUCCESS on success, * AXIS2_FAILURE on error */ - AXIS2_EXTERN axis2_status_t AXIS2_CALL + axis2_status_t AXIS2_CALL axiom_node_set_node_type( axiom_node_t * om_node, const axutil_env_t * env, @@ -117,7 +117,7 @@ extern "C" * @return status code of the op AXIS2_SUCCESS on success, * AXIS2_FAILURE on error */ - AXIS2_EXTERN axis2_status_t AXIS2_CALL + axis2_status_t AXIS2_CALL axiom_node_set_data_element( axiom_node_t * om_node, const axutil_env_t * env, @@ -130,12 +130,29 @@ extern "C" * @param env environment, MUST NOT be NULL. * @param done */ - AXIS2_EXTERN axis2_status_t AXIS2_CALL + axis2_status_t AXIS2_CALL axiom_node_set_complete( axiom_node_t * om_node, const axutil_env_t * env, axis2_bool_t done); + /** + * Sets the builder + */ + axis2_status_t AXIS2_CALL + axiom_node_set_builder( + axiom_node_t * om_node, + const axutil_env_t * env, + struct axiom_stax_builder *builder); + + void AXIS2_CALL + axiom_node_assume_builder_ownership( + axiom_node_t *om_node, + const axutil_env_t * env); + + + +#if 0 /** * This functions is only to be used by builder * do not use this function @@ -146,14 +163,12 @@ extern "C" const axutil_env_t * env, struct axiom_document *om_doc); - /** - * Sets the builder - */ - AXIS2_EXTERN axis2_status_t AXIS2_CALL - axiom_node_set_builder( + AXIS2_EXTERN struct axiom_stax_builder *AXIS2_CALL + axiom_node_get_builder( axiom_node_t * om_node, - const axutil_env_t * env, - struct axiom_stax_builder *builder); + const axutil_env_t * env); + +#endif /** @} */ diff --git a/axiom/src/om/axiom_stax_builder_internal.h b/axiom/src/om/axiom_stax_builder_internal.h index 31344d5..7bb9abe 100644 --- a/axiom/src/om/axiom_stax_builder_internal.h +++ b/axiom/src/om/axiom_stax_builder_internal.h @@ -66,6 +66,11 @@ extern "C" axiom_stax_builder_t * builder, const axutil_env_t * env); + /* this will be called from root node to free the stax builder */ + void AXIS2_CALL + axiom_stax_builder_free_internal( + axiom_stax_builder_t * builder, + const axutil_env_t * env); /** diff --git a/axiom/src/om/om_node.c b/axiom/src/om/om_node.c index 9b525aa..70fb8aa 100644 --- a/axiom/src/om/om_node.c +++ b/axiom/src/om/om_node.c @@ -28,12 +28,12 @@ struct axiom_node { - - /** document only available if build through builder */ - struct axiom_document *om_doc; - + /* stax builder */ axiom_stax_builder_t *builder; + /* whether current node is the owner of stax builder. If so, it has to free it */ + axis2_bool_t own_builder; + /** parent node */ axiom_node_t *parent; @@ -60,11 +60,6 @@ struct axiom_node }; -static axiom_node_t * -axiom_node_detach_without_namespaces( - axiom_node_t * om_node, - const axutil_env_t * env); - AXIS2_EXTERN axiom_node_t *AXIS2_CALL axiom_node_create( const axutil_env_t * env) @@ -86,8 +81,8 @@ axiom_node_create( node->node_type = AXIOM_INVALID; node->done = AXIS2_FALSE; node->data_element = NULL; - node->om_doc = NULL; node->builder = NULL; + node->own_builder = AXIS2_FALSE; return node; } @@ -195,8 +190,6 @@ axiom_node_free_detached_subtree( } AXIS2_FREE(env->allocator, om_node); - - return; } /** @@ -217,10 +210,14 @@ axiom_node_free_tree( /* Detach this node before freeing it and its subtree. */ axiom_node_detach_without_namespaces(om_node, env); + /* if the owner of the builder, then free the builder */ + if(om_node->own_builder) + { + axiom_stax_builder_free_internal(om_node->builder, env); + } + /* Free this node and its subtree */ axiom_node_free_detached_subtree(om_node, env); - - return; } AXIS2_EXTERN axis2_status_t AXIS2_CALL @@ -259,10 +256,13 @@ axiom_node_add_child( } /** - * Detach the node without regard to any namespace references in the node or - * its children. + * Detaches given node from the parent and reset the links. will not adjust the namespace as + * in the case of axiom_node_detach. + * @param om_node node to be detached, cannot be NULL. + * @param env Environment. MUST NOT be NULL, . + * @return a pointer to detached node,returns NULL on error */ -static axiom_node_t * +AXIS2_EXTERN axiom_node_t *AXIS2_CALL axiom_node_detach_without_namespaces( axiom_node_t * om_node, const axutil_env_t * env) @@ -273,7 +273,6 @@ axiom_node_detach_without_namespaces( if(!parent) { /* Node is already detached */ - om_node->builder = NULL; return om_node; } @@ -326,6 +325,13 @@ axiom_node_detach_without_namespaces( return om_node; } +/** + * Detaches given node from the parent and reset the links. Will recreate "namespace defined in + * the parent and used in detached node" within detached node itself + * @param om_node node to be detached, cannot be NULL. + * @param env Environment. MUST NOT be NULL, . + * @return a pointer to detached node,returns NULL on error + */ AXIS2_EXTERN axiom_node_t *AXIS2_CALL axiom_node_detach( axiom_node_t * om_node, @@ -370,7 +376,7 @@ axiom_node_detach( Internal function , only used in om and soap not to be used by users */ -AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_status_t AXIS2_CALL axiom_node_set_parent( axiom_node_t * om_node, const axutil_env_t * env, @@ -1182,7 +1188,12 @@ axiom_node_get_document( axiom_node_t * om_node, const axutil_env_t * env) { - return om_node->om_doc; + if(om_node->builder) + { + return axiom_stax_builder_get_document(om_node->builder, env); + } + + return NULL; } AXIS2_EXTERN void *AXIS2_CALL @@ -1197,7 +1208,7 @@ axiom_node_get_data_element( internal function , not to be used by users only sets the first_child link because this is needed by builder */ -AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_status_t AXIS2_CALL axiom_node_set_first_child( axiom_node_t * om_node, const axutil_env_t * env, @@ -1219,7 +1230,7 @@ axiom_node_set_first_child( only sets the previous sibling link as it is needed by builders */ -AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_status_t AXIS2_CALL axiom_node_set_previous_sibling( axiom_node_t * om_node, const axutil_env_t * env, @@ -1238,7 +1249,7 @@ axiom_node_set_previous_sibling( internal function, not to be used by users only sets the next sibling link; */ -AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_status_t AXIS2_CALL axiom_node_set_next_sibling( axiom_node_t * om_node, const axutil_env_t * env, @@ -1256,7 +1267,7 @@ axiom_node_set_next_sibling( sets the node type only used in soap and om */ -AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_status_t AXIS2_CALL axiom_node_set_node_type( axiom_node_t * om_node, const axutil_env_t * env, @@ -1273,7 +1284,7 @@ axiom_node_set_node_type( internal function , not to be used by users only used in om and soap */ -AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_status_t AXIS2_CALL axiom_node_set_data_element( axiom_node_t * om_node, const axutil_env_t * env, @@ -1291,7 +1302,7 @@ axiom_node_set_data_element( only sets the build status */ -AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_status_t AXIS2_CALL axiom_node_set_complete( axiom_node_t * om_node, const axutil_env_t * env, @@ -1303,50 +1314,27 @@ axiom_node_set_complete( return AXIS2_SUCCESS; } -/** - internal function not to be used by users - only used by om builder - - */ -AXIS2_EXTERN axis2_status_t AXIS2_CALL -axiom_node_set_document( - axiom_node_t * om_node, - const axutil_env_t * env, - struct axiom_document * om_doc) -{ - AXIS2_PARAM_CHECK(env->error, om_node, AXIS2_FAILURE); - om_node->om_doc = om_doc; - return AXIS2_SUCCESS; -} - /** internal function only sets the builder reference , should not be used by user */ -AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_status_t AXIS2_CALL axiom_node_set_builder( axiom_node_t * om_node, const axutil_env_t * env, axiom_stax_builder_t * builder) { - AXIS2_PARAM_CHECK(env->error, om_node, AXIS2_FAILURE); + /* builder == NULL is a valid case */ om_node->builder = builder; return AXIS2_SUCCESS; } -/** - * This is an internal function - */ -AXIS2_EXTERN axiom_stax_builder_t *AXIS2_CALL -axiom_node_get_builder( - axiom_node_t * om_node, +void AXIS2_CALL +axiom_node_assume_builder_ownership( + axiom_node_t *om_node, const axutil_env_t * env) { - if(!om_node) - { - return NULL; - } - return om_node->builder; + om_node->own_builder = AXIS2_TRUE; } AXIS2_EXTERN axis2_char_t *AXIS2_CALL @@ -1453,3 +1441,36 @@ axiom_node_to_string_non_optimized( return xml; } +#if 0 + +/** + internal function not to be used by users + only used by om builder + */ +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axiom_node_set_document( + axiom_node_t * om_node, + const axutil_env_t * env, + struct axiom_document * om_doc) +{ + /* om_doc == NULL is a valid case */ + om_node->om_doc = om_doc; + return AXIS2_SUCCESS; +} + +/** + * This is an internal function + */ +AXIS2_EXTERN axiom_stax_builder_t *AXIS2_CALL +axiom_node_get_builder( + axiom_node_t * om_node, + const axutil_env_t * env) +{ + if(!om_node) + { + return NULL; + } + return om_node->builder; +} + +#endif diff --git a/axiom/src/om/om_stax_builder.c b/axiom/src/om/om_stax_builder.c index a8cfa88..60d4fcc 100644 --- a/axiom/src/om/om_stax_builder.c +++ b/axiom/src/om/om_stax_builder.c @@ -53,13 +53,25 @@ struct axiom_stax_builder axutil_hash_t *declared_namespaces; }; +/** + * Creates an stax builder + * @param environment Environment. MUST NOT be NULL. + * @param parser parser to be used with builder. The builder will take ownership of the parser. + * @return a pointer to the newly created builder struct. + */ AXIS2_EXTERN axiom_stax_builder_t *AXIS2_CALL axiom_stax_builder_create( const axutil_env_t * env, axiom_xml_reader_t * parser) { axiom_stax_builder_t *om_builder = NULL; - AXIS2_PARAM_CHECK(env->error, parser, NULL); + + if(!parser) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_NULL_PARAM, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Invalid xml parser given for stax builder"); + return NULL; + } om_builder = (axiom_stax_builder_t *)AXIS2_MALLOC(env->allocator, sizeof(axiom_stax_builder_t)); if(!om_builder) @@ -69,144 +81,85 @@ axiom_stax_builder_create( return NULL; } - om_builder->done = AXIS2_FALSE; - om_builder->lastnode = NULL; - om_builder->document = NULL; - om_builder->parser = parser; - om_builder->current_event = -1; - om_builder->root_node = NULL; - om_builder->element_level = 0; - om_builder->declared_namespaces = axutil_hash_make(env); om_builder->document = axiom_document_create(env, NULL, om_builder); if(!om_builder->document) { AXIS2_FREE(env->allocator, om_builder); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Unable to create axiom document"); return NULL; } + om_builder->declared_namespaces = axutil_hash_make(env); + if(!om_builder->declared_namespaces) + { + AXIS2_FREE(env->allocator, om_builder); + axiom_document_free(om_builder->document, env); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Unable to create namespace hashmap"); + return NULL; + } + + om_builder->done = AXIS2_FALSE; + om_builder->lastnode = NULL; + om_builder->parser = parser; + om_builder->current_event = -1; + om_builder->root_node = NULL; + om_builder->element_level = 0; return om_builder; } +/** + * Free the build struct instance and its associated document,axiom tree. + * @param builder pointer to builder struct + * @param env environment, MUST NOT be NULL + * @return status of the operation AXIS2_SUCCESS on success, AXIS2_FAILURE on error. + */ AXIS2_EXTERN void AXIS2_CALL axiom_stax_builder_free( axiom_stax_builder_t * om_builder, const axutil_env_t * env) { - if(!om_builder) - { - return; - } - if(om_builder->declared_namespaces) - { - axutil_hash_free(om_builder->declared_namespaces, env); - om_builder->declared_namespaces = NULL; - } - - if(om_builder->document) - { - axiom_document_free(om_builder->document, env); - om_builder->document = NULL; - } - else - { - if(om_builder->root_node) - { - axiom_node_free_tree(om_builder->root_node, env); - om_builder->root_node = NULL; - } - } - - if(om_builder->parser) - { - axiom_xml_reader_free(om_builder->parser, env); - om_builder->parser = NULL; - } - + axutil_hash_free(om_builder->declared_namespaces, env); + axiom_document_free(om_builder->document, env); + axiom_xml_reader_free(om_builder->parser, env); AXIS2_FREE(env->allocator, om_builder); +} - return; +/* this will be called from root node to free the stax builder */ +void AXIS2_CALL +axiom_stax_builder_free_internal( + axiom_stax_builder_t * om_builder, + const axutil_env_t * env) +{ + axutil_hash_free(om_builder->declared_namespaces, env); + axiom_xml_reader_free(om_builder->parser, env); + axiom_document_free_self(om_builder->document, env); + AXIS2_FREE(env->allocator, om_builder); } +/** + * Give the responsibility of freeing the stax builder to the root node. This method will not + * free anything. When the root node is freed, it will call axiom_stax_builder_free_internal + * which will free the stax builder, document and xml reader. + * @param builder pointer to builder struct + * @param env environment, MUST NOT be NULL + * @return status of the operation AXIS2_SUCCESS on success, AXIS2_FAILURE on error. + */ AXIS2_EXTERN void AXIS2_CALL axiom_stax_builder_free_self( axiom_stax_builder_t * om_builder, const axutil_env_t * env) { - - axiom_node_t *temp_node = NULL; - axiom_node_t *nodes[256]; - axiom_node_t *om_node = NULL; - int count = 0; - - om_node = om_builder->root_node; - - nodes[count++] = om_node; - - if(om_node) - { - do - { - - axiom_node_set_builder(om_node, env, NULL); - axiom_node_set_document(om_node, env, NULL); - - temp_node = axiom_node_get_first_child(om_node, env); - /* serialize children of this node */ - if(temp_node) - { - om_node = temp_node; - nodes[count++] = om_node; - } - else - { - temp_node = axiom_node_get_next_sibling(om_node, env); - if(temp_node) - { - om_node = temp_node; - nodes[count - 1] = om_node; - } - else - { - while(count > 1 && !temp_node) - { - count--; - om_node = nodes[count - 1]; - temp_node = axiom_node_get_next_sibling(om_node, env); - } - if(temp_node && count > 1) - { - om_node = temp_node; - nodes[count - 1] = om_node; - } - else - { - count--; - } - } - } - } - while(count > 0); - } - if(om_builder->declared_namespaces) - { - axutil_hash_free(om_builder->declared_namespaces, env); - om_builder->declared_namespaces = NULL; - } - - if(om_builder->parser) + if(om_builder->root_node) { - axiom_xml_reader_free(om_builder->parser, env); - om_builder->parser = NULL; + axiom_node_assume_builder_ownership(om_builder->root_node, env); } - if(om_builder->document) - { - axiom_document_free_self(om_builder->document, env); - om_builder->document = NULL; - } - AXIS2_FREE(env->allocator, om_builder); - return; } +/** Gets the document associated with the builder + * @param builder axiom_stax_builder + * @param env environment + * @return pointer to document struct associated with builder NULL if an error occurred. + */ AXIS2_EXTERN axiom_document_t *AXIS2_CALL axiom_stax_builder_get_document( axiom_stax_builder_t * om_builder, @@ -531,7 +484,6 @@ axiom_stax_builder_create_om_element( } axiom_node_set_builder(element_node, env, om_builder); - axiom_node_set_document(element_node, env, om_builder->document); axiom_element_set_is_empty(om_ele, env, is_empty); /* order of processing name spaces first (before processing attributes) is important */ @@ -583,7 +535,6 @@ axiom_stax_builder_create_om_comment( axiom_xml_reader_xml_free(om_builder->parser,env,comment_value); axiom_node_set_builder(comment_node, env, om_builder); - axiom_node_set_document(comment_node, env, om_builder->document); om_builder->element_level++; om_builder->lastnode = comment_node; @@ -1053,4 +1004,73 @@ axiom_stax_builder_next( while(!node && !axiom_node_is_complete(om_builder->root_node, env)); return node; } + +AXIS2_EXTERN void AXIS2_CALL +axiom_stax_builder_free_self_original( + axiom_stax_builder_t * om_builder, + const axutil_env_t * env) +{ + + axiom_node_t *temp_node = NULL; + axiom_node_t *nodes[256]; + axiom_node_t *om_node = NULL; + int count = 0; + + om_node = om_builder->root_node; + + nodes[count++] = om_node; + + if(om_node) + { + do + { + + axiom_node_set_builder(om_node, env, NULL); + + temp_node = axiom_node_get_first_child(om_node, env); + if(temp_node) + { + /* process the child node */ + om_node = temp_node; + nodes[count++] = om_node; + } + else + { + /* no child node. check whether current node has any siblings */ + temp_node = axiom_node_get_next_sibling(om_node, env); + if(temp_node) + { + /* process sibling nodes */ + om_node = temp_node; + nodes[count - 1] = om_node; + } + else + { + /* no siblings. so fallback to parent of current node and process */ + while(count > 1 && !temp_node) + { + count--; + om_node = nodes[count - 1]; + temp_node = axiom_node_get_next_sibling(om_node, env); + } + if(temp_node && count > 1) + { + om_node = temp_node; + nodes[count - 1] = om_node; + } + else + { + count--; + } + } + } + } + while(count > 0); + } + + axutil_hash_free(om_builder->declared_namespaces, env); + axiom_xml_reader_free(om_builder->parser, env); + axiom_document_free_self(om_builder->document, env); + AXIS2_FREE(env->allocator, om_builder); +} #endif -- cgit v1.1-32-gdbae