Exemplo n.º 1
0
DB_STATUS
adc_getempty(
ADF_CB              *adf_scb,
DB_DATA_VALUE	    *adc_emptydv)	/* Ptr to empty/null data value */
{
    i4			bdt = abs((i4) adc_emptydv->db_datatype);
    i4			bdtv;
    DB_STATUS		db_stat;


    /* Does the datatype exist? */
    bdtv = ADI_DT_MAP_MACRO(bdt);
    if (bdtv <= 0  ||  bdtv > ADI_MXDTS
	||  Adf_globs->Adi_dtptrs[bdtv] == NULL)
	return(adu_error(adf_scb, E_AD2004_BAD_DTID, 0));

    /*
    **	  If datatype is non-nullable, call the function associated with this
    ** datatype to initialize a data value to be "empty".  Currently, this is
    ** only one function for the RTI known datatypes.  This level of indirection
    ** is provided for the implementation of user-defined datatypes in the
    ** future.
    **
    **    If datatype is nullable, we can set the null value right here since it
    ** will be done the same way for all nullable datatypes.
    */

    if (adc_emptydv->db_datatype > 0)		/* non-nullable */
    {
        db_stat = (*Adf_globs->Adi_dtptrs[ADI_DT_MAP_MACRO(bdt)]->
				    adi_dt_com_vect.adp_getempty_addr)
	    		(adf_scb, adc_emptydv);
    }
    else
    {
	ADF_SETNULL_MACRO(adc_emptydv);
	/*
	**  If the datatype is peripheral, then we clear its length as
	**  well.  This is because ADF guarantees that the lengths are
	**  always correct for peripheral datatypes
	*/

	if (Adf_globs->Adi_dtptrs[ADI_DT_MAP_MACRO(bdt)]->
		    adi_dtstat_bits & AD_PERIPHERAL)
	{
	    ((ADP_PERIPHERAL *) adc_emptydv->db_data)->per_length0 = 0;
	    ((ADP_PERIPHERAL *) adc_emptydv->db_data)->per_length1 = 0;
	    ((ADP_PERIPHERAL *) adc_emptydv->db_data)->per_tag = ADP_P_COUPON;
	}
	db_stat = E_DB_OK;
    }

    return(db_stat);
}
Exemplo n.º 2
0
/*{
** Name: adu_rdm2_finish	- Finish Redeeming an ADF_COUPON
**
** Description:
**      This routine completes the action of redeeming a coupon.
**      If running in test mode, this routine makes sure that the
**      varchar field is padded out with the appropriate amount of
**      garbage.
**
**      In general, it places the "closing remarks" in the
**      data stream.  This means that it will place the final segment
**      indicator (saying "no more") in the stream if the stream is
**      destined for GCA.  If the datatype is nullable, then the null
**      bit is set/cleared as appropriate.  If there is insufficient
**      room to make these closing remarks (or to supply the correct
**      amount of garbage in the test case), then the fip_state is set
**      to ADW_F_DONE_NEED_NULL, and an incomplete status is returned.
**      This status will set up the main redeem call to call this
**      routine again with a new buffer, repeating this action until
**      all is done.
**
** Inputs:
**      adf_scb                        Standard ADF SCB Ptr
**      result_dv                      Ptr to output area DB_DATA_VALUE
**      coupon_dv                      PTR to input area DB_DATA_VALUE
**      work                           Ptr to ADP_LO_WKSP in which work
**                                         is done.
**          ->adw_shared               Contains the result of the action
**                                         so far
**          ->adw_fip                  Contains more such results
**      for_gca                        Nat indicating whether the result
**                                         is destined for GCA
**                                         transmission.
**
** Outputs:
**      adf_scb->adf_error             Filled as appropriate.
**      result_dv->db_length           Set correctly.
**      work->adw_fip.fip_state        Set to indicate whether to
**                                         return.
**      work->adw_fip.fip_test*        Set to control the garbage
**                                         returned for the test cases.
**
**	Returns:
**	    DB_STATUS
**	Exceptions:
**	    None
**
** Side Effects:
**	    None
**
** History:
**      07-dec-1989 (fred)
**          Prototyped.
**      06-oct-1992 (fred)
**          Altered to work with timezone integration.  As a temporary measure,
**	    this routine was using the ADF_CB.adf_4rsvd field to store
**	    some context across calls.  In that this field disappeared, a new,
**	    more appropriately named field was added (adf_lo_context).  This
**	    new ADF_CB field is now used in this file.
**	30-Oct-1992 (fred)
**	    Fixed to correctly handle being called with a length too short
**	    for the original header.
**	20-Nov-1992 (fred)
**	    Rewritten for better clarity & better delineation of
**	    function in support of OME large objects.
[@history_template@]...
*/
DB_STATUS static
adu_rdm2_finish(ADF_CB             *adf_scb,
		DB_DATA_VALUE      *result_dv,
		DB_DATA_VALUE      *coupon_dv,
		ADP_LO_WKSP        *work,
		i4                for_gca)
{
    DB_STATUS         status = E_DB_OK;
    i4                zero = 0;

    if (work->adw_shared.shd_l1_check != work->adw_fip.fip_l1_value)
    {
	/* Fix_me -- get more detailed error message to log (log_key, */
	/* what's wrong, etc. */

	/* Then we are sending an inconsistent blob */

	status = adu_error(adf_scb, E_AD7004_ADP_BAD_BLOB,0);
    }
    else if (result_dv->db_length >=
	     (work->adw_shared.shd_o_used + (for_gca * sizeof(i4)) +
	                                        work->adw_fip.fip_null_bytes))

    {
	if (for_gca)
	{
	    I4ASSIGN_MACRO(zero,
			   result_dv->db_data[work->adw_shared.shd_o_used]);
	    work->adw_shared.shd_o_used += sizeof(i4);
	}
	if (work->adw_fip.fip_test_mode)
	{
	    work->adw_fip.fip_test_sent += sizeof(i4);
	    if (work->adw_fip.fip_test_sent <=
		    (work->adw_fip.fip_test_length -
		                      work->adw_fip.fip_null_bytes))

	    {
		/* Then there isn't enough to fill the varchar() */

		if (result_dv->db_length <
		    (work->adw_fip.fip_test_length
		         - work->adw_fip.fip_test_sent))
		{
		    /*
		    ** This is for test purposes only.
		    **
		    ** We need to send a true VARCHAR() datatype.
		    ** Thus, if the blob os smaller than that, then we
		    ** need to pad it out with garbage bytes.  To do
		    ** so, we will increment test_sent by the
		    ** remainder of the buffer, and happily return,
		    ** knowing that we will arrive here with an empty
		    ** buffer in the relatively near future.
		    **
		    ** To set test_sent appropriately, we must first
		    ** decrement it by the amount it was incremented
		    ** before arriving here.  Then we increment as
		    ** appropriate.
		    */
		
		    work->adw_fip.fip_test_sent -=
			work->adw_shared.shd_o_used; 
		    work->adw_fip.fip_test_sent += result_dv->db_length;
		    work->adw_fip.fip_state = ADW_F_DONE_NEED_NULL;
		    adf_scb->adf_errcb.ad_errcode  = E_AD0002_INCOMPLETE;
		    status = E_DB_INFO;
		}
	    }
	}
	
	if (status == E_DB_OK)
	{
	    result_dv->db_length = work->adw_shared.shd_o_used +
		    work->adw_fip.fip_null_bytes;
	    
	    if (work->adw_fip.fip_null_bytes)
	    {
		/*
		**	Then the datatype was nullable.  Copy the NULL byte
		**	from the coupon.
		*/
		
		if (ADI_ISNULL_MACRO(coupon_dv))
		{
		    ADF_SETNULL_MACRO(result_dv);
		}
		else
		{
		    ADF_CLRNULL_MACRO(result_dv);
		}
	    }
	    adf_scb->adf_errcb.ad_errcode = E_DB_OK;
	}
    }
    else
    {
	/*
	**  In this case, we are at the end of data, but the "closing
	**	remarks" (no more strings (if gca) and null bytes) doesn't
	**	fit in the buffer.
	**
	**  We mark this fact by setting the state to ADW_F_DONE_NEED_NULL.
	*/
	result_dv->db_length = work->adw_shared.shd_o_used;
	work->adw_fip.fip_state = ADW_F_DONE_NEED_NULL;

	adf_scb->adf_errcb.ad_errcode  = E_AD0002_INCOMPLETE;
	status = E_DB_INFO;
    }

    return(status);
}
Exemplo n.º 3
0
/*{
** Name: adu_rdm1_setup	- Setup for Redeem an ADF_COUPON
**
** Description:
**      This routine performs the initialization for the redeeming of
**      a coupon.  This amount primarily to initializing the
**      ADP_LO_WKSP function instance private and shared (adw_fip &
**      adw_shared, respectively).  This routine also moves the
**      appropriate peripheral header into the output area.
**
**      Since this routine moves the peripheral header to the output
**      area, in the case where the original call to this routine has
**      insufficient space for the output header, this routine may be
**      called more than once.  We note this since it is "unusual" for
**      the initialization routine to be called more than one time for
**      an object.  In the case where the original space is of
**      insufficent size, then this routine will return an indication
**      that the output area is full, and will move nothing into it.
**      Thus, this routine considers it a call-protocol error to be
**      called a second time with insufficient space.
**
** Inputs:
**      adf_scb                     The session's control block (ptr).
**      result_dv                   Pointer to DB_DATA_VALUE for
**                                      result.
**      coupon_dv                   Pointer to DB_DATA_VALUE
**                                      describing the input coupon to
**                                      be redeemed.
**      workspace_dv                Pointer to DB_DATA_VALUE
**                                      describing redeem's workspace.
**      continuation                Continuation indicator.  0
**                                      indicates the first call, else
**                                      not the first call.
**
** Outputs:
**      adf_scb->adf_error          Filled as appropriate.
**      *result_dv->db_data         Setup with beginning of peripheral
**                                      data type.
**      *workspace_dv->db_data      Initialized for ongoing redeem work.
**	Returns:
**	    DB_STATUS
**	Exceptions:
**	    None.
**
** Side Effects:
**	    None.
**
** History:
**      02-dec-1992 (fred)
**          Coded.  Created from adu_redeem prototype in support of
**          OME large objects.
**       8-Apr-1993 (fred)
**          Fixed bug in zero length large object handling.  For large
**          objects of zero length which are not nullable, the length
**          should not include the null-value-byte.
**      12-Oct-1993 (fred)
**          Removed call to ADP_INFORMATION -- subsumed by
**          adi_per_under(). 
**      10-sep-1998 (schte01)
**          Modified I4ASSIGN for axp_osf to pass the value, not the address
**          of the value, to be assigned. This worked under the -oldc
**          compiler option and got compile errors under -newc.
**	28-jul-1999 (thaju02)
**	    If the coupon stipulates that the data is not null, then
**	    the minimum result buffer length must be large enough to
**	    hold one byte of data along with all necessary info
**	    (ADP_HDR_SIZE + nextsegmarker(i4) + 2byteseglenindicator
**	    + 1byteofdata). Given a buffer with only 18 bytes of space
**	    available, 12 bytes are filled with peripheral header info
**	    in adu_rdm1_setup and 4 bytes are filled with the next
**	    segment marker in adu_redeem. In adc_lvch_xform, the 2 
**	    byte segment length indicator is initially set to zero 
**	    in the result buffer. If there is no space left in the 
**	    result buffer for segment data, we flush the buffer. In 
**	    the front end, upon receiving this result buffer, the 
**	    next segment marker indicates that there is data following, 
**	    yet the length is zero; terminal monitor infinitely loops. 
**	    (b98104)
**      12-aug-99 (stial01)
**          adu_rdm1_setup() 'blob_work' arg to adi_per_under should be  
**          NULL before redeem.
**      24-may-2000 (stial01)
**          adu_rdm1_setup() clear null indicator if not null (B101656)
**
[@history_template@]...
*/
DB_STATUS static
adu_rdm1_setup(ADF_CB             *adf_scb,
	       DB_DATA_VALUE      *result_dv,
	       DB_DATA_VALUE      *coupon_dv,
	       ADP_LO_WKSP        *work,
	       i4                 for_gca)
{
    DB_STATUS	    	status;  
    ADP_PERIPHERAL      *p = (ADP_PERIPHERAL *) result_dv->db_data;
    DB_DT_ID            dtid =
	ADI_DT_MAP_MACRO(abs(result_dv->db_datatype));
    i4			min_size;
    bool		isnull = 0;

    if (coupon_dv->db_datatype < 0)
	work->adw_fip.fip_null_bytes = 1;
    else
	work->adw_fip.fip_null_bytes = 0;

    if (ult_check_macro(&Adf_globs->Adf_trvect, ADF_011_RDM_TO_V_STYLE,
			&dummy1, &dummy2))
    {
	work->adw_fip.fip_test_mode = 1;
	work->adw_fip.fip_test_length = ADP_TST_VLENGTH +
	                                   work->adw_fip.fip_null_bytes;
	work->adw_fip.fip_test_sent = 0;
    }
    else
    {
	work->adw_fip.fip_test_mode = 0;
    }

    work->adw_shared.shd_exp_action = ADW_START;
    work->adw_fip.fip_done = FALSE;

    /*
    ** Fool the main routine into getting us an input segment.  Make
    ** look like the input segement is all used up.
    */
    
    work->adw_shared.shd_type = coupon_dv->db_datatype;
    work->adw_shared.shd_i_area = (char *) 0;
    work->adw_shared.shd_i_used = work->adw_shared.shd_i_length = 0;

    work->adw_shared.shd_o_used = ADP_HDR_SIZE;
    work->adw_shared.shd_o_length = result_dv->db_length;
    work->adw_shared.shd_o_area = (char *) result_dv->db_data;

    if (work->adw_shared.shd_o_length > MAXI2)
    {
	TRdisplay("adu_rdm1_setup shd_o_length %d MAX %d\n",
		work->adw_shared.shd_o_length, MAXI2);
	return(adu_error(adf_scb, E_AD9999_INTERNAL_ERROR, 0));
    }
    work->adw_shared.shd_l0_check = work->adw_shared.shd_l1_check = 0;

    work->adw_fip.fip_pop_cb.pop_continuation = ADP_C_BEGIN_MASK;
    work->adw_fip.fip_pop_cb.pop_user_arg = (PTR) 0;
    
    work->adw_fip.fip_pop_cb.pop_type = (ADP_POP_TYPE);
    work->adw_fip.fip_pop_cb.pop_length = sizeof(ADP_POP_CB);
    work->adw_fip.fip_pop_cb.pop_ascii_id = ADP_POP_ASCII_ID;
    work->adw_fip.fip_pop_cb.pop_temporary = ADP_POP_PERMANENT;
    work->adw_fip.fip_pop_cb.pop_coupon = coupon_dv;
    work->adw_fip.fip_pop_cb.pop_segment = &work->adw_fip.fip_seg_dv;
    work->adw_fip.fip_pop_cb.pop_underdv = &work->adw_fip.fip_under_dv;
    status = adi_per_under(adf_scb,
			   result_dv->db_datatype,
			   &work->adw_fip.fip_under_dv);

    if (status)
    {
	return(adu_error(adf_scb, E_AD7000_ADP_BAD_INFO, 0));
    }

    STRUCT_ASSIGN_MACRO(work->adw_fip.fip_under_dv,
			work->adw_fip.fip_seg_dv);
    work->adw_fip.fip_seg_dv.db_data = (char *) ((char *) work +
						 sizeof(ADP_LO_WKSP));

    if (ADI_ISNULL_MACRO(coupon_dv) ||
       ((((ADP_PERIPHERAL *)coupon_dv->db_data)->per_length0 == 0)
       && (((ADP_PERIPHERAL *) coupon_dv->db_data)->per_length1 == 0))) 
	isnull = 1;

    if (isnull)
	/* hdr + segment indicator + sizeof(null byte) */
        min_size = ADP_HDR_SIZE + sizeof(i4) + work->adw_fip.fip_null_bytes; 
    else	
	/* hdr + segment indicator + segment length + segment single byte */
        min_size = ADP_HDR_SIZE + sizeof(i4) + sizeof(i2) + sizeof(char); 

    if (result_dv->db_length >= min_size)
    {
	if (for_gca)
	    work->adw_shared.shd_out_tag = ADP_P_GCA;
	else
	    work->adw_shared.shd_out_tag = ADP_P_DATA;
	
	I4ASSIGN_MACRO(work->adw_shared.shd_out_tag, p->per_tag);
	
	work->adw_shared.shd_out_segmented =
	    (work->adw_shared.shd_out_tag != ADP_P_DATA);

	I4ASSIGN_MACRO( ((ADP_PERIPHERAL *)
			 coupon_dv->db_data)->per_tag,
		       work->adw_shared.shd_inp_tag);
	work->adw_shared.shd_inp_segmented =
	    (work->adw_shared.shd_inp_tag != ADP_P_DATA);

	I4ASSIGN_MACRO( ((ADP_PERIPHERAL *)
			 coupon_dv->db_data)->per_length0,
		       p->per_length0);
	I4ASSIGN_MACRO(p->per_length0, work->adw_fip.fip_l0_value);
	I4ASSIGN_MACRO(((ADP_PERIPHERAL *)
			coupon_dv->db_data)->per_length1,
		       p->per_length1);
	I4ASSIGN_MACRO(p->per_length1, work->adw_fip.fip_l1_value);
	work->adw_fip.fip_state = ADW_F_RUNNING;
    }
    else if (work->adw_fip.fip_state != ADW_F_STARTING)
    {
	work->adw_fip.fip_state = ADW_F_STARTING;
	result_dv->db_length = 0;
	adf_scb->adf_errcb.ad_errcode = E_AD0002_INCOMPLETE;
	return(E_DB_INFO);
    }
    else
    {
	return(adu_error(adf_scb, E_AD9999_INTERNAL_ERROR, 0));
    }

    if (isnull)
    {
	if (work->adw_fip.fip_test_mode)
	{
	    ((DB_TEXT_STRING *) p)->db_t_count = (i2) 0;

	    if (result_dv->db_length >=
		    (work->adw_fip.fip_test_length -
		              work->adw_fip.fip_test_sent))

	    {
		
		result_dv->db_length = work->adw_fip.fip_test_length -
		     work->adw_fip.fip_test_sent;
		work->adw_fip.fip_test_sent = work->adw_fip.fip_test_length;
	    }
	    else
	    {
		work->adw_fip.fip_state = ADW_F_DONE_NEED_NULL;
		work->adw_fip.fip_test_sent += result_dv->db_length;
		adf_scb->adf_errcb.ad_errcode = E_AD0002_INCOMPLETE;
		return(E_DB_INFO);
	    }
	}
	else
	{
	    i4	    zero = 0;

	    /*
	    **  Insert GCA mark that says there is no segment.
	    */
	
#if defined(axp_osf) || defined(ris_u64) || defined(LP64) || \
    defined(axp_lnx)
	    /*
	    **	We want to init the GCA field after the header, but
	    **	on axp_osf this is not the same as the start of the
	    **	coupon, because 8-byte alignment causes a slack 4-byte
	    **	integer to be between the header and the coupon.  See
	    **	adu_redeem above for a different way this field is set
	    **	to 1 when we have real data (not null).  The addressing
	    **	of this field should really be standardized in such a
	    **	way that contiguous layout of 4-byte aligned fields is
	    **	not assumed.
	    */
            I4ASSIGN_MACRO(zero,*((char *)p + ADP_HDR_SIZE)); 
#endif
	    I4ASSIGN_MACRO(zero, p->per_value);
	    
	    result_dv->db_length = ADP_NULL_PERIPH_SIZE;
	    if (work->adw_shared.shd_type > 0)
		result_dv->db_length -= 1;
        }
	if (ADI_ISNULL_MACRO(coupon_dv))
	    ADF_SETNULL_MACRO(result_dv);
	else
	    ADF_CLRNULL_MACRO(result_dv);
	adf_scb->adf_errcb.ad_errcode = E_DB_OK;
	work->adw_fip.fip_done = TRUE;
	return(E_DB_OK);
    }

    if (work->adw_fip.fip_test_mode)
    {
	i4	    	segment_count;
	i4	    	length1;
	i2		count;
	
	I4ASSIGN_MACRO(p->per_length1, length1);
	
	I4ASSIGN_MACRO(p->per_length0, segment_count);
	
	if (!segment_count)
	    segment_count = ADP_TST_SEG_CNT;
	
	count = min(	ADP_TST_VLENGTH,
		    (i2) (length1
			  + (segment_count *
			     (sizeof(i4) + sizeof(i2)))
			  + sizeof(i4) /* no more segments */
			  + work->adw_shared.shd_o_used)
		    ) - sizeof(i2);
	I2ASSIGN_MACRO(count, ((DB_TEXT_STRING *) p)->db_t_count);
    }
    return(E_DB_OK);
}