예제 #1
0
파일: ctxeectx.c 프로젝트: Brainiarc7/pbis
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
}
예제 #2
0
파일: ctxeectx.c 프로젝트: Brainiarc7/pbis
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

}
예제 #3
0
파일: ctxeectx.c 프로젝트: Brainiarc7/pbis
void rpc_ss_lkddest_callee_context
(
    dce_uuid_t *p_uuid,    /* Pointer to UUID of context to be destroyed */
    rpc_client_handle_t *p_close_client,
                                /* Ptr to NULL or client to stop monitoring */
    error_status_t *result /* Function result */
)    /* Returns error_status_ok unless the UUID is not in the lookup table */
{
    callee_context_entry_t *this_link, *next_link, *last_link;

#ifdef PERFMON
    RPC_SS_LKDDEST_CALLEE_CONTEXT_N;
#endif

    this_link = &context_table[dce_uuid_hash(p_uuid,(error_status_t *) result)
                                               % CALLEE_CONTEXT_TABLE_SIZE];
    next_link = this_link->next_context;
    if ( dce_uuid_equal(p_uuid,&this_link->uuid, (error_status_t *) result) )
    {
        /* Context to be destroyed is in home slot */
        rpc_ss_take_from_callee_client(this_link,p_close_client,result);
        if (next_link == NULL)
        {
            /* There is no chain from the home slot */
            dce_uuid_create_nil(&this_link->uuid, (error_status_t *) result);
        }
        else
        {
            /* Move the second item in the chain to the home slot */
            memcpy(
                (char *)&this_link->uuid,
                (char *)&next_link->uuid,
                sizeof(dce_uuid_t)
            );
            this_link->user_context = next_link->user_context;
            this_link->rundown = next_link->rundown;
            this_link->p_client_entry = next_link->p_client_entry;
            this_link->prev_in_client = next_link->prev_in_client;
            if (this_link->prev_in_client == NULL)
            {
                (this_link->p_client_entry)->first_context = this_link;
            }
            else
            {
                (this_link->prev_in_client)->next_in_client = this_link;
            }
            this_link->next_in_client = next_link->next_in_client;
            if (this_link->next_in_client == NULL)
            {
                (this_link->p_client_entry)->last_context = this_link;
            }
            else
            {
                (this_link->next_in_client)->prev_in_client = this_link;
            }
            this_link->next_context = next_link->next_context;
            /* And release the memory it was in */
            free((char_p_t)next_link);
        }

#ifdef PERFMON
        RPC_SS_LKDDEST_CALLEE_CONTEXT_X;
#endif

        return;
    }
    else    /* Context is further down chain */
    {
        while (next_link != NULL)
        {
            last_link = this_link;
            this_link = next_link;
            next_link = this_link->next_context;
            if ( dce_uuid_equal(p_uuid,&this_link->uuid,(error_status_t *)result) )
            {
                rpc_ss_take_from_callee_client(this_link,p_close_client,result);
                /* Relink chain to omit found entry */
                last_link->next_context = next_link;
                /* And free the memory it occupied */
                free((char_p_t)this_link);

#ifdef PERFMON
                RPC_SS_LKDDEST_CALLEE_CONTEXT_X;
#endif

                return;
            }
        }
        RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex);
        DPRINT(("Released context tables\n"));
        DCETHREAD_RAISE( rpc_x_ss_context_mismatch);
    }
}
예제 #4
0
파일: ctxeectx.c 프로젝트: Brainiarc7/pbis
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;
}
예제 #5
0
파일: ctxeectx.c 프로젝트: Brainiarc7/pbis
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
    }
}
예제 #6
0
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);
    }
예제 #7
0
void rpc_ss_add_to_callee_client
(
    /* [in] */ rpc_client_handle_t ctx_client,
                             /* Client for whom there is or will be a context */
    /* [in] */ callee_context_entry_t *p_context,  /* Pointer to the context,
                     NULL if we are creating a client table entry to which
                     we expect a context to be attached later */
    /* [out] */ndr_boolean *p_is_new_client,
                                          /* TRUE => first context for client */
    error_status_t *result         /* Function result */
)
{
    int slot;    /* Index of the slot in the lookup table the client
                    should be in */
    ndr_boolean creating_at_home;    /* TRUE if new client being created in slot
                                    in lookup table */
    callee_client_entry_t *this_client, *next_client, *new_client;


#ifdef PERFMON
    RPC_SS_ADD_TO_CALLEE_CLIENT_N;
#endif
    /* Now find which chain */
    slot = HASH_CLIENT_ID(ctx_client);

    /* Look for the client in a chain based on the slot.
        Note the following possibilities exist for the slot:
        1) Unoccupied. No chain.
        2) Occupied. No chain.
        3) Occupied. Chain exists.
        4) Unoccupied. Chain exists.
        This is because once a client record is
            created it is constrained by the presence of threads machinery
            not to be moved */
    this_client = &client_table[slot];
    while (ndr_true)
    {
        if ( ctx_client == this_client->client )
        {
            ++this_client->count;
            *p_is_new_client = (this_client->count == 1);
            /* Linkage of contexts within client */
            p_context->p_client_entry = this_client;
            p_context->prev_in_client = this_client->last_context;
            p_context->next_in_client = NULL;
            if (this_client->first_context == NULL)
            {
                /* Client table entry created before manager was entered */
                this_client->first_context = p_context;
            }
            else
            {
                (this_client->last_context)->next_in_client = p_context;
            }
            this_client->last_context = p_context;
            *result = error_status_ok;
#ifdef PERFMON
            RPC_SS_ADD_TO_CALLEE_CLIENT_X;
#endif
            return;
        }
        next_client = this_client->next_h_client;
        if (next_client == NULL) break;
        this_client = next_client;
    }

    /* Get here only if this is the first context for the client */
    creating_at_home = (client_table[slot].client == NULL);
    if (creating_at_home)
    {
        /* The slot in the table is unoccupied */
        new_client = &client_table[slot];
    }
    else
    {
        new_client = (callee_client_entry_t *)
                            malloc(sizeof(callee_client_entry_t));
        if (new_client == NULL)
        {
            RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex);
            DPRINT(("Released context tables\n"));
            DCETHREAD_RAISE( rpc_x_no_memory );
        }
        this_client->next_h_client = new_client;
        new_client->prev_h_client = this_client;
        new_client->next_h_client = NULL;
    }
    new_client->client = ctx_client;
    new_client->rundown_pending = idl_false;
    RPC_SS_THREADS_CONDITION_CREATE(&(new_client->cond_var));
    if (p_context == NULL)
    {
        /* New (locking) code. Client table entry created before manager
            entered */
        new_client->count = 0;
        new_client->first_context = NULL;
        new_client->last_context = NULL;
        new_client->ref_count = 1;
        *p_is_new_client = ndr_false;
    }
    else
    {
        /* Old (non-locking) code. Client table entry created when non-null
            context marshalled after return from manager */
        new_client->count = 1;
        new_client->first_context = p_context;
        new_client->last_context = p_context;
        new_client->ref_count = 0;
        p_context->p_client_entry = new_client;
        p_context->prev_in_client = NULL;
        p_context->next_in_client = NULL;
        *p_is_new_client = ndr_true;
    }
    *result = error_status_ok;


#ifdef PERFMON
    RPC_SS_ADD_TO_CALLEE_CLIENT_X;
#endif
}