/* @(#)85    1.19  src/examples/type_mgr/server_admin_ops.c, examples.src, os2dce21.dss, 960602a.1 1/29/96 12:54:32 */
/*
 * COMPONENT_NAME:  examples.src
 *
 * FUNCTIONS:
 *
 * ORIGINS: 27
 *
 * (C) COPYRIGHT International Business Machines Corp. 1992, 1994
 * All Rights Reserved
 * Licensed Materials - Property of IBM
 *
 * US Government Users Restricted Rights - Use, duplication or
 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
 *
 */

/*********************************************************************
 *  File      :  server_admin_ops.c                                  *
 *********************************************************************
 *                                                                   *
 *  Functions :  RPC routines defined in idl file.                   *
 *               These operations are available thru the             *
 *               administration interface.                           *
 *                                                                   *
 *  Comments  :  The routines in this file correspond to the RPC     *
 *               interface defined in the idl file for the           *
 *               administration interface.                           *
 *                                                                   *
 *********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <ctype.h>
#include <string.h>
#include <dce/rpc.h>
#include <dce/pthread.h>
#include "tm_admin.h"
#include "tm_admin_if.h"
#include "cust_if.h"
#include "type_mgr.h"
#include "server.h"
#include "server_util.h"
#include "server_object_db.h"
#include <util.h>


/*********************************************************************
 *   Function    :  tm_admin_add_object()                            *
 *********************************************************************
 *                                                                   *
 *   Description : RPC operation for tm_admin interface.             *
 *                 Adds an object.  This means that a name service   *
 *                 entry is created, and endpoint map entry is       *
 *                 created, and the object information is stored     *
 *                 in the server's local database.                   *
 *                                                                   *
 *   Returns     : status = 0 success, != 0 program error.           *
 *                 Note that the return value, although always (0)   *
 *                 here, will indicate any communications errors     *
 *                 that occur between the client and server.         *
 *                 This is because of the [comm_status] attribute    *
 *                 that is defined in the .acf file.                 *
 *                                                                   *
 *********************************************************************/

error_status_t DCEAPI tm_admin_add_object( handle_t  h,
                        idl_char *object_type,
                     idl_char *object_name,
                         unsigned32 *status)
{
    uuid_t                 type_uuid, object_uuid;
    unsigned32             rc2;
    uuid_vector_t          uuid_vec;
    rpc_binding_vector_t   *binding_vector;
    char                   annotation[ 50 ];
    rpc_ns_handle_t        inquiry_context;
    char                   entry_name[ENTRY_LEN];
    char                   *obj_name;
    char                   *type_name;
    object_db_handle_t     obj_db_context;

    TRACE("Request to add an object/type pair\n");

    /* check if the object already exist in the name space. */

    sprintf( entry_name,
                 "%s%s",
                 g_object_ns_directory_path,
                 object_name);

    rpc_ns_entry_object_inq_begin( rpc_c_ns_syntax_default,
                                   entry_name,
                                   &inquiry_context,
                                   status);
    if ( *status )
    {
        return(0) ;
    }

    rpc_ns_entry_object_inq_next( inquiry_context,
                                  &object_uuid,
                                  status);

    /* delete the inquiry context anyway. */
    rpc_ns_entry_object_inq_done( &inquiry_context,
                                  &rc2);

    /* If the object already exists, then return */
    if ( *status != rpc_s_no_more_members  &&
           *status != rpc_s_entry_not_found )
    {
         if ( *status == rpc_s_ok )
         {
             *status = E_ADM_FNDNM ;
             return(0) ;
         }
    }

    if ((*status) = object_db_entry_inq_begin( &obj_db_context ))
    {
        PRINT("Error:  object_db_entry_inq_begin(): %d\n", *status);
        return(0);
    }

    while (((*status) = object_db_entry_inq_next( &obj_db_context,
                                           &obj_name,
                                           &type_name )) != NO_MORE_ENTRIES)
    {
        *status = strcmp( obj_name, object_name );
        free((char *)obj_name);
        free((char *)type_name);
        if (*status == 0)
        {
            *status = E_ADM_FNDDB;
            return(0);
        }
    }

    if ((*status) = object_db_entry_inq_done( &obj_db_context ))
    {
        PRINT("Error:  object_db_entry_inq_done(): %d\n", *status);
        return(0);
    }

    /*
     *  At this point we know that the object does not already exist.
     */

    /* add the object to the server object db */
    *status = object_db_entry_add( object_name, object_type );
    if ( *status )
    {
        *status = E_ADM_F_ADDDB;
        return(0);
    }

    if ( strcmp( object_type, TYPE1_NAME ) == 0 )
    {
        uuid_from_string( g_type1_uuid_str, &type_uuid, status );
        if ( *status )
        {
            return(0);
        }
    }
    else if ( strcmp( object_type, TYPE2_NAME ) == 0 )
    {
        uuid_from_string( g_type2_uuid_str, &type_uuid, status );
        if ( *status )
        {
            return(0);
        }
    }
    else
    {
        object_db_entry_delete( object_name );
        *status = E_ADM_BAD_TYPE;
        return(0);
    }

    uuid_create( &object_uuid, status);
    if ( *status )
    {
        return(0);
    }

    /* associate the object uuid with a type uuid */
    rpc_object_set_type( &object_uuid,
                         &type_uuid,
                         status );
    if ( *status )
    {
        object_db_entry_delete( object_name );
        return(0);
    }

    /* set the object uuid vector */
    uuid_vec.count = 1;
    uuid_vec.uuid[ 0 ] = &object_uuid ;

    /* get the binding vector */
    rpc_server_inq_bindings( &binding_vector,
                             status );

    if ( *status )
    {
        object_db_entry_delete( object_name );
        return(0);
    }

    sprintf( annotation, "Example Type Manager [ %s:%s ]",
                object_type, object_name);

    /* register the object with the endpoint map */
    rpc_ep_register( type_mgr_v1_0_s_ifspec,
                     binding_vector,
                     &uuid_vec,
                     (unsigned_char_t *) annotation ,
                     status );

    if ( *status )
    {
        object_db_entry_delete( object_name );
        return(0);
    }

    /*  export the object to the name space */
    *status = ns_export_object( binding_vector,
                                object_name,
                                &object_uuid );

    if ( *status )
    {
        rpc_ep_unregister( type_mgr_v1_0_s_ifspec,
                       binding_vector,
                       &uuid_vec,
                       status );
        object_db_entry_delete( object_name );
        *status =  E_ADM_F_EXPUUID;
    }

    TRACE("Object has been added sucessfully\n");
    return(0);

} /* end tm_admin_add_object() */


/*********************************************************************
 *   Function    : tm_admin_del_object()                             *
 *********************************************************************
 *                                                                   *
 *   Description :  Remove the specified object.  This means the     *
 *                  object is removed from the namespace, the        *
 *                  endpoint associated with the object is also      *
 *                  removed, as is the object entry in the server's  *
 *                  local database.                                  *
 *                                                                   *
 *   Returns     : status = 0 success, != 0 program error.         *
 *                 Note that the return value, although always (0)   *
 *                 here, will indicate any communications errors     *
 *                 that occur between the client and server.         *
 *                 This is because of the [comm_status] attribute    *
 *                 that is defined in the .acf file.                 *
 *                                                                   *
 *********************************************************************/

error_status_t DCEAPI tm_admin_del_object( handle_t      h,
                    idl_char      *object_name,
                             unsigned32    *status)
{
    uuid_t                 object_uuid;
    uuid_vector_t          uuid_vec;
    rpc_binding_vector_t   *binding_vector;
    unsigned32             error = 0 ;
    char                   entry_name[ENTRY_LEN];

    TRACE("Request to delete an object\n");

    /*
     * Note that if an error occurs in the course of removing the object,
     * in some cases we continue on since some cleanup is necessary.
     */

    /* delete the object from the server's local database */
    *status = object_db_entry_delete( object_name );

    if ( *status )
    {
        *status = E_ADM_F_RMVDB;
        return(0);
    }

    rpc_server_inq_bindings( &binding_vector,
                             status );
    if ( *status )
    {
       return(0);
    }

    /*
     *  remove the object from the endpoint map.
     */

    /* import the object uuid from the name space */

    *status = ns_get_object_uuid( object_name, &object_uuid );
    if ( *status )
    {
       if ( !error ) error = E_ADM_F_GETUUID;
    }

    /* set the object uuid vector */
    uuid_vec.count = 1;
    uuid_vec.uuid[0] = &object_uuid ;

    rpc_ep_unregister( type_mgr_v1_0_s_ifspec,
                       binding_vector,
                       &uuid_vec,
                       status );
    if ( *status )
    {
       if ( !error ) error = *status ;
    }

    sprintf( entry_name,
                 "%s%s",
                 g_object_ns_directory_path,
                 object_name);

    /* delete the name space entry of the object */
    rpc_ns_mgmt_entry_delete( rpc_c_ns_syntax_default,
                  entry_name,
                  status);

    if ( *status )
    {
       if ( !error ) error = *status;
    }

    /* resave the previous error. */
    if ( *status == 0 )
    {
       *status = error ;
    }

    TRACE("Object has been deleted successfully\n");
    return(0);

} /* end tm_admin_del_object() */


/*********************************************************************
 *   Function    :  tm_admin_list_object()                           *
 *********************************************************************
 *                                                                   *
 *   Description : Retrun the list of object names, and their        *
 *                 associated types.  This information is retrieved  *
 *                 from the server's in-memory object table.         *
 *                                                                   *
 *   Returns     : status = 0 success, != 0 program error.         *
 *                 Note that the return value, although always (0)   *
 *                 here, will indicate any communications errors     *
 *                 that occur between the client and server.         *
 *                 This is because of the [comm_status] attribute    *
 *                 that is defined in the .acf file.                 *
 *                                                                   *
 *********************************************************************/

error_status_t DCEAPI tm_admin_list_object( handle_t        h,
                               obj_list        **object_list,
                        unsigned32      *status)
{
    obj_list           *tmp_list;
    int                size, i;
    char               *obj_name, *type_name;
    object_db_handle_t obj_db_context;

    TRACE("Request to list existing objects\n");

    /*
     * get the information  of the objects from the server's object
     * table held in memory.
     */

    size = sizeof(obj_list) + sizeof(cstring_t) * 20;
    tmp_list = (obj_list *) rpc_ss_allocate( size );

    if ((*status) = object_db_entry_inq_begin( &obj_db_context ))
    {
        PRINT("Error:  object_db_entry_inq_begin(): %d\n", status);
        return(0);
    }

    i = 0;
    while (((*status) = object_db_entry_inq_next( &obj_db_context,
                                           &obj_name,
                                           &type_name )) != NO_MORE_ENTRIES)
    {
        sprintf(tmp_list->objects[ i ], "%s:%s",
              type_name, obj_name);
        i++;
        free((char *)obj_name);
        free((char *)type_name);
    }

    if ((*status) = object_db_entry_inq_done( &obj_db_context ))
    {
        PRINT("Error:  object_db_entry_inq_done(): %d\n", status);
        return(0);
    }

    tmp_list->size = i;
    *object_list = tmp_list;

    *status = rpc_s_ok;
    TRACE("Object list has been built successfully\n");
    return(0);

} /* end tm_admin_list_object() */

/* EOF server_admin_ops.c */


