Exemple #1
0
/*{
** Name: psq_topen	- Open a query text chain
**
** Description:
**      This function opens a query text chain by opening a memory stream,
**	allocating a header, and filling it in. 
**
** Inputs:
**      header                          Place to put pointer to header
**	memleft				Pointer to memory left
**	err_blk				Filled in if an error happens
**
** Outputs:
**      header                          Filled in with pointer to header
**	err_blk				Filled in if an error happened
**	Returns:
**	    E_DB_OK			Success
**	    E_DB_ERROR			Non-catastrophic failure
**	    E_DB_FATAL			Catastrophic failure
**	Exceptions:
**	    none
**
** Side Effects:
**	    Allocates memory
**
** History:
**      18-jul-86 (jeff)
**          written
**      02-sep-86 (seputis)
**          err_blk becomes a DB_ERROR *
*/
DB_STATUS
psq_topen(
	PTR                *header,
	SIZE_TYPE	   *memleft,
	DB_ERROR	   *err_blk)
{
    ULM_RCB             ulm_rcb;
    DB_STATUS		status;
    i4		err_code;
    PSQ_THEAD		*hp;
    extern PSF_SERVBLK	*Psf_srvblk;

    /* Open the stream and allocate memory for the header */
    ulm_rcb.ulm_facility = DB_PSF_ID;
    ulm_rcb.ulm_poolid = Psf_srvblk->psf_poolid;
    ulm_rcb.ulm_blocksize = 512;
    ulm_rcb.ulm_memleft = memleft;
    ulm_rcb.ulm_streamid_p = &ulm_rcb.ulm_streamid;
    ulm_rcb.ulm_flags = ULM_SHARED_STREAM | ULM_OPEN_AND_PALLOC;
    ulm_rcb.ulm_psize = sizeof(PSQ_THEAD);
    if ((status = ulm_openstream(&ulm_rcb)) != E_DB_OK)
    {
	if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM)
	{
	    psf_error(E_PS0F02_MEMORY_FULL, 0L, PSF_CALLERR, 
		&err_code, err_blk, 0);
	}
	else
	    (VOID) psf_error(E_PS0370_OPEN_TEXT_CHAIN,
		ulm_rcb.ulm_error.err_code, PSF_INTERR, &err_code, err_blk, 0);
	return (status);
    }

    *header = ulm_rcb.ulm_pptr;

    /* Fill in the header */
    hp		    = (PSQ_THEAD*) ulm_rcb.ulm_pptr;
    hp->psq_first   = (PSQ_TEXT *) NULL;
    hp->psq_last    = (PSQ_TEXT *) NULL;
    hp->psq_tsize   = 0;
    STRUCT_ASSIGN_MACRO(ulm_rcb, hp->psq_tmem);
    hp->psq_tmem.ulm_streamid_p = &hp->psq_tmem.ulm_streamid;

    return (E_DB_OK);
}
Exemple #2
0
/*{
** Name: opu_allocate	- allocate a new private memory stream
**
** Description:
**      This routine will allocate a new private memory stream from the ULM
**
** Inputs:
**      global                          ptr to global state variable
**
** Outputs:
**	Returns:
**	    PTR which represents the new memory stream
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	16-jun-86 (seputis)
**          initial creation
**	11-oct-2006 (hayke02)
**	    Send E_OP0002_NOMEMORY to errlog.log. This change fixes bug 116309.
[@history_line@]...
*/
PTR
opu_allocate(
    OPS_STATE          *global)
{
    DB_STATUS       ulmstatus;		/* return status from ulm */

    /* Tell ULM to return streamid into ulm_streamid */
    global->ops_mstate.ops_ulmrcb.ulm_streamid_p =
        &global->ops_mstate.ops_ulmrcb.ulm_streamid;
    ulmstatus = ulm_openstream(&global->ops_mstate.ops_ulmrcb);
    if (DB_FAILURE_MACRO(ulmstatus))
    {
        opx_lerror(E_OP0002_NOMEMORY, 0);
        opx_verror(ulmstatus, E_OP0002_NOMEMORY,
                   global->ops_mstate.ops_ulmrcb.ulm_error.err_code);
    }
    return ( global->ops_mstate.ops_ulmrcb.ulm_streamid );
}
Exemple #3
0
/*{
** Name: OPU_OSMEMORY_OPEN	- Initialize the stack ULM memory stream
**
** Description:
**      This routine initializes the ULM memory stream that will be used 
**      for the stack style memory allocation and deallocation. 
[@comment_line@]...
**
** Inputs:
**	global -
**	    State info for the current query.
**	global->ops_mstate.ops_ulmrcb -
**	    The ULM control block.
**
** Outputs:
**	global->ops_mstate.ops_sstreamid -
**	    The new stream id.
**
**	Returns:
**	    Nothing
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**      19-July-87 (eric)
**          written
**	11-oct-2006 (hayke02)
**	    Send E_OP0002_NOMEMORY to errlog.log. This change fixes bug 116309.
[@history_template@]...
*/
VOID
opu_Osmemory_open(
	OPS_STATE   *global)
{
    DB_STATUS      ulmstatus;		    /* return status from ULM */

    /* Set the output streamid location for ULM */
    global->ops_mstate.ops_ulmrcb.ulm_streamid_p = &global->ops_mstate.ops_sstreamid;

    if ( (ulmstatus = ulm_openstream( &global->ops_mstate.ops_ulmrcb )) != E_DB_OK )
    {
	if (global->ops_mstate.ops_ulmrcb.ulm_error.err_code == E_UL0005_NOMEM)
	{
	    opx_lerror(E_OP0002_NOMEMORY, 0, 0, 0, 0, 0);
	    opx_error( E_OP0002_NOMEMORY);  /* out of memory */
	}
#ifdef E_OP0093_ULM_ERROR
	else
	    opx_verror( ulmstatus, E_OP0093_ULM_ERROR, 
		global->ops_mstate.ops_ulmrcb.ulm_error.err_code); /* check for error */
#endif
    }	
}
Exemple #4
0
/*
** Name: sxapo_open - open an audit trail
**
** Description:
**	This routine is used to open an audit trail that can, in theory, be used
**	for either reading or writing audit records, although reading of
**	operating system audit records is not currently supported. SXF supports
**	the ability to have a maximum of one audit trail open for writing at
**	a time. This routine
**	returns an access identifier (actually a pointer to a SXAPO_RSCB
**	structure) that must be specified for all other operations requested
**	on this trail. if no filename is specified the current audit trail
**	will be opened.
**
** 	Overview of algorithm:-
**
**	Validate the parameters passed to the routine.
**	Open a memory stream and allocate and build a SXAPO_RSCB.
**	If filename is NULL get the name of the current audit trail.
**	Call the SAopen routine to perform the physical open call.
**
**
** Inputs:
**	filename		Name of the audit trail to open, if this is NULL
**				the current audit trail will be opened.
**	mode			either SXF_READ of SXF_WRITE (must currently
**				be SXF_WRITE).
**	sxf_rscb		the SXF_RSCB for the audit trail
**
** Outputs:
**	sxf_rscb		Access identifier for audit file.
**	err_code		Error code returned to the caller.
**
** Returns:
**	DB_STATUS
**
** History:
**	6-jan-94 (stephenb)
**	    Initial Creation.
**	7-feb-94 (stephenb)
**	    log error E_SX002E_OSAUDIT_NO_READ since we don't do it anywhere
**	    else yet.
**	11-feb-94 (stephenb)
**	    Update SA call to current spec.
*/
DB_STATUS
sxapo_open(
    PTR			filename,
    i4			mode,
    SXF_RSCB		*sxf_rscb,
    i4		*filesize,
    PTR			sptr,
    i4		*err_code)
{
    ULM_RCB		ulm_rcb;
    DB_STATUS		status = E_DB_OK;
    i4		local_err;
    bool		stream_open = FALSE;
    SXAPO_RSCB		*sxapo_rscb;
    STATUS		cl_stat;
    CL_ERR_DESC		cl_err;

    *err_code = E_SX0000_OK;
    for (;;)
    {
        /* validate parameters, write is currently the only valid mode */
        if (sxf_rscb == NULL)
        {
            *err_code = E_SX0004_BAD_PARAMETER;
            break;
        }
        else if (mode != SXF_WRITE)
        {
            *err_code = E_SX002E_OSAUDIT_NO_READ;
            /*
            ** Log this here since we don't yet do it anywhere else.
            */
            _VOID_ ule_format(*err_code, NULL, ULE_LOG, NULL, NULL, 0L,
                              NULL, &local_err, 0);
            break;
        }
        /*
        ** Open a memory stream and allocate some memory for the SXAPO_RSCB
        */
        ulm_rcb.ulm_facility = DB_SXF_ID;
        ulm_rcb.ulm_poolid = Sxf_svcb->sxf_pool_id;
        ulm_rcb.ulm_blocksize = 0;
        ulm_rcb.ulm_memleft = &Sxf_svcb->sxf_pool_sz;
        ulm_rcb.ulm_streamid_p = &ulm_rcb.ulm_streamid;
        /* No other allocations on this stream - make it private */
        /* Open stream and allocate SXAPO_RSCB with one call */
        ulm_rcb.ulm_flags = ULM_PRIVATE_STREAM | ULM_OPEN_AND_PALLOC;
        ulm_rcb.ulm_psize = sizeof (SXAPO_RSCB);
        status = ulm_openstream(&ulm_rcb);
        if (status != E_DB_OK)
        {
            if(ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM)
                *err_code = E_SX1002_NO_MEMORY;
            else
                *err_code = E_SX106B_MEMORY_ERROR;
            _VOID_ ule_format(ulm_rcb.ulm_error.err_code, NULL, ULE_LOG,
                              NULL, NULL, 0L, NULL, &local_err, 0);
            _VOID_ ule_format(*err_code, NULL, ULE_LOG,
                              NULL, NULL, 0L, NULL, &local_err, 0);
            break;
        }
        stream_open = TRUE;

        sxf_rscb->sxf_sxap = ulm_rcb.ulm_pptr;
        sxapo_rscb = (SXAPO_RSCB *) sxf_rscb->sxf_sxap;
        sxapo_rscb->rs_memory = ulm_rcb.ulm_streamid;
        /*
        ** Filename should not be supplied for OS audit trail writes
        */
        if (filename)
        {
            *err_code = E_SX101E_INVALID_FILENAME;
            break;
        }
        else
        {
            /*
            ** Auditing must be enabled to use "current" file
            */
            if (Sxapo_cb->sxapo_status & SXAPO_STOPAUDIT)
            {
                _VOID_ ule_format(E_SX10A7_NO_CURRENT_FILE, NULL, ULE_LOG,
                                  NULL, NULL, 0L, NULL, &local_err, 0);
                *err_code = E_SX0015_FILE_NOT_FOUND;
                break;
            }
        }
        /*
        ** Open the audit trail with SAopen
        */
        cl_stat = SAopen(NULL, SA_WRITE,
                         &sxapo_rscb->sxapo_desc, &cl_err);
        if (cl_stat != OK)
        {
            *err_code = E_SX1018_FILE_ACCESS_ERROR;
            _VOID_ ule_format(*err_code, &cl_err, ULE_LOG, NULL, NULL,
                              0L, NULL, &local_err, 0);
            break;
        }
        break;
    }
    /*
    ** Handle any errors
    */
    if (*err_code != E_SX0000_OK)
    {
        if (stream_open)
            _VOID_ ulm_closestream(&ulm_rcb);
        if (*err_code > E_SXF_INTERNAL)
        {
            _VOID_ ule_format(E_SX10B6_OSAUDIT_OPEN_FAILED, NULL, ULE_LOG,
                              NULL, NULL, 0L, NULL, &local_err, 0);
            *err_code = E_SX1023_SXAP_OPEN;
        }
        if (status == E_DB_OK)
            status = E_DB_ERROR;
    }
    else
    {
        /*
        ** Incriment stats counter
        */
        Sxf_svcb->sxf_stats->open_write++;
    }

    return (status);
}
Exemple #5
0
/*{
** Name: uld_prtree	- Format and print a tree
**
** Description:
**      This function formats and prints a tree, with help from caller-
**	supplied functions.  The algorithm was adapted by Bob Kooi from
**		Wetherell, C. and Shannon, A., "Tidy Drawings of Trees,"
**		IEEE Transactions on Software Engineering, Vol. SE-5, No. 5
**		September, 1979
**
**	Later mods made it re-entrant so it could run as part of a server.
**
**	EXAMPLE:
**		suppose you have a tree made out of nodes of type tnode:
**
**		struct tnode
**		{
**			i4		data1;
**			i4		data2;
**			struct tnode	*left;
**			struct tnode	*right;
**		}
**
**		where Root is a pointer to the root.  you must provide
**		three routines, call them leftson, rightson and printnode:
**
**		PTR
**		leftson(t)
**		PTR	    t;
**		{
**			return ((PTR) ((struct tnode *) t)->left);
**		}
**
**		PTR
**		rightson(t)
**		PTR	    t;
**		{
**			return ((PTR) ((struct tnode *) t)->right);
**		}
**
**		VOID 
**		printnode(t, control)
**		PTR	    t;
**		PTR	    control;
**		{
**			struct tnode	*node = (struct tnode *) t;
**
**			uld_prnode(control, "*****");
**			TRformat(uld_tr_callback, (i4 *)0,
**			    global_buffer, sizeof(global_buffer),
**			    "* %d *",
**			    node->data1);
**			uld_prnode(control, global_buffer);
**			TRformat(uld_tr_callback, (i4 *)0,
**			    global_buffer, sizeof(global_buffer),
**			    %d*",
**			    node->data2, node->data1);
**			uld_prnode(control, global_buffer);
**			uld_prnode(control, "*****");
**		}
**
**
**		then the call:
**
**		uld_prtree(0, (PTR) Root, printnode, leftson, rightson, 8, 5);
**
**		would print a tree where each node is 8 characters wide
**		by 5 characters long and would contain data1 on the first
**		line, data2 and data1 on the second line with a border of
**		stars.
**
**		a sample output might be:
 
                                        *****
                                        * 7 *
                                        *3 7*
                                        *****
 
                         /                              \
                        *****                           *****
                        * 4 *                           * 3 *
                        *3 4*                           *3 3*
                        *****                           *****
 
                 /              \                /              \
                *****           *****           *****           *****
                * 3 *           * 1 *           * 2 *           * 1 *
                *3 3*           *3 1*           *3 2*           *3 1*
                *****           *****           *****           *****
 
         /              \                /              \
        *****           *****           *****           *****
        * 2 *           * 1 *           * 1 *           * 1 *
        *3 2*           *3 1*           *3 1*           *3 1*
        *****           *****           *****           *****
 
 /              \
*****           *****
* 1 *           * 1 *
*3 1*           *3 1*
*****           *****
 
 
**
** Parts of a tree that exceed the manifest constants are not printed
** but should not otherwise cause difficulty (supposedly).
**
**
** the main difference between this and the reference is that here a
** "parallel" tree is built to hold the info (x,modifier) that, in the
** reference, is held in the nodes of the tree being printed.
** this means that the user need not plan for this routine but can
** easily add it in later. this is almost imperative when the user
** is working with variable size nodes in his tree.
**
** Inputs:
**      root                            Pointer to the root of the tree
**	printnode			Pointer to function to format a node
**	leftson				Pointer to function to find left son
**	rightson			Pointer to function to find right son
**	indent				Indent scale factor (number of spaces
**					to indent for each horizontal level)
**	lbl				Lines between levels (should at least
**					equal the maximum number of lines that
**					the user would ever print for a node
**					to ensure an evenly spaced tree)
**      facility                        facility ID of caller
**
** Outputs:
**      None
**	Returns:
**	    None
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	06-may-86 (jeff)
**          Adapted from fmttree() in jutil!fmttree.c in 4.0
**	24-mar-87 (daved)
**	    set exclusive semaphore so that large static structures
**	    for the control struct are single threaded.
**	18-Jun-87 (DaveS)
**	    Modified to get memory from ULM instead of using statics.
**	    SCF semaphore removed since we no longer need it.
**	04-nov-87 (thurston)
**          On ulm_startup() call, I made the block size almost as large as the
**          pool since all that this routine does is create a pool, start a
**          stream, and allocate one L*A*R*G*E piece out of it.  (Wouldn't this
**          be better served by SCU_MALLOC directly???
**	08-feb-89 (jrb)
**	    Fixed calls to ule_format which made no sense at all.
**	21-may-89 (jrb)
**	    Updated for new ule_format interface.
**	22-sep-1992 (bryanp)
**	    Pass an err_code argument to ule_format. It demands one.
**	7-oct-2004 (thaju02)
**	    Change memleft to SIZE_TYPE.
**	19-Aug-2009 (kibro01) b122509
**	    Add new uld_prtree_x function which allows an extra sc930-tracing
**	    parameter to uld_prtree
**      17-Aug-2010 (horda03) b124274
**          Allow Trees to be printed in connected segments to aid readability.
*/
VOID
uld_prtree_x( i4 flags, PTR root, VOID (*printnode)(), PTR (*leftson)(), PTR (*rightson)(),
	    i4  indent, i4  lbl, i4  facility, PTR sc930_trace )
{
    register i4         i;
    register PARATREE	*pnode;
    ULD_CONTROL		control;
    ULD_STORAGE		*storage = 0;
    ULM_RCB		ulm_rcb;
    SIZE_TYPE		memleft;
    STATUS		status;
    i4		err_code;
    i4          max_nodes;
    ULD_PARAM   *uld_param = 0;
    
 
    control.facility = facility;
    ulm_rcb.ulm_facility = DB_ULF_ID;
    ulm_rcb.ulm_sizepool = sizeof(ULD_STORAGE) + 1024;
    ulm_rcb.ulm_blocksize = sizeof(ULD_STORAGE) + 128;
    memleft = sizeof(ULD_STORAGE) + 1024;
    ulm_rcb.ulm_memleft	    = &memleft;
 
    /* create a memory pool */
    status = ulm_startup(&ulm_rcb);
    if (status != E_DB_OK)
    {
	 (VOID) ule_format(ulm_rcb.ulm_error.err_code, (CL_ERR_DESC *)NULL,
		  ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL,
		  &err_code, 0);
	 (VOID) ule_format(E_UL0201_ULM_FAILED, (CL_ERR_DESC *)NULL,
		  ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL,
		  &err_code, 0);
	 return;
    }

    /* open the private memory stream and allocate ULD_STORAGE */
    ulm_rcb.ulm_flags = ULM_PRIVATE_STREAM | ULM_OPEN_AND_PALLOC;
    ulm_rcb.ulm_psize	    = sizeof (ULD_STORAGE);
    ulm_rcb.ulm_streamid_p = NULL;
    if ((status = ulm_openstream(&ulm_rcb)) != E_DB_OK)
    {
	 (VOID) ule_format(ulm_rcb.ulm_error.err_code, (CL_ERR_DESC *)NULL,
		  ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL,
		  &err_code, 0);
	(VOID) ule_format(E_UL0201_ULM_FAILED, (CL_ERR_DESC *)NULL,
		  ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL,
		  &err_code, 0);
	return;
    }
 
    storage   		    = (ULD_STORAGE *)ulm_rcb.ulm_pptr;
 
    control.lbl = lbl + 1;
    control.isf = indent;
    control.pti = 0;
    control.ptp = storage->pts;
    control.ncmx = indent * 2;
    control.first = 0;
 
    if (flags & ULD_FLAG_OUT_SEG)
    {
       uld_param = (ULD_PARAM *) root;

       root = uld_param->root;

       control.max_level = uld_param->control->max_level;
       control.segments  = uld_param->control->segments;
       control.num_segments = uld_param->control->num_segments;
    }
    else if (flags & ULD_FLAG_SEGMENTS)
    {
       control.segments = storage->segments;
       control.num_segments = &storage->num_segments;
       storage->num_segments = 0;

       max_nodes = 132 / control.ncmx;

       for (i = 1; i < sizeof(nodes_per_level)/sizeof(i4); i++)
       {
          if (max_nodes < nodes_per_level [i]) break;
       }

       control.max_level = i - 1;
    }
    else
       control.max_level = 0;

    for (i = PMX + 1; i--; )
	control.pbuf[i] = &(storage->pbf[i][0]);
 
    control.modifier = storage->mod;
    control.next_pos = storage->ned;
 
    /* Initialize line buffers */
    control.bmax = PMX;
    prflsh(1, &control, NULL);
 
    /* Initialize arrays */
    for (i = MAXH; i--; )
    {
	control.next_pos[i] = '\1';
	control.modifier[i] = '\0';
    }
 
    /* Initialize the function pointers */
    control.lson = leftson;
    control.rson = rightson;
    control.pnod = printnode;
 
    /* Do the first post-order walk */
    control.maxh = -1;
    pnode = walk1(root, 0, &control);

    if (uld_param)
    {
       pnode->new_root = uld_param->root_num;
    }
 
    /* Do the second pre-order walk */
    control.modfsum = 0;
    walk2(pnode, &control);
 
    /* For each level, print out the nodes at that level */
    control.type = ROOT;
    for (i = 0; i <= control.maxh; i++)
    {
	walk3(root, pnode, 0, i, &control);
	prflsh(0, &control, sc930_trace);
    }

    if ( !uld_param  && control.max_level)
    {
       ULD_PARAM u_root;

       u_root.control = &control;

       for (i = 0; i < *control.num_segments; i++ )
       {
           u_root.root = control.segments [i];

           u_root.root_num = i + 1;

           uld_prtree_x( ULD_FLAG_OUT_SEG, (PTR) &u_root, printnode, leftson, rightson, indent, -lbl, facility, sc930_trace );
       }
    }
 
    /* if we got any memory, return it */
    if (storage)
       ulm_shutdown(&ulm_rcb);
}
Exemple #6
0
/*{
** Name: ops_init - initialize structures needed for optimization
**
** Description:
**	This routine will initialize the "global state" variable which contains
**      all information for the optimization of this query for this session.
**
** Inputs:
**      global				ptr to global state variable
**          .ops_cb                     ptr to session control block
**          .ops_caller_cb              ptr to same object as opf_cb
**      opf_cb                          caller's control block
**
** Outputs:
**      global                          all components initialized
**	Returns:
**	    E_DB_OK, E_DB_ERROR
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	24-feb-86 (seputis)
**          initial creation
**	26-nov-90 (stec)
**	    Added initialization of ops_prbuf in OPS_STATE struct.
**	28-dec-90 (stec)
**	    Changed initialization of print buffer; ops_prbuf has been
**	    removed, opc_prbuf in OPC_STATE struct will be initialized
**	    instead.
**      28-jan-91 (seputis)
**          added support for OPF ACTIVE FLAG
**	11-jun-91 (seputis)
**	    ifdef distributed code until header files merge
**      04-sep-92 (fpang)
**          Fixed initialization of rdr_r1_distrib.
**      27-apr-95 (inkdo01)
**          Init ops_osubquery to NULL 
**	26-nov-96 (inkdo01)
**	    Allow users OPF memory equal to 1.5 config.dat definition. That way
**	    the boundary users don't dictate the size of the mem pool (it being
**	    highly unlikely that all users will want big memory simultaneously).
**	12-dec-96 (inkdo01)
**	    Shamed into doing the above change more rigourously. Now a new 
**	    config parm (opf_maxmemf) defines the proportion of the OPF pool
**	    available to any session. This gets computed in opsstartup, so the
**	    code added for the previous change is now removed.
**	20-jun-1997 (nanpr01)
**	    Initialize the rdf_info_blk to NULL. This is specially required
**	    for  query without a base table.
**	23-oct-98 (inkdo01)
**	    Init opc_retrowno, opc_retrowoff for row producing procs.
**	27-oct-98 (inkdo01)
**	    Quicky afterthought to init opc_retrow_rsd.
**	11-oct-2006 (hayke02)
**	    Send E_OP0002_NOMEMORY to errlog.log. This change fixes bug 116309.
**      25-Nov-2008 (hanal04) Bug 121248
**          Initialise new caller_ref field in the opv_rdfcb to avoid SEGVs
**          later on.
**	25-feb-10 (smeke01) b123333
**	    As the NULL-ing of ops_trace.opt_conode has been remmoved from 
**	    opt_printCostTree() we need to make sure it is initialised here  
**	    prior to any call of opt_cotree() by trace point op145 (set qep).
[@history_line@]...
[@history_template@]...
*/
VOID
ops_init(
	OPF_CB             *opf_cb,
	OPS_STATE          *global)
{
    /* initialize some variables so that error recovery can determine which
    ** resources to free (i.e. which resources have been successfully
    ** allocated)
    ** - this must be done prior to the allocation of a memory stream since
    ** the streamid is used to indicate whether any resources at all have
    ** been allocated
    */

    global->ops_cb = (OPS_CB *)opf_cb->opf_scb; /* save session control block */
    /* global->ops_caller_cb initialized before exception handler established */
    global->ops_adfcb = global->ops_cb->ops_adfcb; /* get current ADF control
                                        ** block for session */
    if (global->ops_adfcb)
    {	/* init adf_constants since this may uninitialized after the
	** previous query executed by QEF, and may cause ADF to write
	** to deallocated memory */
	global->ops_adfcb->adf_constants = (ADK_CONST_BLK *)NULL;
    }
    global->ops_qheader = NULL;		
    global->ops_statement = NULL;		
    global->ops_procedure = NULL;	/* - NULL indicates that QSF query
                                        ** tree has not been fixed 
                                        ** - used by error handling to determine
                                        ** if this resource needs to be 
                                        ** deallocated
                                        */
    /* global->ops_lk_id initialized below */
    /* global->ops_parmtotal initialized below */

    global->ops_mstate.ops_streamid = NULL;/* init so deallocate routines do not
                                        ** access unless it is necessary */
    global->ops_mstate.ops_sstreamid = NULL; /* init so deallocate routines do
                                        ** not access unless it is necessary */
    global->ops_mstate.ops_tstreamid = NULL; /* the temporary buffer stream is
                                        ** allocated only when needed */
    global->ops_subquery = NULL;        /* initialize the subquery list */
    global->ops_osubquery = NULL;

    /* initialise pointer used in opt_printCostTree() for tracing CO node */
    global->ops_trace.opt_conode = NULL;  

    /* global->ops_astate initialized by aggregate processing phase */
    /* global->ops_estate initialized by joinop processing phase */
    global->ops_qpinit = FALSE;		/* query plan object not allocated yet*/
    global->ops_cstate.opc_prbuf = NULL;/* trace print buffer ptr. */
    global->ops_cstate.opc_relation = NULL;  /* init relation descriptor
                                            ** so deallocation routine will
                                            ** only be done if OPC allocates
                                            ** an RDF descriptor */
    global->ops_cstate.opc_retrowno = -1;
    global->ops_cstate.opc_retrowoff = 0;  /* result row buffer init */
    global->ops_cstate.opc_retrow_rsd = (PST_QNODE *) NULL;
    ops_qinit(global, (PST_STATEMENT *)NULL); /* init range table only for resource
					** deallocation */
    {
	/* allocate a memory stream to be used by the optimizer
        ** - the streamid PTR was initialized to NULL earlier - prior to the
        ** establishment of the exception handler so that it can be used
        ** to indicate to the cleanup routines that no resources have been
        ** allocated
        */
        DB_STATUS       ulmstatus;

        global->ops_mstate.ops_ulmrcb.ulm_facility = DB_OPF_ID; /* identifies optimizer
					** so that ULM can make SCF calls on
                                        ** behave of the optimizer */
        global->ops_mstate.ops_ulmrcb.ulm_poolid = global->ops_cb->ops_server->opg_memory;
                                        /* poolid of OPF
                                        ** obtained at server startup time */
        global->ops_mstate.ops_ulmrcb.ulm_blocksize = 0; /* use default for 
					** now */
        global->ops_mstate.ops_memleft =global->ops_cb->ops_alter.ops_maxmemory;
                                        /* save amount of memory which can be 
                                        ** used by this session */
        global->ops_mstate.ops_mlimit = global->ops_mstate.ops_memleft / 10;
					/* if 10% of memory is left trigger 
                                        ** garbage collection routines */
        global->ops_mstate.ops_ulmrcb.ulm_memleft = &global->ops_mstate.ops_memleft; /* 
					** and point to it for ULM */
	global->ops_mstate.ops_ulmrcb.ulm_streamid_p = &global->ops_mstate.ops_streamid; /*
					** Where ULM will return streamid */
	global->ops_mstate.ops_ulmrcb.ulm_flags = ULM_PRIVATE_STREAM;
					/* Allocate private, thread-safe streams */
        ulmstatus = ulm_openstream(&global->ops_mstate.ops_ulmrcb); /* get memory for the
                                        ** optimizer */
        if (DB_FAILURE_MACRO(ulmstatus))
	{
	    opx_lerror(E_OP0002_NOMEMORY, 0, 0, 0, 0, 0);
	    opx_verror( ulmstatus, E_OP0002_NOMEMORY, 
		global->ops_mstate.ops_ulmrcb.ulm_error.err_code);
	}
        global->ops_mstate.ops_tptr = NULL; /* init temp buffer ptr from 
                                        ** ops_tstreamid*/
        global->ops_mstate.ops_tsize = 0;          /* init temp buffer size */
					/* ULM has set ops_streamid to the
                                        ** streamid for "global optimizer"
                                        ** memory, note the enumeration will
                                        ** create other streamids for "local"
                                        ** memory but still use the 
                                        ** same control ops_ulmrcb 
                                        ** in order to decrement and
                                        ** increment the same "memleft" counter
                                        */
	/* initialize ptrs to full size array of ptrs, allocate once for DB procedure
	** or 4K will be wasted for each assignment statement and query */
        global->ops_mstate.ops_trt = NULL;
        global->ops_mstate.ops_tft = NULL;
        global->ops_mstate.ops_tat = NULL;
        global->ops_mstate.ops_tet = NULL;
        global->ops_mstate.ops_tbft = NULL;
	global->ops_mstate.ops_usemain = FALSE; /* disable redirection of
					** memory allocation */
	global->ops_mstate.ops_totalloc = 0;	/* init stats fields */
	global->ops_mstate.ops_countalloc = 0;
	global->ops_mstate.ops_count2kalloc = 0;
	global->ops_mstate.ops_recover = 0;
    }

    
    {
	/* get the procedure from QSF */
        DB_STATUS	       qsfstatus;  /* QSF return status */

	qsfstatus = ops_gqtree(global); /* get procedure from QSF */
        if (DB_FAILURE_MACRO(qsfstatus))
	    opx_verror( qsfstatus, E_OP0085_QSO_LOCK, 
		global->ops_qsfcb.qsf_error.err_code); /* report error */

    }

    {
	/* initialize the RDF control block used to fetch information for
        ** the global range table */
	RDR_RB                 *rdfrb;      /* ptr to RDF request block */

	rdfrb = &global->ops_rangetab.opv_rdfcb.rdf_rb;
	global->ops_rangetab.opv_rdfcb.rdf_info_blk = NULL;
        global->ops_rangetab.opv_rdfcb.caller_ref = (RDR_INFO **)NULL;
	rdfrb->rdr_db_id = global->ops_cb->ops_dbid; /* save the data base id
                                            ** for this session only */
        rdfrb->rdr_unique_dbid = global->ops_cb->ops_udbid; /* save unique
                                            ** dbid for all sessions */
        rdfrb->rdr_session_id = global->ops_cb->ops_sid; /* save the session id
                                            ** for this session */
        rdfrb->rdr_fcb = global->ops_cb->ops_server->opg_rdfhandle; /* save the
					    ** poolid for the RDF info */
        if (global->ops_cb->ops_smask & OPS_MDISTRIBUTED)
            rdfrb->rdr_r1_distrib = DB_3_DDB_SESS;
	else
            rdfrb->rdr_r1_distrib = 0;
	if (global->ops_cb->ops_smask & OPS_MCONDITION)
	    rdfrb->rdr_2types_mask = RDR2_TIMEOUT; /* indicate that timeout should
					    ** occur on all RDF accesses */
	else
	    rdfrb->rdr_2types_mask = 0;
	rdfrb->rdr_instr = RDF_NO_INSTR;
    }
}
Exemple #7
0
/*{
** Name: psq_bgn_session	- Begin a parser session.
**
**  INTERNAL PSF call format: status = psq_bgn_session(&psq_cb, &sess_cb);
**
**  EXTERNAL call format: status = psq_call(PSQ_BGN_SESSION, &psq_cb, &sess_cb);
**
** Description:
**      The psq_bgn_session function begins a parser session.  It should be
**	called each time a new user connects to a server.  There may be 
**      many parser sessions per database server.  There should be one parser 
**      session for each invocation of the database system that is connected 
**      to the server.  When starting a parser session, one has to tell it
**	what query language to use, and other session parameters.
**
** Inputs:
**      psq_cb
**          .psq_qlang                  The query language to use.
**          .psq_decimal
**		.psf_decspec		TRUE indicates that the decimal marker
**					has been specified.  FALSE means use the
**					default (a ".").
**		.psf_decimal		The character to use as a decimal marker
**					(if specified).
**	    .psq_distrib		Indicator for whether distributed
**					statements and constructs should be
**					accepted.
**	    .psq_sessid			Session id 
**	    .psq_server			address of server control block
**	    .psq_adf_cb			Pointer to session's ADF_CB
**	    .psq_dbid			Database id for this session.
**	    .psq_user			User name of 
**	    .psq_dba			User name of dba
**	    .psq_group			Group id of session
**	    .psq_aplid			Application id of session
**	    .psq_flag			bitmask containing the following flags:
**	      .psq_catupd		  TRUE means catalogs updateable
**	      .psq_warnings		  Set to TRUE if user wishes to see
**					  warnings on unsupported commands
**	    .psq_idxstruct		Structure for creating new indexes
**					(e.g. DB_ISAM_STORE)
**	    .psq_udbid			Unique database id for this session.
**	    .psq_ustat	 		User status flags from SCS_ICS
**	    .psq_dbxlate		Case translation semantics for the db
**	sess_cb				Pointer to session control block
**					(Can be NULL)
**
** Outputs:
**      psq_cb
**          .psq_error                  Error information
**		.err_code		    What error occurred
**		    E_PS0000_OK			Success
**		    E_PS0001_INTERNAL_ERROR	    Internal PSF problem
**		    E_PS0201_BAD_QLANG		    Bad query language specifier
**		    E_PS0203_NO_DECIMAL		    No decimal marker specified
**		    E_PS0204_BAD_DISTRIB	    Bad distributed
**						    specification
**		    E_PS0205_SRV_NOT_INIT	    Server not initialized
**		    E_PS0206_TOO_MANY_SESS	    Too many sessions at one
**						    time
**	Returns:
**	    E_DB_OK			Function completed normally.
**	    E_DB_WARN			Function completed with warning(s)
**	    E_DB_ERROR			Function failed; non-catastrophic error
**	    E_DB_SEVERE			Session is to be aborted
**	    E_DB_FATAL			Function failed; catastrophic error
**	Exceptions:
**	    none
**
** Side Effects:
**	    Causes memory to be allocated.
**	    Increments the session count in the server control block.
**
** History:
**	01-oct-85 (jeff)
**          written
**	28-jul-86 (jeff)
**	    Added initialization of pss_catupd and pss_idxstruct
**      26-aug-86 (seputis)
**          Removed definition of yaccstream
**	13-apr-87 (puree)
**	    Initialize prototype list for dynamic SQL.
**	24-apr-87 (stec)
**	    init pss_project.
**	11-may-87 (stec)
**	    store psq_udbid to pss_dbid.
**	04-sep-87 (stec)
**	    Added critical region code where needed.
**	02-oct-87 (stec)
**	    Added pss_journaling initialization.
**	13-jun-88 (stec)
**	    Added initialization of pss_ruset for DB procs.
**	08-mar-89 (andre)
**	    Copy dba_drop_all from PSQ_CB to PSS_SESBLK.
**	15-mar-89 (ralph)
**	    GRANT Enhancements, Phase 1:
**	    Copy psq_aplid to pss_aplid;
**	    Copy psq_group to pss_group.
**	16-mar-89 (neil)
**	    Initialized rule field.
**	27-jul-89 (jrb)
**	    Copy numeric literals flag into session cb.
**	27-oct-89 (ralph)
**	    Copy user status flags to session control block.
**	11-oct-89 (ralph)
**	    Initialize pss_rgset and pss_raset.
**	28-dec-89 (andre)
**	    Copy fips_mode from PSQ_CB to PSS_SESBLK.
**	13-feb-90 (andre)
**	    set scf_stype to SCU_EXCLUSIVE before calling scu_swait.
**	12-sep-90 (sandyh)
**	    Added support for session memory value calculated from psf
**	    memory startup parameter.
**	15-nov-90 (andre)
**	    check the return status after calling SCF to acquire or to release a
**	    semaphore.
**	    If an error occurred when trying to acquire the semaphore, return
**	    E_DB_SEVERE to abort the session.
**	    If an error occurred when trying to release the semaphore, return
**	    E_DB_FATAL to bring down the server.
**	17-may-91 (andre)
**	    store DBA name into sess_cb->pss_dbaname and NULL-terminate.
**	08-nov-91 (rblumer)
**          merged from 6.4:  25-jul-91 (andre)
**		if (psq_cb->psq_flag & PSQ_STRIP_NL_IN_STRCONST), set bit
**		PSS_STRIP_NL_IN_STRCONST in sess_cb->pss_ses_flag.  this will
**		indicate that we are connected to an older FE, so the scanners
**		will continue to strip NLs inside quoted strings;
**		this is required to fix bug 38098
**	14-jan-92 (barbara)
**	    Included ddb.h for Star.  Updated to check for distributed
**	    specification.
**	26-feb-92 (andre)
**	    if PSQ_REPAIR_SYSCAT is set in psq_cb->psq_flag, set
**	    PSS_REPAIR_SYSCAT in sess_cb->pss_ses_flags
**	30-mar-1992 (bryanp)
**	    Fill in pss_sess_owner with a session-unique owner name for use
**	    by temporary tables which are owned by this session.
**	02-jun-92 (andre)
**	    initialize pss_dependencies_stream to NULL to avloid use of illegal
**	    address throughout the parser.
**	24-nov-92 (ralph)
**	    CREATE SCHEMA:
**	    Initialize pss_prvgoval
**	22-dec-92 (rblumer)
**	    initialize pointer for statement-level rule list.
**	14-jan-93 (andre)
**	    remember whether we are running UPGRADEDB - this will enable us to
**	    decide whether IIDEVICES can be dropped - which is needed by
**	    UPGRADEDB
**	15-mar-93 (ralph)
**	    DELIM_IDENT: initialize pss_dbxlate to zero
**	08-apr-93 (andre)
**	    names of rule list headers in sess_cb have changed (and their
**	    number has doubled)
**	26-mar-93 (ralph)
**	    DELIM_IDENT: Must initialize pss_dbxlate from psq_cb.psq_dbxlate
**	    and pss_cat_owner from psq_cat_owner.
**	10-aug-93 (andre)
**	    fixed cause of a compiler warning
**	08-sep-93 (swm)
**	    Changed sizeof(DB_SESSID) to sizeof(CS_SID) to reflect recent CL
**	    interface revision.
**	20-sep-93 (rogerk)
**	    Changed default table create semantics to be WITH JOURNALING.
**	    Initialized the pss_ses_flag setting to include PSS_JOURNALING
**	    which mimics the user requesting "set journaling" to indicate that
**	    tables created should be journaled.
**	08-oct-93 (rblumer)
**	    increased values allowed in pss_trace vector, using PSS_TVALS.
**	18-oct-93 (rogerk)
**	    Added support for journal default override.  Check psf server
**	    control block flag for PSF_NO_JNL_DEFAULT override before setting
**	    the session parse flag to assume journaling on table creates.
**	15-nov-93 (andre)
**	    add code to initialize a newly added sess_cb->pss_flattening_flags
**	01-nov-93 (anitap)
**	    if PSQ_INGRES_PRIV is set in psq_cb->psq_flag, set
**	    PSS_INGRES_PRIV in sess_cb->pss_ses_flags.
**	17-dec-93 (rblumer)
**	    "FIPS mode" no longer exists.  It was replaced some time ago by
**	    several feature-specific flags (e.g. flatten_nosingleton and
**	    direct_cursor_mode).  So I removed all FIPS_MODE flags.
**	02-jan-94 (andre)
**	    if starting a local session, call DMF to determine whether the 
**	    database to which we are connected is being journaled and record 
**	    that information by setting (or not setting) PSS_JOURNALED_DB bit 
**	    in pss_ses_flags
**	 7-jan-94 (swm)
**	    Bug #58635
**	    Added PTR cast for pss_owner which has changed type to PTR.
**	17-mar-94 (robf)
**          Add support for PSQ_SELECT_ALL flag
**	13-Feb-1995 (canor01)
**	    initialize the pss_audit field in the session control block
**	09-Oct-1998 (jenjo02)
**	    Removed SCF semaphore functions, inlining the CS calls instead.
**	23-mar-1999 (thaju02)
**	    Modified '$Sess' to use #define DB_SESS_TEMP_OWNER. (B94067)
**      01-Dec-2000 (hanal04) Bug 100680 INGSRV 1123
**          If PSQ_RULE_UPD_PREFETCH is set turn on PSS_RULE_UPD_PREFETCH
**          in the session control block to signify that we should use
**          the prefetch stategy required to ensure consitent behaviour in
**          updating rules fired by updates.
**	10-Jan-2001 (jenjo02)
**	    Remove callback to SCF to get session id and ADF_CB;
**	    *ADF_CB now supplied by scsinit in PSQ_CB.
**	30-Jan-2004 (schka24)
**	    Get rid of a type-cast warning on adf cb.
**	3-Feb-2005 (schka24)
**	    Num-literals renamed to parser-compat, fix here.
**	15-june-06 (dougi)
**	    Add support for "before" triggers.
**	30-aug-06 (thaju02)
**	    If PSQ_RULE_DEL_PREFETCH is set turn on PSS_RULE_DEL_PREFETCH
**          in the session control block, for prefetch strategy to 
**          be applied for deletes. (B116355)
**	26-Oct-2009 (kiria01) SIR 121883
**	    Scalar sub-query support: Added copy of
**	    psq_flag.PSQ_NOCHK_SINGLETON_CARD to session flag
**	    for defaulting SET CARDINALITY_CHECK
**      November 2009 (stephenb)
**          Batch execution; initilization of new fields.
**      29-apr-2010 (stephenb)
**          Init batch_copy_optim.
**	04-may-2010 (miket) SIR 122403
**	    Init new sess_cb->pss_stmt_flags2.
**	19-May-2010 (kiria01) b123766
**	    Get cardinality check default from server block not psq_cb
**	21-Jul-2010 (kschendel) SIR 124104
**	    Initialize default compression from facility cb.
**	14-Oct-2010 (kschendel) SIR 124544
**	    Initialize default result structure from facility cb.
**	19-Nov-2010 (kiria01) SIR 124690
**	    Add support for setting installation wide collation defaults.
*/
DB_STATUS
psq_bgn_session(
	register PSQ_CB     *psq_cb,
	register PSS_SESBLK *sess_cb)
{
    i4		    err_code;
    i4			    i;
    DB_STATUS		    status = E_DB_OK;
    STATUS		    sem_status;
    i4		    sem_errno;
    bool		    leave_loop = TRUE;
    ULM_RCB		    ulm_rcb;

    /*
    ** No error to begin with.
    */
    psq_cb->psq_error.err_code = E_PS0000_OK;

    /*
    ** Do as much validity checking as possible before allocating any memory.
    ** That way, there won't be any cleaning up to do for the majority of
    ** errors.
    */

    /*
    ** Check for server initialized. This code could be placed within
    ** critical region, but this is not necessary, since this is a flag
    ** test.
    */
    if (!Psf_srvblk->psf_srvinit)
    {
	(VOID) psf_error(E_PS0205_SRV_NOT_INIT, 0L, PSF_CALLERR, &err_code,
	    &psq_cb->psq_error, 0);
	return (E_DB_ERROR);
    }

    /*
    ** Check for valid language spec.
    */
    if (psq_cb->psq_qlang != DB_QUEL && psq_cb->psq_qlang != DB_SQL)
    {
	(VOID) psf_error(E_PS0201_BAD_QLANG, 0L, PSF_CALLERR, &err_code,
	    &psq_cb->psq_error, 0);
	return (E_DB_ERROR);
    }
	
    /*
    ** Check whether language is allowed in this server.  This will be useful
    ** when we have configurable servers, where some query languages can be
    ** used and some can't. This code could be placed within a critical region
    ** but it is not necessary, since this is a flag test only.
    */
    if ((psq_cb->psq_qlang & Psf_srvblk->psf_lang_allowed) == 0)
    {
	(VOID) psf_error(E_PS0202_QLANG_NOT_ALLOWED, 0L, PSF_CALLERR, &err_code,
	    &psq_cb->psq_error, 0);
	return (E_DB_ERROR);
    }

    /*
    ** Make sure that the decimal character is actually specified.
    */
    if (!psq_cb->psq_decimal.db_decspec)
    {
	(VOID) psf_error(E_PS0203_NO_DECIMAL, 0L, PSF_CALLERR, &err_code,
	    &psq_cb->psq_error, 0);
	return (E_DB_ERROR);
    }

     /* Check distributed specification
    **
    ** a=local_server, b=distrib_server, c=distrib_session
    **
    **   a,b
    **
    **     00  01  11  10
    **    -----------------
    ** c  |   |   |   |   |
    **  0 | 1 | 1 | 0 | 0 |
    **    |   |   |   |   |
    **    -----------------  ==> ERROR
    **    |   |   |   |   |
    **  1 | 1 | 0 | 0 | 1 |
    **    |   |   |   |   |
    **    -----------------
    */
    if (   !(psq_cb->psq_distrib & (DB_1_LOCAL_SVR | DB_3_DDB_SESS))
	|| ((~psq_cb->psq_distrib & DB_2_DISTRIB_SVR)
	    && (psq_cb->psq_distrib & DB_3_DDB_SESS))
	)
    {
	psf_error(E_PS0204_BAD_DISTRIB, 0L, PSF_CALLERR, &err_code,
	    &psq_cb->psq_error,0);
	return (E_DB_ERROR);
    }

    /*
    ** Check for too many sessions in server at one time.
    ** This code must be executed as a critical region.
    */

    do		    /* something to break out of */
    {
	/* get the semaphore */
	if (sem_status = CSp_semaphore(1, &Psf_srvblk->psf_sem)) /* exclusive */
	{
	    status = E_DB_SEVERE;	/* abort the session */
	    sem_errno = E_PS020A_BGNSES_GETSEM_FAILURE;
	    break;
	}

	if (Psf_srvblk->psf_nmsess >= Psf_srvblk->psf_mxsess)
	{
	    (VOID) psf_error(E_PS0208_TOO_MANY_SESS, 0L, PSF_CALLERR, &err_code,
		&psq_cb->psq_error, 0);
	    status = E_DB_ERROR;
	    break;
	}

	/* Increment the session count */
	Psf_srvblk->psf_nmsess++;
	sess_cb->pss_psessid = ++Psf_srvblk->psf_sess_num;

	/* leave_loop has already been set to TRUE */
    } while (!leave_loop);

    /* if semaphore has been successfully acquired, try to release it */
    if (sem_status == OK)
    {
	if (sem_status = CSv_semaphore(&Psf_srvblk->psf_sem))
	{
	    status = E_DB_FATAL;	/* bring down the server */
	    sem_errno = E_PS020B_BGNSES_RELSEM_FAILURE;
	}
    }

    /*
    ** if an error was encountered while trying to get or to release a
    ** semaphore, report it here
    */
    if (sem_status != OK)
    {
	(VOID) psf_error(sem_errno, sem_status, PSF_INTERR,
	    &err_code, &psq_cb->psq_error, 0);
    }

    if (DB_FAILURE_MACRO(status))
    {
	return(status);
    }

    /*
    ** Initialize the case translation semantics stuff
    */
    sess_cb->pss_dbxlate = psq_cb->psq_dbxlate;
    sess_cb->pss_cat_owner = psq_cb->psq_cat_owner;

    /*
    ** Copy the user name and dba name to the session control block.
    */
    STRUCT_ASSIGN_MACRO(psq_cb->psq_user.db_tab_own, sess_cb->pss_user);
    STRUCT_ASSIGN_MACRO(psq_cb->psq_dba, sess_cb->pss_dba);
    STRUCT_ASSIGN_MACRO(psq_cb->psq_group, sess_cb->pss_group);
    STRUCT_ASSIGN_MACRO(psq_cb->psq_aplid, sess_cb->pss_aplid);

    /* copy DBA name into sess_cb->pss_dbaname and NULL-terminate */
    {
	u_i2			dba_name_len;

	dba_name_len = (u_i2) psf_trmwhite((u_i4) sizeof(sess_cb->pss_dba),
			    (char *) &sess_cb->pss_dba);
	MEcopy((PTR) &sess_cb->pss_dba, dba_name_len,
	       (PTR) sess_cb->pss_dbaname);

	sess_cb->pss_dbaname[dba_name_len] = EOS;
    }

    /*
    ** Build a DB_OWN_NAME which contains a session-unique owner name. This
    ** owner name will be used for temporary tables which are owned by this
    ** session.
    */
    {
	char	    temp_sess_id[10];

	STmove(DB_SESS_TEMP_OWNER, ' ', sizeof(sess_cb->pss_sess_owner),
		(char *)&sess_cb->pss_sess_owner);
	/*
	** We can't convert directly into the sess_owner field because CVlx
	** null-terminates the result, and we don't want the trailing null
	*/
	CVlx(sess_cb->pss_psessid, temp_sess_id);
	MEcopy(temp_sess_id, 8, &sess_cb->pss_sess_owner.db_own_name[5]);
    }

    /*
    ** Start with per-user quota of memory.  Note that user may have overridden
    ** the default value at server startup in which case we will use calculated
    ** amount (pool/sessions); otherwise, default amount will be used.
    */
    sess_cb->pss_memleft = (Psf_srvblk->psf_sess_mem) ? Psf_srvblk->psf_sess_mem
						      : PSF_SESMEM;

    /*
    ** Initialize the user range table.
    */
    if (pst_rginit(&sess_cb->pss_usrrange) != E_DB_OK)
    {
	return (E_DB_FATAL);
    }
	
    /*
    ** Initialize the auxiliary range table.
    */
    if (pst_rginit(&sess_cb->pss_auxrng) != E_DB_OK)
    {
	return (E_DB_FATAL);
    }

    /*
    ** Open a memory stream for the symbol table.  The symbol table is
    ** composed of a list of blocks.
    ** Allocate the symbol table at the same time.
    */
    ulm_rcb.ulm_facility = DB_PSF_ID;
    ulm_rcb.ulm_poolid = Psf_srvblk->psf_poolid;
    ulm_rcb.ulm_blocksize = sizeof(PSS_SYMBLK);
    ulm_rcb.ulm_memleft = &sess_cb->pss_memleft;
    /* Set pointer to stream handle for ULM */
    ulm_rcb.ulm_streamid_p = &sess_cb->pss_symstr;
    /* Open a private, thread-safe stream */
    ulm_rcb.ulm_flags = ULM_PRIVATE_STREAM | ULM_OPEN_AND_PALLOC;
    ulm_rcb.ulm_psize = sizeof(PSS_SYMBLK);
    if (ulm_openstream(&ulm_rcb) != E_DB_OK)
    {
	if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM)
	{
	    (VOID) psf_error(E_PS0F02_MEMORY_FULL, 0L, PSF_CALLERR, 
		&err_code, &psq_cb->psq_error, 0);
	}
	else
	{
	    (VOID) psf_error(E_PS0A02_BADALLOC, ulm_rcb.ulm_error.err_code,
		PSF_INTERR, &err_code, &psq_cb->psq_error, 0);
	}

	return((ulm_rcb.ulm_error.err_code == E_UL0004_CORRUPT) ? E_DB_FATAL
								: E_DB_ERROR);
    }

    sess_cb->pss_symtab = (PSS_SYMBLK*) ulm_rcb.ulm_pptr;
    sess_cb->pss_symtab->pss_sbnext = (PSS_SYMBLK *) NULL;

    /*
    ** Allocate the YACC_CB.  
    */

    if ((status = psl_yalloc(sess_cb->pss_symstr, 
	&sess_cb->pss_memleft,
	(PTR *) &sess_cb->pss_yacc, &psq_cb->psq_error)) != E_DB_OK)
    {
	/*
	** If the allocation failed, remember to close the streams, so the
	** memory associated with it will be freed.
	*/
	(VOID) ulm_closestream(&ulm_rcb);
	return (status);
    }
	
    /*
    ** Fill in the control block header.
    */
    sess_cb->pss_next = (PSS_SESBLK *) NULL;
    sess_cb->pss_prev = (PSS_SESBLK *) NULL;
    sess_cb->pss_length = sizeof(PSS_SESBLK);
    sess_cb->pss_type = PSS_SBID;
    sess_cb->pss_owner = (PTR)DB_PSF_ID;
    sess_cb->pss_ascii_id = PSSSES_ID;

    /*
    ** Initialize the session control block.
    */
    /* Save the session id */
    sess_cb->pss_sessid	    = psq_cb->psq_sessid;

    /* Set pointer to session's ADF_CB */
    sess_cb->pss_adfcb	    = (ADF_CB *) psq_cb->psq_adfcb;

    /* No cursors yet */
    sess_cb->pss_numcursors = 0;

    /* Language has already been validated */
    sess_cb->pss_lang = psq_cb->psq_qlang;

    /* Decimal spec has already been validated */
    sess_cb->pss_decimal = psq_cb->psq_decimal.db_decimal;

    /* Distributed spec has already been validated */
    sess_cb->pss_distrib = psq_cb->psq_distrib;

    /* Save the database id */
    sess_cb->pss_dbid = psq_cb->psq_dbid;

    /* Save the unique database id */
    sess_cb->pss_udbid = psq_cb->psq_udbid;

    /* Initialize QSF_RCB for use by psfmem.c functions */
    sess_cb->pss_qsf_rcb.qsf_type = QSFRB_CB;
    sess_cb->pss_qsf_rcb.qsf_ascii_id = QSFRB_ASCII_ID;
    sess_cb->pss_qsf_rcb.qsf_length = sizeof(sess_cb->pss_qsf_rcb);
    sess_cb->pss_qsf_rcb.qsf_owner = (PTR)DB_PSF_ID;
    sess_cb->pss_qsf_rcb.qsf_sid = sess_cb->pss_sessid;

    /*
    **	so session reset all bit flags
    */
    sess_cb->pss_stmt_flags = sess_cb->pss_stmt_flags2 =
	sess_cb->pss_dbp_flags = sess_cb->pss_ses_flag = 0L;
    sess_cb->pss_flattening_flags = 0;

    /*
    ** Default table create semantics are to assume journaling unless
    ** the PSF_NO_JNL_DEFAULT override is set.
    */
    if ((Psf_srvblk->psf_flags & PSF_NO_JNL_DEFAULT) == 0)
	sess_cb->pss_ses_flag |= PSS_JOURNALING;

	    /* catalog update flag */
    if (psq_cb->psq_flag & PSQ_CATUPD)
	sess_cb->pss_ses_flag |= PSS_CATUPD;

	    /* warnings on unsupported commands */
    if (psq_cb->psq_flag & PSQ_WARNINGS)
	sess_cb->pss_ses_flag |= PSS_WARNINGS;

	/* INDICATE if the DBA may DROP everyone's tables */
    if (psq_cb->psq_flag & PSQ_DBA_DROP_ALL)
	sess_cb->pss_ses_flag |= PSS_DBA_DROP_ALL;

	/* INDICATE if the session may SELECT everyone's tables */
    if (psq_cb->psq_flag & PSQ_SELECT_ALL)
	sess_cb->pss_ses_flag |= PSS_SELECT_ALL;

	/*
	** indicate that the session is allowed to INSERT/DELETE/UPDATE an index
	** which is a catalog (but not an extended catalog
	*/
    if (psq_cb->psq_flag & PSQ_REPAIR_SYSCAT)
	sess_cb->pss_ses_flag |= PSS_REPAIR_SYSCAT;

	/* 
	** indicate that the session allows $ingres to drop/add constraint on
	** tables owned by other users
	*/
    if (psq_cb->psq_flag & PSQ_INGRES_PRIV)
	sess_cb->pss_ses_flag |= PSS_INGRES_PRIV;	

    if (psq_cb->psq_flag & PSQ_ROW_SEC_KEY)
	sess_cb->pss_ses_flag |= PSS_ROW_SEC_KEY;

    /* See if passwords, roles allowed */
    if (psq_cb->psq_flag & PSQ_PASSWORD_NONE)
	sess_cb->pss_ses_flag |= PSS_PASSWORD_NONE;

    if (psq_cb->psq_flag & PSQ_ROLE_NONE)
	sess_cb->pss_ses_flag |= PSS_ROLE_NONE;

    if (psq_cb->psq_flag & PSQ_ROLE_NEED_PW)
	sess_cb->pss_ses_flag |= PSS_ROLE_NEED_PW;

	/* remember whether we are running UPGRADEDB */
    if (psq_cb->psq_flag & PSQ_RUNNING_UPGRADEDB)
	sess_cb->pss_ses_flag |= PSS_RUNNING_UPGRADEDB;

    /* Pick up serverwide default for card check */
    if (Psf_srvblk->psf_flags & PSF_NOCHK_SINGLETON_CARD)
	sess_cb->pss_ses_flag |= PSS_NOCHK_SINGLETON_CARD;

        /* Initialize pss_project. */
    sess_cb->pss_ses_flag |= PSS_PROJECT;	/* pss_project = TRUE */
    
    /* init last statement */
    sess_cb->pss_last_sname[0] = EOS;
    /* batch optimization switch starts undefined */
    sess_cb->batch_copy_optim = PSS_BATCH_OPTIM_UNDEF;

    /* 
    ** if starting a local session, determine whether the database is being 
    ** journaled
    */
    if (~psq_cb->psq_distrib & DB_3_DDB_SESS)
    {
        DMC_CB		    dmc_cb, *dmc = &dmc_cb;
        DMC_CHAR_ENTRY	    dmc_char;

	MEfill(sizeof(dmc_cb), (u_char) 0, (PTR) dmc);

        dmc->type = DMC_CONTROL_CB;
        dmc->length = sizeof(*dmc);
        dmc->dmc_op_type = DMC_DATABASE_OP;
	dmc->dmc_session_id = (PTR) sess_cb->pss_sessid;
        dmc->dmc_flags_mask = DMC_JOURNAL;
        dmc->dmc_char_array.data_address= (PTR) &dmc_char;
	dmc->dmc_char_array.data_out_size = sizeof(dmc_char);
	dmc->dmc_db_id = (char *) sess_cb->pss_dbid;
	
	status = dmf_call(DMC_SHOW, (PTR) dmc);
	if (DB_FAILURE_MACRO(status))
	{
	    (VOID) psf_error(E_PS020E_CANT_GET_DB_JOUR_STATUS, 
		dmc->error.err_code, PSF_INTERR, &err_code, 
		&psq_cb->psq_error, 0);
	    return(status);
	}

	if (dmc_char.char_value == DMC_C_ON)
	{
	    sess_cb->pss_ses_flag |= PSS_JOURNALED_DB;
	}
    }

    /* Save the storage structure for indexes */
    sess_cb->pss_idxstruct = psq_cb->psq_idxstruct;

    /* Make session copy of parser compatability settings */
    sess_cb->pss_parser_compat = psq_cb->psq_parser_compat;

    /* remember if NLs inside string constants need to be stripped */
    if (psq_cb->psq_flag & PSQ_STRIP_NL_IN_STRCONST)
	sess_cb->pss_ses_flag |= PSS_STRIP_NL_IN_STRCONST;

    /* no rule tree yet */
    sess_cb->pss_row_lvl_usr_rules  =
    sess_cb->pss_row_lvl_sys_rules  =
    sess_cb->pss_stmt_lvl_usr_rules =
    sess_cb->pss_stmt_lvl_sys_rules =
    sess_cb->pss_row_lvl_usr_before_rules  =
    sess_cb->pss_row_lvl_sys_before_rules  =
    sess_cb->pss_stmt_lvl_usr_before_rules =
    sess_cb->pss_stmt_lvl_sys_before_rules = (PST_STATEMENT *) NULL;

    if (psq_cb->psq_flag & PSQ_RULE_DEL_PREFETCH)
	sess_cb->pss_ses_flag |= PSS_RULE_DEL_PREFETCH;

    if(psq_cb->psq_flag2 & PSQ_RULE_UPD_PREFETCH)
        sess_cb->pss_ses_flag |= PSS_RULE_UPD_PREFETCH;

    /* copy user status flags to session control block */
    sess_cb->pss_ustat = psq_cb->psq_ustat;

    /*
    ** Initialize lots of pointer to NULL because nothing is happening yet.
    */
    sess_cb->pss_qbuf = sess_cb->pss_nxtchar = sess_cb->pss_prvtok =
	sess_cb->pss_bgnstmt = sess_cb->pss_endbuf =
	sess_cb->pss_prvgoval = (u_char *) NULL;

    /* initialize pss_audit */
    sess_cb->pss_audit = NULL;

    for (i = 0; i < PSS_CURTABSIZE; i++)
    {
	sess_cb->pss_curstab.pss_curque[i] = (PSC_CURBLK *) NULL;
    }

    /* initialize prototype list for dynamic SQL */
    sess_cb->pss_proto = (PST_PROTO *) NULL;

    /*
    ** pss_dependencies_stream, when not NULL, is expected to point at a valid
    ** stream descriptor.  After closing the stream we always reset
    ** pss_dependencies_stream to NULL, but in some cases we may end up checking
    ** pss_dependencies_stream before ever opening (and closing it).  As a
    ** result, you may end up using invalid address as a stream pointer.
    ** Initializing it here to NULL will ensure that it is non-NULL iff it
    ** points at a valid open stream descriptor.
    */
    sess_cb->pss_dependencies_stream = (PSF_MSTREAM *) NULL;

    /* No trace flags set */
    /* expect lint message */
    ult_init_macro(&sess_cb->pss_trace, PSS_TBITS, PSS_TVALS, PSS_TVAO);

    /* Cursor id set to 0, no cursors open yet */
    sess_cb->pss_crsid = 0;

    sess_cb->pss_create_compression = Psf_srvblk->psf_create_compression;

    /* SCF can pass a client requested result_structure, but if it
    ** doesn't, init from server default.
    */
    if (psq_cb->psq_result_struct != 0)
    {
	sess_cb->pss_result_struct = psq_cb->psq_result_struct;
	sess_cb->pss_result_compression = psq_cb->psq_result_compression;
    }
    else
    {
	sess_cb->pss_result_struct = Psf_srvblk->psf_result_struct;
	sess_cb->pss_result_compression = Psf_srvblk->psf_result_compression;
    }

    if (psq_cb->psq_def_coll > DB_NOCOLLATION)
	sess_cb->pss_def_coll = psq_cb->psq_def_coll;
    else
	sess_cb->pss_def_coll = Psf_srvblk->psf_def_coll;
    if (psq_cb->psq_def_unicode_coll > DB_NOCOLLATION)
	sess_cb->pss_def_unicode_coll = psq_cb->psq_def_unicode_coll;
    else
	sess_cb->pss_def_unicode_coll = Psf_srvblk->psf_def_unicode_coll;

    return (E_DB_OK);
}
Exemple #8
0
/*{
** Name: gwi_remove - remove a gateway index
**
** Description:
**	This function removes extended gateway index catalog information.  A
**	DMF external interface is used to update, namely delete, the extended
**	gateway index catalog, iigwX_index. This request must be made before
**	gateway index removal can be considered complete.
**
**	The GWF tcb cache for the base table is discarded since it is no longer
**	current.
**
** Inputs:
**	gw_rcb->		gateway request control block
**		session_id	an established session id
**		dmu->
**		  dmu_db_id	database id
**		  dmu_tran_id	transaction id
**		  dmu_tbl_id	base table id
**		  dmu_idx_id	INGRES index id
**		gw_id		gateway id, derived from DBMS type
**
** Output:
**	gw_rcb->
**		error.err_code	One of the following error numbers.
**                              E_GW0600_NO_MEM
**				E_GW0400_BAD_GWID
**				E_GW0006_XIDX_OPEN_FAILED
**      Returns:
**          E_DB_OK             Function completed normally. 
**          E_DB_ERROR          Function completed abnormally with 
**                              error.err_code.
** History:
**      28-Apr-1989 (alexh)
**          Created.
**	2-apr-90 (bryanp)
**	    If this gateway has no extended system catalogs, nothing to do.
**	09-apr-90 (linda)
**	    Added error handling, single return point.
**	18-apr-90 (bryanp)
**	    Return E_GW0600_NO_MEM when out of ULM memory.
**	28-mar-91 (linda)
**	    Fixed 2 problems:  (a) error on tuple delete from dmf was logged
**	    but did not cause this routine to return a bad status; (b) call to
**	    DMR_DELETE required DMR_CURRENT_POS in flags mask.
**      7-oct-92 (daveb)
**          prototyped.  Cast arg to gwu_copen (db_id is PTR).
*/
DB_STATUS
gwi_remove(GW_RCB *gw_rcb)
{
    GW_SESSION	    *session = (GW_SESSION *)gw_rcb->gwr_session_id;
    DMT_CB	    dmt;
    DMR_CB	    dmr;
    ULM_RCB	    ulm_rcb;
    DM_DATA	    xidx_buff;
    i4	    gw_id = gw_rcb->gwr_gw_id;
    i4		    xidx_sz = Gwf_facility->gwf_gw_info[gw_id].gwf_xidx_sz;
    DMR_ATTR_ENTRY  attkey[2];
    DMR_ATTR_ENTRY  *attkey_ptr[2];
    DB_TAB_ID	    sav_idx_id;
    DB_ERROR	    err;
    DB_STATUS	    status;
    DB_STATUS	    sav_status;

    for (;;)
    {
	if ((gw_id <= 0) || (gw_id >= GW_GW_COUNT) ||
	    (Gwf_facility->gwf_gw_info[gw_id].gwf_gw_exist == 0))
	{
	    (VOID) gwf_error(E_GW0400_BAD_GWID, (i4)0, GWF_INTERR, 1,
			     sizeof(gw_rcb->gwr_gw_id), &gw_rcb->gwr_gw_id);
	    gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
	    status = E_DB_ERROR;
	    break;
	}

	if (xidx_sz == 0)
	{
	    status = E_DB_OK;
	    break;
	}

	/* copy ulm_rcb */
	STRUCT_ASSIGN_MACRO(session->gws_ulm_rcb, ulm_rcb);
	xidx_buff.data_in_size = xidx_sz;
	ulm_rcb.ulm_blocksize = xidx_buff.data_in_size;

	/* allocate a iigwX_index buffer from a temporary  memory stream */
	if ((status = ulm_openstream(&ulm_rcb)) != E_DB_OK)
	{
	    (VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0);
	    (VOID) gwf_error(E_GW0312_ULM_OPENSTREAM_ERROR, GWF_INTERR, 3,
			     sizeof(*ulm_rcb.ulm_memleft),
			     ulm_rcb.ulm_memleft,
			     sizeof(ulm_rcb.ulm_sizepool),
			     &ulm_rcb.ulm_sizepool,
			     sizeof(ulm_rcb.ulm_blocksize),
			     &ulm_rcb.ulm_blocksize);
	    if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM)
		gw_rcb->gwr_error.err_code = E_GW0600_NO_MEM;
	    else
		gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;
	    break;
	}

	ulm_rcb.ulm_psize = ulm_rcb.ulm_blocksize;
	if ((status = ulm_palloc(&ulm_rcb)) != E_DB_OK)
	{
	    (VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0);
	    (VOID) gwf_error(E_GW0314_ULM_PALLOC_ERROR, GWF_INTERR, 4,
			     sizeof(*ulm_rcb.ulm_memleft),
			     ulm_rcb.ulm_memleft,
			     sizeof(ulm_rcb.ulm_sizepool),
			     &ulm_rcb.ulm_sizepool,
			     sizeof(ulm_rcb.ulm_blocksize),
			     &ulm_rcb.ulm_blocksize,
			     sizeof(ulm_rcb.ulm_psize),
			     &ulm_rcb.ulm_psize);
	    if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM)
		gw_rcb->gwr_error.err_code = E_GW0600_NO_MEM;
	    else
		gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;

	    if ((status = ulm_closestream(&ulm_rcb)) != E_DB_OK)
	    {
		(VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0);
		(VOID) gwf_error(E_GW0313_ULM_CLOSESTREAM_ERROR, GWF_INTERR, 1,
				 sizeof(*ulm_rcb.ulm_memleft),
				 ulm_rcb.ulm_memleft);
	    }
	    status = E_DB_ERROR;    /* reset after closestream call */
	    break;
	}

	xidx_buff.data_address = ulm_rcb.ulm_pptr;

	/* initialize dmt_sequence */
	dmt.dmt_sequence = gw_rcb->gwr_gw_sequence;

	/* set up position for iigwXX_index catalog*/
	attkey[0].attr_number = 1;
	attkey[0].attr_operator = DMR_OP_EQ;
	attkey[0].attr_value = (char *)&gw_rcb->gwr_tab_id.db_tab_base;
	attkey[1].attr_number = 2;
	attkey[1].attr_operator = DMR_OP_EQ;
	attkey[1].attr_value = (char *)&gw_rcb->gwr_tab_id.db_tab_index;

	attkey_ptr[0] = &attkey[0];
	attkey_ptr[1] = &attkey[1];

	dmr.type = DMR_RECORD_CB;
	dmr.length = sizeof(DMR_CB);
	dmr.dmr_flags_mask = 0;
	dmr.dmr_position_type = DMR_QUAL;
	dmr.dmr_attr_desc.ptr_in_count = 2;
	dmr.dmr_attr_desc.ptr_size = sizeof(DMR_ATTR_ENTRY);
	dmr.dmr_attr_desc.ptr_address = (PTR)&attkey_ptr[0];
	dmr.dmr_access_id = dmt.dmt_record_access_id;
	dmr.dmr_q_fcn = NULL;

	/* open the iigwX_index catalog */
	if ((status = gwu_copen(&dmt, &dmr, session->gws_scf_session_id, 
		(PTR)gw_rcb->gwr_database_id, gw_id, gw_rcb->gwr_xact_id,
		&gw_rcb->gwr_tab_id,
		&session->gws_gw_info[gw_id].gws_xidx_tab_name,
		DMT_A_WRITE, TRUE, &err)) != E_DB_OK)
	{
	    switch (dmt.error.err_code)
	    {
		case    E_DM0042_DEADLOCK:
		    gw_rcb->gwr_error.err_code = E_GW0327_DMF_DEADLOCK;
		    break;

		default:
		    (VOID) gwf_error(err.err_code, GWF_INTERR, 0);
		    gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;
		    break;
	    }

	    if ((status = ulm_closestream(&ulm_rcb)) != E_DB_OK)
	    {
		(VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0);
		(VOID) gwf_error(E_GW0313_ULM_CLOSESTREAM_ERROR, GWF_INTERR, 1,
				 sizeof(*ulm_rcb.ulm_memleft),
				 ulm_rcb.ulm_memleft);
		gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;
	    }
	    break;
	}

	dmr.dmr_flags_mask = DMR_NEXT;
	STRUCT_ASSIGN_MACRO(xidx_buff, dmr.dmr_data);
	dmr.dmr_char_array.data_address = 0;

	/*
	**	Delete the index entry with index and base table id
	*/
	do
	{
	    status = (*Dmf_cptr)(DMR_GET, &dmr);
	}
	while (status == E_DB_OK &&
		MEcmp((PTR)dmr.dmr_data.data_address,
		      (PTR)&gw_rcb->gwr_tab_id,
		      sizeof(DB_TAB_ID))
		);

	if (status == E_DB_OK)
	{
	    dmr.dmr_flags_mask |= DMR_CURRENT_POS;
	    if ((status = (*Dmf_cptr)(DMR_DELETE, &dmr)) != E_DB_OK)
	    {
		switch (dmt.error.err_code)
		{
		    case    E_DM0042_DEADLOCK:
			gw_rcb->gwr_error.err_code = E_GW0327_DMF_DEADLOCK;
			break;

		    default:
			(VOID) gwf_error(dmr.error.err_code, GWF_INTERR, 0);
			(VOID) gwf_error(E_GW0322_DMR_DELETE_ERROR, GWF_INTERR,
				     2, sizeof(gw_rcb->gwr_tab_id.db_tab_base),
				     &gw_rcb->gwr_tab_id.db_tab_base,
				     sizeof(gw_rcb->gwr_tab_id.db_tab_index),
				     &gw_rcb->gwr_tab_id.db_tab_index);
			gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;
			break;
		}
		if (dmt.error.err_code == E_DM0042_DEADLOCK)
			break;
		/* (Else no break; we still want to close index catalog.) */
	    }
	}
	else	/* status != E_DB_OK */
	{
	    switch (dmt.error.err_code)
	    {
		case    E_DM0042_DEADLOCK:
		    gw_rcb->gwr_error.err_code = E_GW0327_DMF_DEADLOCK;
		    break;

		default:
		    (VOID) gwf_error(dmr.error.err_code, GWF_INTERR, 0);
		    (VOID) gwf_error(E_GW0321_DMR_GET_ERROR, GWF_INTERR, 2,
				     sizeof(gw_rcb->gwr_tab_id.db_tab_base),
				     &gw_rcb->gwr_tab_id.db_tab_base,
				     sizeof(gw_rcb->gwr_tab_id.db_tab_index),
				     &gw_rcb->gwr_tab_id.db_tab_index);
		    gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;
		    break;
	    }
	    if (dmt.error.err_code == E_DM0042_DEADLOCK)
		    break;
	    /* (Else no break; we still want to close index catalog.) */
	}

	sav_status = status;	/* in case of non-deadlock error above */

	if ((status = (*Dmf_cptr)(DMT_CLOSE, &dmt)) != E_DB_OK)
	{
	    switch (dmt.error.err_code)
	    {
		case    E_DM0042_DEADLOCK:
		    gw_rcb->gwr_error.err_code = E_GW0327_DMF_DEADLOCK;
		    break;

		default:
		    (VOID) gwf_error(dmt.error.err_code, GWF_INTERR, 0);
		    (VOID) gwf_error(E_GW0325_DMT_CLOSE_ERROR, GWF_INTERR, 2,
				     sizeof(dmt.dmt_id.db_tab_base),
				     &dmt.dmt_id.db_tab_base,
				     sizeof(dmt.dmt_id.db_tab_index),
				     &dmt.dmt_id.db_tab_index);
		    gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;
		    break;
	    }
	}

	/* 
	**  delete tcb from GWF cache since its index info cannot be current.
	*/
	/*
	** First save index's tab_id, set base to 0 for call.
	*/
	_VOID_ MEcopy((PTR)&gw_rcb->gwr_tab_id, sizeof(DB_TAB_ID),
		      (PTR)&sav_idx_id);
	gw_rcb->gwr_tab_id.db_tab_index = 0;

	if ((status = gwu_deltcb(gw_rcb, GWU_TCB_OPTIONAL, &err)) != E_DB_OK)
	{
	    (VOID) gwf_error(err.err_code, GWF_INTERR, 0);
	    gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;
	    _VOID_ MEcopy((PTR)&sav_idx_id, sizeof(DB_TAB_ID),
			  (PTR)&gw_rcb->gwr_tab_id);
	    break;
	}
	_VOID_ MEcopy((PTR)&sav_idx_id, sizeof(DB_TAB_ID),
		      (PTR)&gw_rcb->gwr_tab_id);

	if ((status = ulm_closestream(&ulm_rcb)) != E_DB_OK)
	{
	    (VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0);
	    (VOID) gwf_error(E_GW0313_ULM_CLOSESTREAM_ERROR, GWF_INTERR, 1,
			     sizeof(ulm_rcb.ulm_error.err_code),
			     &ulm_rcb.ulm_error.err_code);
	    gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;
	    break;
	}

	/*
	** If we get here, things went okay after the tuple delete.  Recheck
	** status from that call.
	*/
	if (sav_status == E_DB_OK)
	{
	    gw_rcb->gwr_error.err_code = E_DB_OK;
	}
	else
	{
	    status = sav_status;
	    gw_rcb->gwr_error.err_code = E_GW0209_GWI_REMOVE_ERROR;
	}
	break;
    }

    return(status);
}
Exemple #9
0
/*
** Name: gwi_register - register a gateway index
**
** Description:
**	This function registers extended gateway  index catalog information.  A
**	DMF external interface is used to update, namely put, the extended
**	gateway catalog,  iigwX_index.  This request  must be made before
**	gateway index registration can be considered complete.
**
**	The GWF tcb cache for the base table is discarded since it is no longer
**	current.
**
** Inputs:
**	gw_rcb->		gateway request control block
**		session_id	an established session id
**		dmu->
**		  dmu_db_id	database id
**		  dmu_tran_id	transaction id
**		  dmu_tbl_id	base table id
**		  dmu_idx_id	INGRES index id
**		gw_id		gateway id, derived from DBMS type
**		in_vdata2	source of the gateway index.
**
** Output:
**	gw_rcb->
**		error.err_code	One of the following error numbers.
**                              E_GW0600_NO_MEM
**				E_GW0400_BAD_GWID
**				E_GW0208_GWI_REGISTER_ERROR
**				E_GW0006_XIDX_OPEN_FAILED
**      Returns:
**          E_DB_OK             Function completed normally. 
**          E_DB_ERROR          Function completed abnormally with 
**                              error.err_code.
** History:
**      28-Apr-1989 (alexh)
**          Created.
**	2-apr-90 (bryanp)
**	    If gateway has no extended system catalog, nothing to do.
**	09-apr-90 (linda)
**	    Add error handling and single return point.
**	18-apr-90 (bryanp)
**	    Return E_GW0600_NO_MEM when out of ULM memory.
**	1-jul-91 (rickh)
**	    If the gateway exit returns an error, don't clobber the status
**	    word when we close the stream!  Also, if the exit has already
**	    reported the problem, spare us the uninformative yet alarming
**	    error-babble of higher facilities.
**	7-oct-92 (robf)
**	    Still create Xrelation & Xattribute entries even if no Xindex
**	    table - a gateway may need rel/attr entires but not the
**	    index one
**      7-oct-92 (daveb)
**          Hand the exit the session pointer, in case it wants to add
**          an exit-private SCB.  Prototyped.  Removed dead vars xrel_sz
**          and sav_idx_id.  Cast db_id arg to gwu_copen; it's a PTR.
**	17-nov-92 (robf)
**	    Changed calls to gwf_display() to use array rather than
**	    arg list.
*/
DB_STATUS
gwi_register(GW_RCB *gw_rcb)
{
    GWX_RCB	gwx;
    ULM_RCB	ulm_rcb;
    GW_SESSION	*session = (GW_SESSION *)gw_rcb->gwr_session_id;
    DMT_CB	dmt;
    DMR_CB	dmr;
    i4     gw_id = gw_rcb->gwr_gw_id;
    i4          xidx_sz = Gwf_facility->gwf_gw_info[gw_id].gwf_xidx_sz;
    DB_STATUS	status;
    DB_STATUS	ulm_status;
    DB_ERROR	err;
    char	trbuf[GWF_MAX_MSGLEN + 1]; /* last char for `\n' */

    if(GWF_MAIN_MACRO(12))
    {
	gwf_display(gwf_scctalk, 0, trbuf, sizeof(trbuf) - 1,
	    "GWI_REGISTER: REGISTER INDEX entry\n");
    }
    for (;;)
    {
	if ((gw_id <= 0) || (gw_id >= GW_GW_COUNT) ||
	    (Gwf_facility->gwf_gw_info[gw_id].gwf_gw_exist == 0))
	{
	    (VOID) gwf_error(E_GW0400_BAD_GWID, (i4)0, GWF_INTERR, 1,
			     sizeof(gw_id), &gw_id);
	    gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
	    status = E_DB_ERROR;
	    break;
	}
	/*
	** Allocate a memory stream for the life of this operation.  Used as
	** storage for temporary structures.  Note that it is allocated from
	** the session's GWF memory stream.
	*/
	STRUCT_ASSIGN_MACRO(session->gws_ulm_rcb, ulm_rcb);
	ulm_rcb.ulm_blocksize = xidx_sz;
	if ((status = ulm_openstream(&ulm_rcb)) != E_DB_OK)
	{
		(VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0);
		(VOID) gwf_error(E_GW0312_ULM_OPENSTREAM_ERROR, GWF_INTERR, 3,
			 sizeof(*ulm_rcb.ulm_memleft),
			 ulm_rcb.ulm_memleft,
			 sizeof(ulm_rcb.ulm_sizepool),
			 &ulm_rcb.ulm_sizepool,
			 sizeof(ulm_rcb.ulm_blocksize),
			 &ulm_rcb.ulm_blocksize);
		if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM)
			gw_rcb->gwr_error.err_code = E_GW0600_NO_MEM;
		else
			gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
		break;
	}
	/*
	**	Only process extended index info if this gateway has an
	**	extended index catalog
	*/
	if (Gwf_facility->gwf_gw_info[gw_id].gwf_xidx_sz > 0)
	{

	    gwx.xrcb_tab_id = &gw_rcb->gwr_tab_id;
/*	    STRUCT_ASSIGN_MACRO(gw_rcb->gwr_tab_id, gwx.xrcb_tab_id);    */
	    gwx.xrcb_gw_id = gw_id;
	    STRUCT_ASSIGN_MACRO(gw_rcb->gwr_in_vdata2, gwx.xrcb_var_data2);


	    /* allocate iigwX_index tuple buffer */
	    gwx.xrcb_var_data1.data_in_size =
	        ulm_rcb.ulm_psize = ulm_rcb.ulm_blocksize; 
	    if ((status = ulm_palloc(&ulm_rcb)) != E_DB_OK)
	    {
	        (VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0);
	        (VOID) gwf_error(E_GW0314_ULM_PALLOC_ERROR, GWF_INTERR, 4,
	    		     sizeof(*ulm_rcb.ulm_memleft),
	    		     ulm_rcb.ulm_memleft,
	    		     sizeof(ulm_rcb.ulm_sizepool),
	    		     &ulm_rcb.ulm_sizepool,
	    		     sizeof(ulm_rcb.ulm_blocksize),
	    		     &ulm_rcb.ulm_blocksize,
	    		     sizeof(ulm_rcb.ulm_psize),
	    		     &ulm_rcb.ulm_psize);
	        if (ulm_rcb.ulm_error.err_code == E_UL0005_NOMEM)
	    	gw_rcb->gwr_error.err_code = E_GW0600_NO_MEM;
	        else
	    	gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
	        break;
	    }
	    gwx.xrcb_var_data1.data_address = ulm_rcb.ulm_pptr;

	    /* request exit format */
	    if ((status =
	    	(*Gwf_facility->gwf_gw_info[gw_id].gwf_gw_exits	[GWX_VIDXF])
	    	    (&gwx)) !=  E_DB_OK)
	    {
	        if ( gwx.xrcb_error.err_code == E_GW050E_ALREADY_REPORTED )
	        {
			gw_rcb->gwr_error.err_code = E_GW050E_ALREADY_REPORTED;
	        }
	        else
	        {
			(VOID) gwf_error(gwx.xrcb_error.err_code, GWF_INTERR, 0);
			gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
	        }

	        if ((ulm_status = ulm_closestream(&ulm_rcb)) != E_DB_OK)
	        {
			(VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0);
			(VOID) gwf_error(E_GW0313_ULM_CLOSESTREAM_ERROR, GWF_INTERR, 1,
					 sizeof(*ulm_rcb.ulm_memleft),
					 ulm_rcb.ulm_memleft);
			break;
	        }

	        break;
	    }
	    else
	    {
	        /* initialize dmt_sequence */
	        dmt.dmt_sequence = gw_rcb->gwr_gw_sequence;

	        /* request DMF to append tuples */
	        status = gwu_copen(&dmt, &dmr, session->gws_scf_session_id, 
	            (PTR) gw_rcb->gwr_database_id, gw_id, gw_rcb->gwr_xact_id,
	            &gw_rcb->gwr_tab_id,
		    &session->gws_gw_info[gw_id].gws_xidx_tab_name,
	            DMT_A_WRITE, FALSE, &err);

	        /* put the iigwX_index tuple */
	        if ( status == E_DB_OK)
	        {
	    	STRUCT_ASSIGN_MACRO(gwx.xrcb_var_data1, dmr.dmr_data);
	    	if ((status = (*Dmf_cptr)(DMR_PUT, &dmr)) == E_DB_OK)
	    	{
	    	    status = (*Dmf_cptr)(DMT_CLOSE, &dmt);
	    	    if (status != E_DB_OK)
	    	    {
	    		/* Handle error from close */
	    		(VOID) gwf_error(dmt.error.err_code, GWF_INTERR, 0);
	    		gw_rcb->gwr_error.err_code =
	    			    E_GW0208_GWI_REGISTER_ERROR;
	    		break;
	    	    }
	    	}
	    	else
	    	{
	    	    /* Handle error from put */
	    	    switch (dmt.error.err_code)
	    	    {
	    		case    E_DM0042_DEADLOCK:
	    		    gw_rcb->gwr_error.err_code = E_GW0327_DMF_DEADLOCK;
	    		    break;

	    		default:
	    		    (VOID) gwf_error(dmt.error.err_code, GWF_INTERR, 0);
	    		    gw_rcb->gwr_error.err_code =
	    				E_GW0208_GWI_REGISTER_ERROR;
	    		    break;
	    	    }
	    	    break;
	    	}
	        }
	        else
	        {
			/* Handle error from gwu_copen() */
			(VOID) gwf_error(err.err_code, GWF_INTERR, 0);
			gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
			break;
	        }

	        /* 
	        **	delete tcb from GWF cache since its index info cannot be
	        **	current.
	        **
	        **** Not clear that we care about this. We probably can't remove
	        **** an index if it is being used and it is only referenced in its
	        **** own tcb.
	        */
#if 0
	        /*
	        ** Save the index's table id, set db_tab_index to 0 for the call.
	        */
	        _VOID_ MEcopy((PTR)&gw_rcb->gwr_tab_id, sizeof(DB_TAB_ID),
	    		  (PTR)&sav_idx_id);
	        gw_rcb->gwr_tab_id.db_tab_index = 0;

	        if ((status = gwu_deltcb(gw_rcb, GWU_TCB_OPTIONAL, &err))
	    	    != E_DB_OK)
	        {
			(VOID) gwf_error(err.err_code, GWF_INTERR, 0);
			gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
			_VOID_ MEcopy((PTR)&sav_idx_id, sizeof(DB_TAB_ID),
	    		      (PTR)&gw_rcb->gwr_tab_id);
			break;
	        }
	        _VOID_ MEcopy((PTR)&sav_idx_id, sizeof(DB_TAB_ID),
	    		  (PTR)&gw_rcb->gwr_tab_id);
#endif	    /* 0 */
	    }
	} /* End if Xindex processing */

	/*
	** Append a tuple to iigwX_relation catalog for this index.
	*/
	if ((status = gwi_map_idx_rel(gw_rcb, &dmt, &dmr, &ulm_rcb)) != E_DB_OK)
	{
	    _VOID_ gwf_error(gw_rcb->gwr_error.err_code, GWF_INTERR, 0);
	    gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
	    break;
	}

	/*
	** Now append iigwX_attribute tuples.
	*/

	if ((status = gwi_map_idx_att(gw_rcb, &ulm_rcb)) != E_DB_OK)
	{
	    _VOID_ gwf_error(gw_rcb->gwr_error.err_code, GWF_INTERR, 0);
	    gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
	    break;
	}

	/* close the temporary stream */
	if ((status = ulm_closestream(&ulm_rcb)) != E_DB_OK)
	{
	    (VOID) gwf_error(ulm_rcb.ulm_error.err_code, GWF_INTERR, 0);
	    (VOID) gwf_error(E_GW0313_ULM_CLOSESTREAM_ERROR, GWF_INTERR, 1,
			     sizeof(*ulm_rcb.ulm_memleft),
			     ulm_rcb.ulm_memleft);
	    gw_rcb->gwr_error.err_code = E_GW0208_GWI_REGISTER_ERROR;
	    break;
	}

	/* If we get here everything is okay. */
	break;
    }

    if (status == E_DB_OK)
	gw_rcb->gwr_error.err_code = E_DB_OK;

    return(status);
}