Home | Previous Page | Next Page   Creating User-Defined Routines > Managing Memory > Managing Stack Space >

Increasing Stack Space

The DataBlade API provides the mi_call( ) function to dynamically manage stack space. This function performs the following tasks:

Use the mi_call( ) function to increase stack space for recursive UDRs.

Keep in mind that mi_call( ) does not know the size of the routine arguments. When mi_call( ) creates a new stack and copies an argument onto this new stack, the function uses the size of the MI_DATUM data type for the argument. If the data type of the routine argument is larger than MI_DATUM, mi_call( ) does not copy all the argument bytes.

For example, consider a UDR that includes an mi_double argument.

UNIX/Linux Only

On UNIX or Linux, an mi_double_precision argument takes the space of two long int values. Therefore, the mi_call( ) function pushes only half of the argument onto the new stack. Any arguments after the mi_double_precision might get garbled, and the last one might be truncated.

End of UNIX/Linux Only

When you design UDRs that require the use of mi_call( ), make sure you use the correct passing mechanism for the argument data type. Pass all data types larger than MI_DATUM by reference. Examples of large data types are floating-point types (such as mi_real and mi_double_precision) and data type structures.

The following example illustrates stack-space allocation with mi_call( ):

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mi.h"

mi_integer factorial(mi_integer value)
{
   mi_integer callstatus=0,
            retval=0;

   if ( value < 0 )
      return -1;
   else if ( value == 1 || value == 0 )
      return 1;
   else if ( value > 30 )
      mi_db_error_raise(NULL, MI_EXCEPTION,
   "factorial: input value too big for result.");

   callstatus = mi_call(&retval, factorial, 1, value-1);
   switch( callstatus )
      {
      case MI_TOOMANY:
         mi_db_error_raise(NULL, MI_EXCEPTION,
            "factorial: too many parameters.");

      case MI_CONTINUE:
         return (value * factorial(value-1));

      case MI_NOMEM:
         mi_db_error_raise(NULL, MI_EXCEPTION,
            "factorial: not enough memory");

      case MI_DONE:
         /* At the end of the factorial recursion, the
          * function still needs to calculate:
          *      value * factorial(value-1)
          */
         retval *= value;
         break;
      }

   return retval;
}

This code sample implements a factorial function. If the mi_call( ) function determines that there is sufficient stack space, the code recursively calls the handle_row( ) function to process the row value. The return value of the mi_call( ) function indicates whether mi_call( ) has allocated additional thread-stack memory, as follows.

mi_call( ) Return Value Description Action
MI_CONTINUE The thread stack currently has room for another invocation of factorial( ). The mi_call( ) function does not need to allocate a new thread stack.

The code fragment explicitly calls factorial( ) on the value-1 value.

MI_DONE The thread stack currently does not have room for another invocation of factorial( ). The mi_call( ) function allocates a new thread stack, copies the arguments onto this stack, and invokes the factorial( ) function on the value-1 value, returning its value in callstatus.

The code fragment does not need to explicitly call factorial( ) on the value-1 value. The mi_call( ) function did the work of invoking the routine; however, mi_call( ) completed only the following portion of the calculation:

factorial(value-1)

To complete the factorial, the function needs to complete the following calculation:

value * factorial(value-1)

The other mi_call( ) return values (MI_NOMEM and MI_TOOMANY) indicate error conditions. For these return values, the function uses the mi_db_error_raise( ) function to raise a database server exception and provide an error message.

The following CREATE FUNCTION registers the factorial( ) function:

CREATE FUNCTION factorial (INTEGER)
   RETURNS INTEGER
   EXTERNAL NAME
      "$INFORMIXDIR/extend/misc/fact_ius.bld"
   LANGUAGE C;

The following EXECUTE FUNCTION invokes the factorial( ) function:

EXECUTE FUNCTION factorial(5);
Home | [ Top of Page | Previous Page | Next Page | Contents | Index ]