svn commit: samba r2675 - in branches/SAMBA_4_0/source: lib rpc_server/samr

tridge at samba.org tridge at samba.org
Mon Sep 27 05:13:00 GMT 2004


Author: tridge
Date: 2004-09-27 05:13:00 +0000 (Mon, 27 Sep 2004)
New Revision: 2675

WebSVN: http://websvn.samba.org/websvn/changeset.php?rep=samba&path=/branches/SAMBA_4_0/source&rev=2675&nolog=1

Log:
added a convenience function 

  void *talloc_reference(const void *context, const void *ptr);

this function makes a secondary reference to ptr, and hangs it off the
given context. This greatly simplifies some of the current reference
counting code in the samr server and I suspect it will be widely used
in other places too.

the way you use it is like this:

	domain_state->connect_state = talloc_reference(domain_state, connect_state);

that makes the element connect_state of domain_state a secondary
reference to connect_state. The connect_state structure will then only
be freed when both domain_state and the original connect_state go
away, allowing you to free them independently and in any order.

you could do this alrady using a talloc destructor, and that is what
the samr server did previously, but that meant this construct was
being reinvented in several places. So this convenience function sets
up the destructor for you, giving a much more convenient and less
error prone API.

Modified:
   branches/SAMBA_4_0/source/lib/talloc.c
   branches/SAMBA_4_0/source/rpc_server/samr/dcesrv_samr.c


Changeset:
Modified: branches/SAMBA_4_0/source/lib/talloc.c
===================================================================
--- branches/SAMBA_4_0/source/lib/talloc.c	2004-09-27 04:20:18 UTC (rev 2674)
+++ branches/SAMBA_4_0/source/lib/talloc.c	2004-09-27 05:13:00 UTC (rev 2675)
@@ -124,8 +124,43 @@
 	tc->ref_count++;
 }
 
+/*
+  helper for talloc_reference()
+*/
+static int talloc_reference_destructor(void *ptr)
+{
+	void **handle = ptr;
+	talloc_free(*handle);
+	return 0;
+}
 
 /*
+  make a secondary reference to a pointer, hanging off the given context.
+  the pointer remains valid until both the original caller and this given
+  context are freed.
+  
+  the major use for this is when two different structures need to reference the 
+  same underlying data, and you want to be able to free the two instances separately,
+  and in either order
+*/
+void *talloc_reference(const void *context, const void *ptr)
+{
+	void **handle;
+	handle = _talloc(context, sizeof(void *));
+	if (handle == NULL) {
+		return NULL;
+	}
+	/* note that we hang the destructor off the handle, not the
+	   main context as that allows the caller to still setup their
+	   own destructor on the context if they want to */
+	talloc_set_destructor(handle, talloc_reference_destructor);
+	talloc_increase_ref_count(ptr);
+	*handle = discard_const(ptr);
+	return *handle;
+}
+
+
+/*
   add a name to an existing pointer - va_list version
 */
 static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);

Modified: branches/SAMBA_4_0/source/rpc_server/samr/dcesrv_samr.c
===================================================================
--- branches/SAMBA_4_0/source/rpc_server/samr/dcesrv_samr.c	2004-09-27 04:20:18 UTC (rev 2674)
+++ branches/SAMBA_4_0/source/rpc_server/samr/dcesrv_samr.c	2004-09-27 05:13:00 UTC (rev 2675)
@@ -27,7 +27,7 @@
 
 
 /*
-  destroy a general handle. This relies on the talloc destructor being set up correctly
+  destroy a general handle. 
 */
 static void samr_handle_destroy(struct dcesrv_connection *conn, struct dcesrv_handle *h)
 {
@@ -256,18 +256,6 @@
 }
 
 
-/*
-  close an open domain context
-*/
-static int samr_Domain_destructor(void *ptr)
-{
-	struct samr_domain_state *d_state = ptr;
-	/* we need to explicitly free the connect state to lower the
-	   reference count */
-	talloc_free(d_state->connect_state);
-	return 0;
-}
-
 /* 
   samr_OpenDomain 
 */
@@ -315,7 +303,7 @@
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	d_state->connect_state = c_state;
+	d_state->connect_state = talloc_reference(d_state, c_state);
 	d_state->sam_ctx = c_state->sam_ctx;
 	d_state->domain_sid = talloc_strdup(d_state, sidstr);
 	d_state->domain_name = talloc_strdup(d_state, domain_name);
@@ -331,9 +319,7 @@
 		talloc_free(d_state);
 		return NT_STATUS_NO_MEMORY;
 	}
-	talloc_set_destructor(d_state, samr_Domain_destructor);
-	talloc_increase_ref_count(c_state);
-
+	
 	h_domain->data = d_state;
 	h_domain->destroy = samr_handle_destroy;
 	*r->out.domain_handle = h_domain->wire_handle;
@@ -417,18 +403,6 @@
 	DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 }
 
-/*
-  close an open domain context
-*/
-static int samr_Account_destructor(void *ptr)
-{
-	struct samr_account_state *a_state = ptr;
-	/* we need to explicitly free the domain state to lower the
-	   reference count */
-	talloc_free(a_state->domain_state);
-	return 0;
-}
-
 /* 
   samr_CreateDomainGroup 
 */
@@ -526,11 +500,12 @@
 	}
 	a_state->sam_ctx = d_state->sam_ctx;
 	a_state->access_mask = r->in.access_mask;
-	a_state->domain_state = d_state;
+	a_state->domain_state = talloc_reference(a_state, d_state);
 	a_state->account_dn = talloc_steal(d_state, msg.dn);
 	a_state->account_sid = talloc_strdup(d_state, sidstr);
 	a_state->account_name = talloc_strdup(d_state, groupname);
 	if (!a_state->account_name || !a_state->account_sid) {
+		talloc_free(a_state);
 		return NT_STATUS_NO_MEMORY;
 	}
 
@@ -543,10 +518,6 @@
 	g_handle->data = a_state;
 	g_handle->destroy = samr_handle_destroy;
 
-	/* the domain state is in use one more time */
-	talloc_increase_ref_count(d_state);
-	talloc_set_destructor(a_state, samr_Account_destructor);
-
 	*r->out.group_handle = g_handle->wire_handle;
 	*r->out.rid = rid;	
 
@@ -703,17 +674,19 @@
 	}
 	a_state->sam_ctx = d_state->sam_ctx;
 	a_state->access_mask = r->in.access_mask;
-	a_state->domain_state = d_state;
+	a_state->domain_state = talloc_reference(a_state, d_state);
 	a_state->account_dn = talloc_steal(d_state, msg.dn);
 	a_state->account_sid = talloc_strdup(d_state, sidstr);
 	a_state->account_name = talloc_strdup(d_state, account_name);
 	if (!a_state->account_name || !a_state->account_sid) {
+		talloc_free(a_state);
 		return NT_STATUS_NO_MEMORY;
 	}
 
 	/* create the policy handle */
 	u_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_USER);
 	if (!u_handle) {
+		talloc_free(a_state);
 		return NT_STATUS_NO_MEMORY;
 	}
 
@@ -721,8 +694,7 @@
 	u_handle->destroy = samr_handle_destroy;
 
 	/* the domain state is in use one more time */
-	talloc_increase_ref_count(d_state);
-	talloc_set_destructor(a_state, samr_Account_destructor);
+	
 
 	*r->out.user_handle = u_handle->wire_handle;
 	*r->out.access_granted = 0xf07ff; /* TODO: fix access mask calculations */
@@ -1014,7 +986,7 @@
 	}
 	a_state->sam_ctx = d_state->sam_ctx;
 	a_state->access_mask = r->in.access_mask;
-	a_state->domain_state = d_state;
+	a_state->domain_state = talloc_reference(a_state, d_state);
 	a_state->account_dn = talloc_steal(a_state, msgs[0]->dn);
 	a_state->account_sid = talloc_strdup(a_state, sidstr);
 	a_state->account_name = talloc_strdup(a_state, groupname);
@@ -1031,10 +1003,6 @@
 	g_handle->data = a_state;
 	g_handle->destroy = samr_handle_destroy;
 
-	/* the domain state is in use one more time */
-	talloc_increase_ref_count(d_state);
-	talloc_set_destructor(a_state, samr_Account_destructor);
-
 	*r->out.group_handle = g_handle->wire_handle;
 
 	return NT_STATUS_OK;
@@ -1386,7 +1354,7 @@
 	}
 	a_state->sam_ctx = d_state->sam_ctx;
 	a_state->access_mask = r->in.access_mask;
-	a_state->domain_state = d_state;
+	a_state->domain_state = talloc_reference(a_state, d_state);
 	a_state->account_dn = talloc_steal(d_state, msgs[0]->dn);
 	a_state->account_sid = talloc_strdup(d_state, sidstr);
 	a_state->account_name = talloc_strdup(d_state, account_name);
@@ -1403,10 +1371,6 @@
 	u_handle->data = a_state;
 	u_handle->destroy = samr_handle_destroy;
 
-	/* the domain state is in use one more time */
-	talloc_increase_ref_count(d_state);
-	talloc_set_destructor(a_state, samr_Account_destructor);
-
 	*r->out.user_handle = u_handle->wire_handle;
 
 	return NT_STATUS_OK;



More information about the samba-cvs mailing list