[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Thu Mar 2 07:39:03 UTC 2017


The branch, master has been updated
       via  70923b7 ndr: Use resizing array instead of linked lists (breaking ABI)
       via  4bd8e63 ndr: fix whitespace in libndr.h, ndr.c
       via  f2614ba selftest: add search performance tests
       via  779ea4c selftest: ndr_pack/unpack performance test
       via  f1b2d35 ndr tests: silence a harmless warning
      from  41204a4 vfs_fruit: enabling AAPL extensions must be a global switch

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 70923b7521786d59b76e651d566bbd61fea024cc
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri Feb 24 11:58:33 2017 +1300

    ndr: Use resizing array instead of linked lists (breaking ABI)
    
    The ndr token code keeps a temporary store of tokens which are
    referred to a small number of times (often once) before being
    discarded. The access patterns are somewhat stack-like, with recently
    placed tokens being accessed most often.
    
    The old code kept these tokens in a linked list, which we replace with
    a self-resizing array.
    
    This keeps everything roughly the same in big-O terms, but makes it
    all faster in practice by vastly reducing the amount of tallocing and
    pointer-chasing.
    
    The peak memory use is strictly reduced. On a 64 bit machine each core
    token struct fits in 16 bytes (after padding) while the two pointers
    used by the DLIST add another 16 bytes, so the overall list allocation
    is the same as the peak 2n array allocation -- except in the list case
    it is dwarfed by the talloc and malloc metadata overhead.
    
    Before settling on the resized arrays, we tried red-black trees, which
    are bound to be better for large ndr structures. As it happens, we
    don't deal with large structures (the size of replication clumps is
    limited to 400 objects) and the asymptotic benefits of the trees are
    not realised in practice.
    
    With luck you should find graphs comparing the performance of these
    various techniques at:
    
    https://www.samba.org/~dbagnall/perf-tests/ndr-token/
    
    This necessarily breaks the ABI because the linked list implementation
    was publicly exposed.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Thu Mar  2 08:38:22 CET 2017 on sn-devel-144

commit 4bd8e63165e180565bda5dcf978ee0d38d3fa13d
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri Feb 24 11:59:24 2017 +1300

    ndr: fix whitespace in libndr.h, ndr.c
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit f2614bae2b5057ff2040e0f89cb87a81e926cc82
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri Feb 24 14:42:32 2017 +1300

    selftest: add search performance tests
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 779ea4c1b5047d546ec7ab91305c97ed9f20cce7
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Feb 16 16:41:00 2017 +1300

    selftest: ndr_pack/unpack performance test
    
    This just does a lot of packing and unpacking of various structures.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit f1b2d356585d43f2bac24d5c32cbef4a90c43f36
Author: Douglas Bagnall <douglas at halo.gen.nz>
Date:   Sat Feb 25 13:38:17 2017 +1300

    ndr tests: silence a harmless warning
    
    gcc 7.
    
    "duplicate ‘const’ declaration specifier [-Wduplicate-decl-specifier]"
    
    Signed-off-by: Douglas Bagnall <douglas at halo.gen.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 librpc/ABI/{ndr-0.0.9.sigs => ndr-0.1.0.sigs}      |   8 +-
 librpc/ndr/libndr.h                                |  72 +++----
 librpc/ndr/ndr.c                                   | 150 +++++++++-----
 librpc/wscript_build                               |   2 +-
 selftest/perf_tests.py                             |  17 ++
 ..._performance.py => ad_dc_search_performance.py} | 221 ++++++++------------
 source4/dsdb/tests/python/ndr_pack_performance.py  | 227 +++++++++++++++++++++
 source4/torture/ndr/string.c                       |  20 +-
 testdata/replication-ndrpack-example.gz            | Bin 0 -> 132871 bytes
 9 files changed, 480 insertions(+), 237 deletions(-)
 copy librpc/ABI/{ndr-0.0.9.sigs => ndr-0.1.0.sigs} (98%)
 copy source4/dsdb/tests/python/{ad_dc_performance.py => ad_dc_search_performance.py} (52%)
 create mode 100644 source4/dsdb/tests/python/ndr_pack_performance.py
 create mode 100644 testdata/replication-ndrpack-example.gz


Changeset truncated at 500 lines:

diff --git a/librpc/ABI/ndr-0.0.9.sigs b/librpc/ABI/ndr-0.1.0.sigs
similarity index 98%
copy from librpc/ABI/ndr-0.0.9.sigs
copy to librpc/ABI/ndr-0.1.0.sigs
index b363b96..80a3faf 100644
--- a/librpc/ABI/ndr-0.0.9.sigs
+++ b/librpc/ABI/ndr-0.1.0.sigs
@@ -251,9 +251,9 @@ ndr_syntax_id_equal: bool (const struct ndr_syntax_id *, const struct ndr_syntax
 ndr_syntax_id_from_string: bool (const char *, struct ndr_syntax_id *)
 ndr_syntax_id_null: uuid = {time_low = 0, time_mid = 0, time_hi_and_version = 0, clock_seq = "\000", node = "\000\000\000\000\000"}, if_version = 0
 ndr_syntax_id_to_string: char *(TALLOC_CTX *, const struct ndr_syntax_id *)
-ndr_token_peek: uint32_t (struct ndr_token_list **, const void *)
-ndr_token_retrieve: enum ndr_err_code (struct ndr_token_list **, const void *, uint32_t *)
-ndr_token_retrieve_cmp_fn: enum ndr_err_code (struct ndr_token_list **, const void *, uint32_t *, comparison_fn_t, bool)
-ndr_token_store: enum ndr_err_code (TALLOC_CTX *, struct ndr_token_list **, const void *, uint32_t)
+ndr_token_peek: uint32_t (struct ndr_token_list *, const void *)
+ndr_token_retrieve: enum ndr_err_code (struct ndr_token_list *, const void *, uint32_t *)
+ndr_token_retrieve_cmp_fn: enum ndr_err_code (struct ndr_token_list *, const void *, uint32_t *, comparison_fn_t, bool)
+ndr_token_store: enum ndr_err_code (TALLOC_CTX *, struct ndr_token_list *, const void *, uint32_t)
 ndr_transfer_syntax_ndr: uuid = {time_low = 2324192516, time_mid = 7403, time_hi_and_version = 4553, clock_seq = "\237\350", node = "\b\000+\020H`"}, if_version = 2
 ndr_transfer_syntax_ndr64: uuid = {time_low = 1903232307, time_mid = 48826, time_hi_and_version = 18743, clock_seq = "\203\031", node = "\265\333\357\234\314\066"}, if_version = 1
diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h
index 7337e86..d6e2e37 100644
--- a/librpc/ndr/libndr.h
+++ b/librpc/ndr/libndr.h
@@ -1,25 +1,25 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
    rpc interface definitions
 
    Copyright (C) Andrew Tridgell 2003
-   
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-/* This is a public header file that is installed as part of Samba. 
- * If you remove any functions or change their signature, update 
+/* This is a public header file that is installed as part of Samba.
+ * If you remove any functions or change their signature, update
  * the so version number. */
 
 #ifndef __LIBNDR_H__
@@ -38,16 +38,17 @@
 
 
 /*
-  this is used by the token store/retrieve code
+  We store the token mapping in an array that is resized as necessary.
 */
+struct ndr_token;
+
 struct ndr_token_list {
-	struct ndr_token_list *next, *prev;
-	const void *key;
-	uint32_t value;
+	struct ndr_token *tokens;
+	uint32_t count;
 };
 
-/* this is the base structure passed to routines that 
-   parse MSRPC formatted data 
+/* this is the base structure passed to routines that
+   parse MSRPC formatted data
 
    note that in Samba4 we use separate routines and structures for
    MSRPC marshalling and unmarshalling. Also note that these routines
@@ -63,12 +64,12 @@ struct ndr_pull {
 	uint32_t relative_highest_offset;
 	uint32_t relative_base_offset;
 	uint32_t relative_rap_convert;
-	struct ndr_token_list *relative_base_list;
+	struct ndr_token_list relative_base_list;
 
-	struct ndr_token_list *relative_list;
-	struct ndr_token_list *array_size_list;
-	struct ndr_token_list *array_length_list;
-	struct ndr_token_list *switch_list;
+	struct ndr_token_list relative_list;
+	struct ndr_token_list array_size_list;
+	struct ndr_token_list array_length_list;
+	struct ndr_token_list switch_list;
 
 	TALLOC_CTX *current_mem_ctx;
 
@@ -84,17 +85,17 @@ struct ndr_push {
 	uint32_t alloc_size;
 	uint32_t offset;
 	bool fixed_buf_size;
-	
+
 	uint32_t relative_base_offset;
 	uint32_t relative_end_offset;
-	struct ndr_token_list *relative_base_list;
+	struct ndr_token_list relative_base_list;
 
-	struct ndr_token_list *switch_list;
-	struct ndr_token_list *relative_list;
-	struct ndr_token_list *relative_begin_list;
-	struct ndr_token_list *nbt_string_list;
-	struct ndr_token_list *dns_string_list;
-	struct ndr_token_list *full_ptr_list;
+	struct ndr_token_list switch_list;
+	struct ndr_token_list relative_list;
+	struct ndr_token_list relative_begin_list;
+	struct ndr_token_list nbt_string_list;
+	struct ndr_token_list dns_string_list;
+	struct ndr_token_list full_ptr_list;
 
 	/* this is used to ensure we generate unique reference IDs */
 	uint32_t ptr_count;
@@ -104,7 +105,7 @@ struct ndr_push {
 struct ndr_print {
 	uint32_t flags; /* LIBNDR_FLAG_* */
 	uint32_t depth;
-	struct ndr_token_list *switch_list;
+	struct ndr_token_list switch_list;
 	void (*print)(struct ndr_print *, const char *, ...) PRINTF_ATTRIBUTE(2,3);
 	void *private_data;
 	bool no_newline;
@@ -463,7 +464,7 @@ void ndr_print_dom_sid0(struct ndr_print *ndr, const char *name, const struct do
 size_t ndr_size_dom_sid0(const struct dom_sid *sid, int flags);
 void ndr_print_GUID(struct ndr_print *ndr, const char *name, const struct GUID *guid);
 void ndr_print_sockaddr_storage(struct ndr_print *ndr, const char *name, const struct sockaddr_storage *ss);
-bool ndr_syntax_id_equal(const struct ndr_syntax_id *i1, const struct ndr_syntax_id *i2); 
+bool ndr_syntax_id_equal(const struct ndr_syntax_id *i1, const struct ndr_syntax_id *i2);
 char *ndr_syntax_id_to_string(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *id);
 bool ndr_syntax_id_from_string(const char *s, struct ndr_syntax_id *id);
 enum ndr_err_code ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, const void *p, ndr_push_flags_fn_t fn);
@@ -508,7 +509,7 @@ void ndr_print_function_debug(ndr_print_function_t fn, const char *name, int fla
 char *ndr_print_struct_string(TALLOC_CTX *mem_ctx, ndr_print_fn_t fn, const char *name, void *ptr);
 char *ndr_print_union_string(TALLOC_CTX *mem_ctx, ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr);
 char *ndr_print_function_string(TALLOC_CTX *mem_ctx,
-				ndr_print_function_t fn, const char *name, 
+				ndr_print_function_t fn, const char *name,
 				int flags, void *ptr);
 void ndr_set_flags(uint32_t *pflags, uint32_t new_flags);
 enum ndr_err_code ndr_pull_error(struct ndr_pull *ndr,
@@ -534,12 +535,13 @@ enum ndr_err_code ndr_push_subcontext_end(struct ndr_push *ndr,
 				 size_t header_size,
 				 ssize_t size_is);
 enum ndr_err_code ndr_token_store(TALLOC_CTX *mem_ctx,
-			 struct ndr_token_list **list, 
-			 const void *key, 
+			 struct ndr_token_list *list,
+			 const void *key,
 			 uint32_t value);
-enum ndr_err_code ndr_token_retrieve_cmp_fn(struct ndr_token_list **list, const void *key, uint32_t *v, int(*_cmp_fn)(const void*,const void*), bool _remove_tok);
-enum ndr_err_code ndr_token_retrieve(struct ndr_token_list **list, const void *key, uint32_t *v);
-uint32_t ndr_token_peek(struct ndr_token_list **list, const void *key);
+enum ndr_err_code ndr_token_retrieve_cmp_fn(struct ndr_token_list *list, const void *key, uint32_t *v,
+					    int(*_cmp_fn)(const void*,const void*), bool erase);
+enum ndr_err_code ndr_token_retrieve(struct ndr_token_list *list, const void *key, uint32_t *v);
+uint32_t ndr_token_peek(struct ndr_token_list *list, const void *key);
 enum ndr_err_code ndr_pull_array_size(struct ndr_pull *ndr, const void *p);
 uint32_t ndr_get_array_size(struct ndr_pull *ndr, const void *p);
 enum ndr_err_code ndr_check_array_size(struct ndr_pull *ndr, void *p, uint32_t size);
@@ -566,7 +568,7 @@ enum ndr_err_code ndr_pull_union_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem
 #define NDR_SCALAR_PROTO(name, type) \
 enum ndr_err_code ndr_push_ ## name(struct ndr_push *ndr, int ndr_flags, type v); \
 enum ndr_err_code ndr_pull_ ## name(struct ndr_pull *ndr, int ndr_flags, type *v); \
-void ndr_print_ ## name(struct ndr_print *ndr, const char *var_name, type v); 
+void ndr_print_ ## name(struct ndr_print *ndr, const char *var_name, type v);
 
 #define NDR_SCALAR_PTR_PROTO(name, type) \
 enum ndr_err_code ndr_push_ ## name(struct ndr_push *ndr, int ndr_flags, const type *v); \
@@ -576,7 +578,7 @@ void ndr_print_ ## name(struct ndr_print *ndr, const char *var_name, const type
 #define NDR_BUFFER_PROTO(name, type) \
 enum ndr_err_code ndr_push_ ## name(struct ndr_push *ndr, int ndr_flags, const type *v); \
 enum ndr_err_code ndr_pull_ ## name(struct ndr_pull *ndr, int ndr_flags, type *v); \
-void ndr_print_ ## name(struct ndr_print *ndr, const char *var_name, const type *v); 
+void ndr_print_ ## name(struct ndr_print *ndr, const char *var_name, const type *v);
 
 NDR_SCALAR_PROTO(uint8, uint8_t)
 NDR_SCALAR_PROTO(int8, int8_t)
diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c
index 22c4d76..1c49c9a 100644
--- a/librpc/ndr/ndr.c
+++ b/librpc/ndr/ndr.c
@@ -138,11 +138,11 @@ _PUBLIC_ enum ndr_err_code ndr_pull_pop(struct ndr_pull *ndr)
 		return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
 				      "%s", __location__);
 	}
-	if (ndr->relative_list != NULL) {
+	if (ndr->relative_list.count != 0) {
 		return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
 				      "%s", __location__);
 	}
-	if (ndr->relative_base_list != NULL) {
+	if (ndr->relative_base_list.count != 0) {
 		return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
 				      "%s", __location__);
 	}
@@ -187,7 +187,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_advance(struct ndr_pull *ndr, uint32_t size)
 {
 	ndr->offset += size;
 	if (ndr->offset > ndr->data_size) {
-		return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, 
+		return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
 				      "ndr_pull_advance by %u failed",
 				      size);
 	}
@@ -201,7 +201,7 @@ static enum ndr_err_code ndr_pull_set_offset(struct ndr_pull *ndr, uint32_t ofs)
 {
 	ndr->offset = ofs;
 	if (ndr->offset > ndr->data_size) {
-		return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, 
+		return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
 				      "ndr_pull_set_offset %u failed",
 				      ofs);
 	}
@@ -264,7 +264,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_expand(struct ndr_push *ndr, uint32_t extra_
 				      "push_expand to %u",
 				      size);
 	}
-	
+
 	if (ndr->alloc_size > size) {
 		return NDR_ERR_SUCCESS;
 	}
@@ -314,7 +314,7 @@ _PUBLIC_ void ndr_print_debugc_helper(struct ndr_print *ndr, const char *format,
 	free(s);
 }
 
-_PUBLIC_ void ndr_print_debug_helper(struct ndr_print *ndr, const char *format, ...) 
+_PUBLIC_ void ndr_print_debug_helper(struct ndr_print *ndr, const char *format, ...)
 {
 	va_list ap;
 	char *s = NULL;
@@ -343,7 +343,7 @@ _PUBLIC_ void ndr_print_debug_helper(struct ndr_print *ndr, const char *format,
 	free(s);
 }
 
-_PUBLIC_ void ndr_print_printf_helper(struct ndr_print *ndr, const char *format, ...) 
+_PUBLIC_ void ndr_print_printf_helper(struct ndr_print *ndr, const char *format, ...)
 {
 	va_list ap;
 	uint32_t i;
@@ -375,7 +375,7 @@ _PUBLIC_ void ndr_print_string_helper(struct ndr_print *ndr, const char *format,
 	}
 
 	va_start(ap, format);
-	ndr->private_data = talloc_vasprintf_append_buffer((char *)ndr->private_data, 
+	ndr->private_data = talloc_vasprintf_append_buffer((char *)ndr->private_data,
 						    format, ap);
 	va_end(ap);
 	if (!ndr->no_newline) {
@@ -513,7 +513,7 @@ failed:
   a useful helper function for printing idl function calls to a string
 */
 _PUBLIC_ char *ndr_print_function_string(TALLOC_CTX *mem_ctx,
-				ndr_print_function_t fn, const char *name, 
+				ndr_print_function_t fn, const char *name,
 				int flags, void *ptr)
 {
 	struct ndr_print *ndr;
@@ -598,7 +598,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_error(struct ndr_pull *ndr,
 */
 _PUBLIC_ enum ndr_err_code ndr_push_error(struct ndr_push *ndr,
 				 enum ndr_err_code ndr_err,
-				 const char *format, ...) 
+				 const char *format, ...)
 {
 	char *s=NULL;
 	va_list ap;
@@ -754,7 +754,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_start(struct ndr_pull *ndr,
 		return NDR_ERR_SUCCESS;
 
 	default:
-		return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) header_size %d", 
+		return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) header_size %d",
 				      (int)header_size);
 	}
 
@@ -840,7 +840,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_subcontext_start(struct ndr_push *ndr,
 }
 
 /*
-  push a subcontext header 
+  push a subcontext header
 */
 _PUBLIC_ enum ndr_err_code ndr_push_subcontext_end(struct ndr_push *ndr,
 				 struct ndr_push *subndr,
@@ -859,14 +859,14 @@ _PUBLIC_ enum ndr_err_code ndr_push_subcontext_end(struct ndr_push *ndr,
 	}
 
 	switch (header_size) {
-	case 0: 
+	case 0:
 		break;
 
-	case 2: 
+	case 2:
 		NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, subndr->offset));
 		break;
 
-	case 4: 
+	case 4:
 		NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, subndr->offset));
 		break;
 
@@ -906,7 +906,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_subcontext_end(struct ndr_push *ndr,
 		break;
 
 	default:
-		return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext header size %d", 
+		return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext header size %d",
 				      (int)header_size);
 	}
 
@@ -914,40 +914,78 @@ _PUBLIC_ enum ndr_err_code ndr_push_subcontext_end(struct ndr_push *ndr,
 	return NDR_ERR_SUCCESS;
 }
 
+
+struct ndr_token {
+	const void *key;
+	uint32_t value;
+};
+
 /*
   store a token in the ndr context, for later retrieval
 */
 _PUBLIC_ enum ndr_err_code ndr_token_store(TALLOC_CTX *mem_ctx,
-			 struct ndr_token_list **list, 
-			 const void *key, 
+			 struct ndr_token_list *list,
+			 const void *key,
 			 uint32_t value)
 {
-	struct ndr_token_list *tok;
-	tok = talloc(mem_ctx, struct ndr_token_list);
-	NDR_ERR_HAVE_NO_MEMORY(tok);
-	tok->key = key;
-	tok->value = value;
-	DLIST_ADD((*list), tok);
+	if (list->tokens == NULL) {
+		list->tokens = talloc_array(mem_ctx, struct ndr_token, 10);
+		if (list->tokens == NULL) {
+			NDR_ERR_HAVE_NO_MEMORY(list->tokens);
+		}
+	} else {
+		uint32_t alloc_count = talloc_array_length(list->tokens);
+		if (list->count == alloc_count) {
+			unsigned new_alloc;
+			unsigned increment = MIN(list->count, 1000);
+			new_alloc = alloc_count + increment;
+			if (new_alloc < alloc_count) {
+				return NDR_ERR_RANGE;
+			}
+			list->tokens = talloc_realloc(mem_ctx, list->tokens,
+						      struct ndr_token, new_alloc);
+			if (list->tokens == NULL) {
+				NDR_ERR_HAVE_NO_MEMORY(list->tokens);
+			}
+		}
+	}
+	list->tokens[list->count].key = key;
+	list->tokens[list->count].value = value;
+	list->count++;
 	return NDR_ERR_SUCCESS;
 }
 
 /*
   retrieve a token from a ndr context, using cmp_fn to match the tokens
 */
-_PUBLIC_ enum ndr_err_code ndr_token_retrieve_cmp_fn(struct ndr_token_list **list, const void *key, uint32_t *v,
-				   comparison_fn_t _cmp_fn, bool _remove_tok)
-{
-	struct ndr_token_list *tok;
-	for (tok=*list;tok;tok=tok->next) {
-		if (_cmp_fn && _cmp_fn(tok->key,key)==0) goto found;
-		else if (!_cmp_fn && tok->key == key) goto found;
+_PUBLIC_ enum ndr_err_code ndr_token_retrieve_cmp_fn(struct ndr_token_list *list,
+						     const void *key, uint32_t *v,
+						     comparison_fn_t _cmp_fn,
+						     bool erase)
+{
+	struct ndr_token *tokens = list->tokens;
+	unsigned i;
+	if (_cmp_fn) {
+		for (i = list->count - 1; i < list->count; i--) {
+			if (_cmp_fn(tokens[i].key, key) == 0) {
+				goto found;
+			}
+		}
+	} else {
+		for (i = list->count - 1; i < list->count; i--) {
+			if (tokens[i].key == key) {
+				goto found;
+			}
+		}
 	}
 	return NDR_ERR_TOKEN;
 found:
-	*v = tok->value;
-	if (_remove_tok) {
-		DLIST_REMOVE((*list), tok);
-		talloc_free(tok);
+	*v = tokens[i].value;
+	if (erase) {
+		if (i != list->count - 1) {
+			tokens[i] = tokens[list->count - 1];
+		}
+		list->count--;
 	}
 	return NDR_ERR_SUCCESS;
 }
@@ -955,7 +993,8 @@ found:
 /*
   retrieve a token from a ndr context
 */
-_PUBLIC_ enum ndr_err_code ndr_token_retrieve(struct ndr_token_list **list, const void *key, uint32_t *v)
+_PUBLIC_ enum ndr_err_code ndr_token_retrieve(struct ndr_token_list *list,
+					      const void *key, uint32_t *v)
 {
 	return ndr_token_retrieve_cmp_fn(list, key, v, NULL, true);
 }
@@ -963,14 +1002,17 @@ _PUBLIC_ enum ndr_err_code ndr_token_retrieve(struct ndr_token_list **list, cons
 /*
   peek at but don't removed a token from a ndr context
 */
-_PUBLIC_ uint32_t ndr_token_peek(struct ndr_token_list **list, const void *key)
+_PUBLIC_ uint32_t ndr_token_peek(struct ndr_token_list *list, const void *key)
 {
-	struct ndr_token_list *tok;
-	for (tok = *list; tok; tok = tok->next) {
-		if (tok->key == key) {
-			return tok->value;
+	unsigned i;
+	struct ndr_token *tokens = list->tokens;
+
+	for (i = list->count - 1; i < list->count; i--) {
+		if (tokens[i].key == key) {
+			return tokens[i].value;
 		}
 	}
+
 	return 0;
 }
 
@@ -1000,7 +1042,7 @@ _PUBLIC_ enum ndr_err_code ndr_check_array_size(struct ndr_pull *ndr, void *p, u
 	uint32_t stored;
 	stored = ndr_token_peek(&ndr->array_size_list, p);
 	if (stored != size) {
-		return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, 
+		return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
 				      "Bad array size - got %u expected %u\n",
 				      stored, size);
 	}
@@ -1015,7 +1057,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_array_length(struct ndr_pull *ndr, const voi
 	uint32_t length, offset;
 	NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &offset));
 	if (offset != 0) {
-		return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, 
+		return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
 				      "non-zero array offset %u\n", offset);
 	}
 	NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &length));
@@ -1038,7 +1080,7 @@ _PUBLIC_ enum ndr_err_code ndr_check_array_length(struct ndr_pull *ndr, void *p,
 	uint32_t stored;
 	stored = ndr_token_peek(&ndr->array_length_list, p);
 	if (stored != length) {
-		return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, 
+		return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
 				      "Bad array length - got %u expected %u\n",
 				      stored, length);
 	}
@@ -1146,7 +1188,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CT
 /*
   pull a struct from a blob using NDR - failing if all bytes are not consumed
 */
-_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, 
+_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
 						    void *p, ndr_pull_flags_fn_t fn)
 {
 	struct ndr_pull *ndr;
@@ -1213,7 +1255,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all_noalloc(const DATA_BLOB *blo
 /*
   pull a union from a blob using NDR, given the union discriminator
 */
-_PUBLIC_ enum ndr_err_code ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, 
+_PUBLIC_ enum ndr_err_code ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
 					       void *p,
 			     uint32_t level, ndr_pull_flags_fn_t fn)
 {


-- 
Samba Shared Repository



More information about the samba-cvs mailing list