void rpc_ss_destroy_callee_context ( dce_uuid_t *p_uuid, /* Pointer to UUID of context to be destroyed */ handle_t h, /* Binding handle */ error_status_t *result /* Function result */ ) /* Returns error_status_ok unless the UUID is not in the lookup table */ { rpc_client_handle_t close_client; /* NULL or client to stop monitoring */ #ifdef PERFMON RPC_SS_DESTROY_CALLEE_CONTEXT_N; #endif RPC_SS_THREADS_MUTEX_LOCK(&rpc_ss_context_table_mutex); DPRINT(("Seized context tables\n")); rpc_ss_lkddest_callee_context(p_uuid,&close_client,result); RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); if ((*result == error_status_ok) && (close_client != NULL)) { rpc_network_stop_monitoring(h, close_client, (error_status_t *) result); } #ifdef PERFMON RPC_SS_DESTROY_CALLEE_CONTEXT_X; #endif }
void rpc_ss_update_callee_context ( rpc_ss_context_t callee_context, /* The user's local form of the context */ dce_uuid_t *p_uuid, /* Pointer to the equivalent UUID */ error_status_t *result /* Function result */ ) { callee_context_entry_t *this_link; #ifdef PERFMON RPC_SS_UPDATE_CALLEE_CONTEXT_N; #endif RPC_SS_THREADS_MUTEX_LOCK(&rpc_ss_context_table_mutex); DPRINT(("Seized context tables\n")); this_link = &context_table[dce_uuid_hash(p_uuid,result) % CALLEE_CONTEXT_TABLE_SIZE]; while ( ! dce_uuid_equal(p_uuid,&this_link->uuid,result) ) { this_link = this_link->next_context; if (this_link == NULL) { RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); DCETHREAD_RAISE( rpc_x_ss_context_mismatch); } } this_link->user_context = callee_context; RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); *result = error_status_ok; #ifdef PERFMON RPC_SS_UPDATE_CALLEE_CONTEXT_X; #endif }
void rpc_ss_ee_ctx_from_wire ( ndr_context_handle *p_wire_context, rpc_ss_context_t *p_context, /* The application context */ volatile error_status_t *p_st ) { dce_uuid_t *p_uuid; /* Pointer to the UUID that has come off the wire */ callee_context_entry_t *this_link; #ifdef PERFMON RPC_SS_EE_CTX_FROM_WIRE_N; #endif p_uuid = &p_wire_context->context_handle_uuid; #ifdef DEBUGCTX debug_context_lookup(p_uuid); debug_context_table(); #endif *p_st = error_status_ok; if ( dce_uuid_is_nil(p_uuid, (error_status_t *)p_st) ) { *p_context = NULL; #ifdef PERFMON RPC_SS_EE_CTX_FROM_WIRE_X; #endif return; } RPC_SS_THREADS_MUTEX_LOCK(&rpc_ss_context_table_mutex); DPRINT(("Seized context tables\n")); this_link = &context_table[dce_uuid_hash(p_uuid, (error_status_t *)p_st) % CALLEE_CONTEXT_TABLE_SIZE]; while ( ! dce_uuid_equal(p_uuid,&this_link->uuid, (error_status_t *)p_st) ) { this_link = this_link->next_context; if (this_link == NULL) { RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); #ifdef PERFMON RPC_SS_EE_CTX_FROM_WIRE_X; #endif DCETHREAD_RAISE( rpc_x_ss_context_mismatch ); return; } } *p_context = this_link->user_context; RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); #ifdef PERFMON RPC_SS_EE_CTX_FROM_WIRE_X; #endif return; }
void rpc_ss_create_callee_context ( rpc_ss_context_t callee_context,/* The user's local form of the context */ dce_uuid_t *p_uuid, /* Pointer to the equivalent UUID */ handle_t h, /* Binding handle */ ctx_rundown_fn_p_t ctx_rundown, /* Pointer to context rundown routine */ error_status_t *result /* Function result */ ) { rpc_client_handle_t ctx_client; /* ID of client owning context */ callee_context_entry_t *this_link, *next_link, * volatile new_link; ndr_boolean is_new_client; //DO_NOT_CLOBBER(new_link); #ifdef PERFMON RPC_SS_CREATE_CALLEE_CONTEXT_N; #endif /* If this is the first context to be created, initialization is needed */ RPC_SS_INIT_CONTEXT rpc_binding_inq_client(h, &ctx_client, (error_status_t *) result); if (*result != error_status_ok) return; RPC_SS_THREADS_MUTEX_LOCK(&rpc_ss_context_table_mutex); DPRINT(("Seized context tables\n")); this_link = &context_table[dce_uuid_hash(p_uuid,(error_status_t *)result) % CALLEE_CONTEXT_TABLE_SIZE]; if ( dce_uuid_is_nil(&this_link->uuid, (error_status_t *)result) ) { /* Home slot in the hash table is empty */ new_link = this_link; next_link = NULL; } else { /* Put the new item at the head of the overflow chain */ new_link = (callee_context_entry_t *) malloc(sizeof(callee_context_entry_t)); if (new_link == NULL) { RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); DCETHREAD_RAISE( rpc_x_no_memory ); } next_link = this_link->next_context; this_link->next_context = new_link; } /* Fill in fields of context entry */ memcpy( (char *)&new_link->uuid, (char *)p_uuid, sizeof(dce_uuid_t) ); new_link->user_context = callee_context; new_link->rundown = ctx_rundown; new_link->next_context = next_link; DCETHREAD_TRY rpc_ss_add_to_callee_client(ctx_client,new_link,&is_new_client, result); DCETHREAD_FINALLY RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); DCETHREAD_ENDTRY if ((*result == error_status_ok) && is_new_client) { rpc_network_monitor_liveness( h, ctx_client, rpc_ss_rundown_client, (error_status_t *) result ); #ifdef PERFMON RPC_SS_CREATE_CALLEE_CONTEXT_X; #endif } }
void rpc_ss_rundown_client ( /* [in] */ rpc_client_handle_t failed_client ) { error_status_t result; callee_client_entry_t *this_client; callee_context_entry_t *this_context; rpc_client_handle_t close_client = NULL; /* NULL or client to stop monitoring */ /* FIXME: is the volatility set correctly here? */ rpc_ss_rundown_list_elt * volatile rundown_list; rpc_ss_rundown_list_elt * volatile rundown_elt; rundown_list = NULL; #ifdef PERFMON RPC_SS_RUNDOWN_CLIENT_N; #endif RPC_SS_THREADS_MUTEX_LOCK(&rpc_ss_context_table_mutex); DPRINT(("Seized context tables\n")); for( this_client = &client_table[HASH_CLIENT_ID(failed_client)]; (this_client != NULL) && (close_client == NULL); this_client = this_client->next_h_client ) { if (this_client->client == failed_client) { while (this_client->ref_count != 0) { this_client->rundown_pending = idl_true; RPC_SS_THREADS_CONDITION_WAIT(&this_client->cond_var, &rpc_ss_context_table_mutex); /* Mutex has been released */ RPC_SS_THREADS_MUTEX_LOCK(&rpc_ss_context_table_mutex); } if (this_client->count == 0) { /* The manager closed the contexts while a rundown was pending */ rpc_ss_ctx_remove_client_entry(this_client); RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); #ifdef PERFMON RPC_SS_RUNDOWN_CLIENT_X; #endif return; } /* Need to clear the rundown pending flag so that the client entry can be deleted */ this_client->rundown_pending = idl_false; while (close_client == NULL) { /* Loop until all contexts for this client have been removed from the context table. Note that each iteration brings a different context to first_context position */ this_context = this_client->first_context; rundown_elt = (rpc_ss_rundown_list_elt *) malloc(sizeof(rpc_ss_rundown_list_elt)); if (rundown_elt == NULL) { RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); /* * rpc_m_ctxrundown_nomem * "Out of memory while trying to run down contexts of client %x" */ RPC_DCE_SVC_PRINTF (( DCE_SVC(RPC__SVC_HANDLE, "%x"), rpc_svc_libidl, svc_c_sev_error, rpc_m_ctxrundown_nomem, this_client )); return; } rundown_elt->rundown = this_context->rundown; rundown_elt->user_context = this_context->user_context; rundown_elt->next = rundown_list; rundown_list = rundown_elt; rpc_ss_lkddest_callee_context (&this_context->uuid,&close_client,&result); } } } RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); while (rundown_list != NULL) { if (rundown_list->rundown != NULL) { DCETHREAD_TRY (*(rundown_list->rundown))(rundown_list->user_context); DCETHREAD_CATCH_ALL(caught) /* * rpc_m_ctxrundown_exc * "Exception in routine at %x, running down context %x of client %x" */ RPC_DCE_SVC_PRINTF (( DCE_SVC(RPC__SVC_HANDLE, "%x%x%x"), rpc_svc_libidl, svc_c_sev_error, rpc_m_ctxrundown_exc, rundown_list->rundown, rundown_list->user_context, this_client )); DCETHREAD_ENDTRY } rundown_elt = rundown_list; rundown_list = rundown_list->next; free(rundown_elt); }