home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c160 / 1.ddi / SOURCE / I4REINDE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-03  |  19.7 KB  |  775 lines

  1.  
  2. /*  i4reindex.c   (c)Copyright Sequiter Software Inc., 1987-1990.  All rights reserved.
  3.  
  4.     Reindexes an Index File
  5. */
  6.  
  7. #include "p4misc.h"
  8. #include "d4all.h"
  9. #include "u4error.h"
  10.  
  11. #include <string.h>
  12. #ifndef UNIX
  13. #include <io.h>
  14. #endif
  15.  
  16. #ifdef WINDOWS_L
  17. #define WINDOWS
  18. #endif
  19. #ifdef WINDOWS_G
  20. #define WINDOWS
  21. #endif
  22.  
  23. static     int   add_key(KEY H_PTR) ;
  24. static   int   reindex(int) ;
  25. static   int   build_sort(int) ;
  26. static   int   index_info( int ) ;
  27. static   int   reindex_w_clean(int) ;
  28. static   int   calc_blocks_needed(void) ; 
  29. static   int   memory_init(unsigned, int) ;
  30. static   int   build_index(void) ;
  31. extern     INDEX    *v4index ;
  32. extern   BASE   *v4base ;
  33. extern     int     v4cur_base ;
  34. extern     int     v4last_base ;
  35. extern   long    v4sort_memory_max ;
  36. extern   int     v4lock_wait ;
  37. extern   int     v4type ;
  38.  
  39. static   char H_PTR  buffer_ptr =  0 ;
  40. static   unsigned buffer_len = 0 ;
  41. static   int      sort_len   = 0 ;
  42.  
  43. static   long     rec_count ;
  44.  
  45. #ifdef CLIPPER
  46. static   KEY      key_value ;
  47. #endif
  48.  
  49. static   BLOCK    H_PTR block_start ;
  50. static     INDEX     *index_ptr  ;
  51. static     int      block_on   ;
  52. static     int      block_max  ;
  53. static     long      file_block ;
  54. static     int      group_len  ;
  55. static     int      key_len    ;
  56. static     int      keys_max   ;
  57.  
  58. #define  MAX_SPOOL  300
  59.  
  60. static int  build_sort( int index_ref )
  61. {
  62.    long      on_rec ;
  63.    int         rc ;
  64.    char     *eval_ptr ;
  65.    BASE     *base_ptr ;
  66.  
  67.    base_ptr =  v4base +  v4cur_base ;
  68.  
  69.    rc = u4read_init( base_ptr->file_hand, buffer_ptr, buffer_len, (long) base_ptr->header_len ) ;
  70.    if ( rc < 0 )  return -1 ;
  71.  
  72.    for ( on_rec = 1; on_rec <= rec_count; on_rec++)
  73.    {
  74.       base_ptr->rec_num =  on_rec ;
  75.       if ( u4read( base_ptr->buffer, base_ptr->buffer_len ) != 0 ) return -1 ;
  76.  
  77.       rc = i4filter_check(index_ref) ;
  78.       if ( rc < 0 )  return -1 ;
  79.       if ( rc )  continue ;
  80.  
  81.       eval_ptr =  e4string( index_ptr->compile ) ;
  82.       if ( eval_ptr == (char *) 0)  return( -1) ;
  83.  
  84.       #ifndef CLIPPER
  85.          if ( v4type == (int) 'D' )
  86.             if ( *eval_ptr == ' ' )
  87.                *eval_ptr =  0xFF ;
  88.       #endif
  89.  
  90.       u4sort_add( eval_ptr, (char *) &on_rec ) ;
  91.    }
  92.  
  93.    return( 0) ;
  94. }
  95.  
  96.  
  97. #ifdef CLIPPER
  98. static int  build_index()
  99. {
  100.    BLOCK  H_PTR  block_ptr ;
  101.    KEY      H_PTR  key_ptr;
  102.    char   H_PTR  from_ptr ;
  103.    char    last_ptr[MAX_KEY_SIZE+2] ;
  104.    int       first_time ;
  105.  
  106.    if ( u4write_init( index_ptr->file_hand, buffer_ptr, buffer_len, (long) BLOCK_SIZE ) < 0 )  return -1 ;
  107.  
  108.    first_time =  1 ;
  109.  
  110.    block_on =  block_max =  -1 ;
  111.    block_ptr=  block_start +    block_on ;
  112.  
  113.    file_block =  BLOCK_SIZE ;
  114.  
  115.    while( 1)
  116.    {
  117.       /* Retrieves Keys in Sorted Order */
  118.       if ( u4sort_get( &from_ptr ) < 0 )  return -1 ;
  119.  
  120.       if ( index_ptr->unique )
  121.       {
  122.      if ( ! first_time )
  123.      {
  124.         while ( from_ptr != (char H_PTR) 0 )
  125.         {
  126.            extern int  v4unique_error ;
  127.            if ( u4huge_cmp( (unsigned char H_PTR) from_ptr, 
  128.                                 (unsigned char H_PTR) last_ptr, 
  129.                                 (unsigned) sort_len) != 0)  break ;
  130.  
  131.            /* Filter out any repeat keys. */
  132.            if ( v4unique_error )
  133.            {
  134.           u4error( E_UNIQUE, index_ptr->name, (char *) 0) ;
  135.           return( -1) ;
  136.            }
  137.                if ( u4sort_get( &from_ptr ) < 0 )  return -1 ;
  138.         }
  139.      }
  140.      if ( from_ptr != (char H_PTR) 0 )
  141.         u4huge_cpy( (char H_PTR) last_ptr, from_ptr, (long) sort_len ) ;
  142.  
  143.      first_time = 0 ;
  144.       }
  145.  
  146.       if ( from_ptr == (char H_PTR) 0 )
  147.       {
  148.      /* Observe
  149.         1.    Full Blocks will have been written if the entry which
  150.         points the the block has been entered.
  151.         2.    Either the bottom block may be written and give a starting
  152.         block pointer or the last block written is a good starting
  153.         block pointer.
  154.         3.    There may be one stranded entry which may be added later.
  155.         4.    file_block is the next address to be written
  156.      */
  157.  
  158.      /* The key_value is not yet active */
  159.      memset( &key_value, 0, sizeof(key_value) ) ;
  160.  
  161.      /* Check for no Entries */
  162.      if ( block_max < 0 )
  163.      {
  164.         add_key( &key_value ) ;
  165.         block_start[0].num_keys =  0 ;
  166.  
  167.         if( u4write( (char H_PTR) &block_start->num_keys, BLOCK_SIZE) != 0 )
  168.            return( -1) ;
  169.  
  170.         file_block +=  BLOCK_SIZE ;
  171.      }
  172.      else
  173.      {
  174.         if ( block_start[0].num_keys == 0 )
  175.         {
  176.            while ( block_start[++block_on].num_keys == 0 ) ;
  177.  
  178.            block_ptr =  block_start + block_on ;
  179.            u4huge_cpy( (char H_PTR) &key_value, (char H_PTR) &block_ptr->num_keys +
  180.             block_ptr->pointers[block_ptr->num_keys-1], (long) group_len) ;
  181.            block_ptr->num_keys-- ;
  182.            if ( block_ptr->num_keys != 0 )    block_on-- ;
  183.         }
  184.      }
  185.  
  186.      while( block_on < block_max )
  187.      {
  188.         block_on++ ;
  189.         block_ptr =  block_start+ block_on ;
  190.  
  191.         if ( block_ptr->num_keys > 0 )
  192.         {
  193.            key_ptr =  (KEY H_PTR) ((char H_PTR) &block_ptr->num_keys+
  194.                   block_ptr->pointers[block_ptr->num_keys]) ;
  195.            if ( block_on > 0 )
  196.           key_ptr->file_block =  file_block - BLOCK_SIZE ;
  197.  
  198.            if (u4write((char H_PTR) &block_ptr->num_keys, BLOCK_SIZE) != 0)
  199.           return( -1) ;
  200.  
  201.            file_block +=  BLOCK_SIZE ;
  202.         }
  203.      }
  204.      index_ptr->root =  file_block -  BLOCK_SIZE ;
  205.      index_ptr->virtual_eof =  index_ptr->eof  =  0L ;
  206.  
  207.      return( 0 ) ;
  208.       }
  209.  
  210.       u4huge_cpy( (char H_PTR) key_value.value, from_ptr, (long) key_len ) ;
  211.       u4huge_cpy( (char H_PTR) &key_value.rec_num, from_ptr+sort_len, (long) sizeof(long) ) ;
  212.       key_value.file_block =  0 ;
  213.       if( add_key( &key_value ) < 0 )  return -1 ;
  214.    }
  215. }
  216.  
  217. #else
  218.  
  219. static int  build_index()
  220. {
  221.    BLOCK H_PTR block_ptr ;
  222.    KEY     H_PTR key_ptr   ;
  223.    char  H_PTR from_ptr ;
  224.    char    last_ptr[MAX_KEY_SIZE+2] ;
  225.    int       i, first_time ;
  226.  
  227.    if ( u4write_init( index_ptr->file_hand, buffer_ptr, buffer_len, (long) BLOCK_SIZE ) < 0 )  return -1 ;
  228.  
  229.    first_time =  1 ;
  230.  
  231.    block_on =  block_max =  0 ;
  232.    block_ptr=  block_start + block_on ;
  233.    u4huge_set( ((char H_PTR)block_ptr)+2*sizeof(int), 0,
  234.        (long) (sizeof(BLOCK)-2*sizeof(int)) ) ;
  235.  
  236.    block_ptr->num_keys =  keys_max ;
  237.    file_block =  1 ;
  238.  
  239.    while( 1)
  240.    {
  241.       key_ptr =  (KEY H_PTR) ((char H_PTR)&block_ptr->key - group_len) ;
  242.       for( i=0; i< keys_max; i++)
  243.       {
  244.      /* Retrieves Keys in Sorted Order */
  245.          if ( u4sort_get( &from_ptr ) < 0 )  return -1 ;
  246.    
  247.          if ( from_ptr != (char H_PTR) 0 && v4type == (int) 'D' )
  248.         if ( *from_ptr == (char) 0xFF )
  249.            *from_ptr =  ' ' ;
  250.  
  251.      if ( index_ptr->unique )
  252.      {
  253.         if ( ! first_time )
  254.         {
  255.            while ( from_ptr != (char H_PTR) 0 )
  256.            {
  257.           extern int  v4unique_error ;
  258.  
  259.           if ( u4huge_cmp((unsigned char H_PTR) from_ptr, 
  260.                                   (unsigned char H_PTR) last_ptr, 
  261.                                   (unsigned) sort_len) != 0 )  break ;
  262.  
  263.           /* Filter out any repeat keys. */
  264.           if ( v4unique_error )
  265.           {
  266.              u4error( E_UNIQUE, index_ptr->name, (char *) 0) ;
  267.              return( -1) ;
  268.           }
  269.                   if ( u4sort_get( &from_ptr ) < 0 )  return -1 ;
  270.            }
  271.         }
  272.         if ( from_ptr != (char H_PTR) 0 )
  273.            u4huge_cpy( (char H_PTR) last_ptr, from_ptr, (long) sort_len ) ;
  274.         first_time = 0 ;
  275.      }
  276.  
  277.      if ( from_ptr == (char H_PTR) 0  && (i > 0 || block_max == block_on))
  278.      {
  279.         block_ptr->num_keys =  i ;
  280.         key_ptr   =  (KEY H_PTR) ((char H_PTR)&block_ptr->key+
  281.              i * group_len) ;
  282.         break ;
  283.      }
  284.  
  285.      if ( from_ptr == (char H_PTR) 0)
  286.      {
  287.         while( ++block_on)
  288.         {
  289.            block_ptr =  block_start+ block_on ;
  290.  
  291.            key_ptr     =  (KEY H_PTR) ((char H_PTR)&block_ptr->key+
  292.                 block_ptr->num_keys * group_len) ;
  293.  
  294.            if ( block_ptr->num_keys > 0)
  295.            {
  296.           if( u4write((char H_PTR)&block_ptr->num_keys, BLOCK_SIZE) != 0)
  297.              return( -1) ;
  298.           key_ptr->file_block =  file_block++ ;
  299.            }
  300.            if ( block_on >= block_max)
  301.            {
  302.           index_ptr->root =  file_block -1 ;
  303.           index_ptr->eof  =  file_block ;
  304.           return( 0 ) ;
  305.            }
  306.            if ( block_ptr->num_keys >= 0 )
  307.           add_key( key_ptr ) ;
  308.         }
  309.      }
  310.  
  311.      key_ptr =  (KEY H_PTR) ((char H_PTR)key_ptr + group_len) ;
  312.          switch( index_ptr->i_type )
  313.          {
  314.             case 'C':
  315.            u4huge_cpy( (char H_PTR) key_ptr->value, from_ptr, (long) key_len )  ;
  316.                break ;
  317.  
  318.         case 'D':
  319.         {
  320.            char    dbf_date[8] ;
  321.            double  d_index ;
  322.            u4huge_cpy( (char H_PTR) dbf_date, from_ptr, (long) sizeof(dbf_date) ) ;
  323.            c4dt_julian( dbf_date, &d_index ) ;
  324.            u4huge_cpy( (char H_PTR) key_ptr->value, (char H_PTR) &d_index, (long) sizeof(double) ) ;
  325.            break ;
  326.         }
  327.  
  328.             case 'N':
  329.         {
  330.            double d ;
  331.            char  temp[MAX_KEY_SIZE+2] ;
  332.            int   i ;
  333.  
  334.            u4huge_cpy( (char H_PTR) temp, from_ptr, (long) sort_len ) ;
  335.            temp[sort_len] = '\000' ;
  336.  
  337.            if ( temp[0] < 0x30 )
  338.            {
  339.               for ( i=0; i< sort_len; i++ )
  340.              temp[i] = (char) 0x5c - temp[i] ;
  341.  
  342.           d = -c4atod( temp, sort_len ) ;
  343.            }
  344.            else
  345.           d =  c4atod( temp, sort_len ) ;
  346.  
  347.            u4huge_cpy( (char H_PTR) key_ptr->value, &d, (long) sizeof(d) ) ;
  348.            break ;
  349.             }
  350.          }
  351.  
  352.      u4huge_cpy( (char H_PTR) &key_ptr->rec_num, from_ptr+sort_len, (long) sizeof(long)) ;
  353.       }
  354.       if( u4write((char H_PTR)&block_ptr->num_keys, BLOCK_SIZE) != 0)
  355.      return( -1 ) ;
  356.  
  357.       key_ptr->file_block = file_block++ ;
  358.       if( add_key(key_ptr ) < 0) return( -1 ) ;
  359.       key_ptr->file_block = 0 ;
  360.    }
  361. }
  362.  
  363. #endif
  364.  
  365.  
  366. #ifdef CLIPPER
  367.  
  368. static int add_key( KEY H_PTR key_ptr )
  369. {
  370.    BLOCK H_PTR block_ptr ;
  371.    int      i, i_block ;
  372.  
  373.    block_on ++ ;
  374.    block_ptr =    block_start+ block_on ;
  375.  
  376.    if ( block_on > block_max )
  377.    {
  378.       /* Initialization for this block level */
  379.       u4huge_set( ((char H_PTR)block_ptr)+2*sizeof(int), 0,
  380.           (long) (sizeof(BLOCK)-2*sizeof(int)) ) ;
  381.  
  382.       i_block =  keys_max*2 + 4 ;
  383.       for (i=0; i<= keys_max; i++, i_block+= group_len)
  384.      block_ptr->pointers[i] =  i_block ;
  385.  
  386.       block_ptr->num_keys =  0 ;
  387.       block_max       =  block_on ;
  388.    }
  389.  
  390.    if ( block_ptr->num_keys >= keys_max )
  391.    {
  392.       u4huge_cpy( (char H_PTR)&block_ptr->num_keys +
  393.             block_ptr->pointers[block_ptr->num_keys],
  394.            (char H_PTR) &key_ptr->file_block, 4L) ;
  395.  
  396.       if( u4write((char H_PTR) &block_ptr->num_keys, BLOCK_SIZE) != 0)
  397.      return( -1) ;
  398.  
  399.       key_ptr->file_block =  file_block ;
  400.       file_block +=  BLOCK_SIZE ;
  401.       if( add_key( key_ptr) < 0)  return( -1) ;
  402.  
  403.       block_ptr->num_keys =  0 ;
  404.    }
  405.    else
  406.    {
  407.       u4huge_cpy( (char H_PTR)&block_ptr->num_keys +
  408.             block_ptr->pointers[block_ptr->num_keys],
  409.            (char H_PTR) key_ptr, (long) group_len) ;
  410.       block_ptr->num_keys++ ;
  411.    }
  412.  
  413.    block_on -- ;
  414.    return(0) ;
  415. }
  416.  
  417. #else
  418.  
  419. static int add_key( KEY H_PTR key_ptr )
  420. {
  421.    BLOCK H_PTR block_ptr ;
  422.  
  423.    block_on ++ ;
  424.    block_ptr =    block_start+ block_on ;
  425.  
  426.    if ( block_on > block_max )
  427.    {
  428.       /* Initialization for this block level */
  429.       u4huge_set( ((char H_PTR)block_ptr)+2*sizeof(int), 0,
  430.           (long) (sizeof(BLOCK)-2*sizeof(int)) ) ;
  431.       block_ptr->num_keys =  -1 ;
  432.       block_max =  block_on ;
  433.    }
  434.  
  435.    key_ptr->rec_num =  0 ;
  436.  
  437.    if ( ++block_ptr->num_keys >= keys_max )
  438.    {
  439.       u4huge_cpy( (char H_PTR)&block_ptr->key + block_ptr->num_keys*group_len,
  440.            (char H_PTR) key_ptr, (long) sizeof(long)) ;
  441.  
  442.       if( u4write((char H_PTR) &block_ptr->num_keys, BLOCK_SIZE) != 0 )
  443.      return( -1) ;
  444.       key_ptr->file_block =  file_block++ ;
  445.       if( add_key( key_ptr) < 0)  return( -1) ;
  446.  
  447.       block_ptr->num_keys = -1 ;
  448.    }
  449.    else
  450.       u4huge_cpy( (char H_PTR)&block_ptr->key + block_ptr->num_keys*group_len,
  451.            (char H_PTR) key_ptr, (long) group_len) ;
  452.  
  453.    block_on -- ;
  454.    return(0) ;
  455. }
  456.  
  457. #endif
  458.  
  459. #ifdef CLIPPER
  460.    int  v4clipper_len = 17 ;
  461.    int  v4clipper_dec =  2 ;
  462. #endif
  463.  
  464. static int  index_info( int index_ref )
  465. {
  466.    INDEX  *index_ptr ;
  467.    char   *eval_ptr ;
  468.  
  469.    index_ptr =    v4index +  index_ref ;
  470.    memset( d4ptr()->buffer, (int) ' ', (size_t) d4ptr()->buffer_len) ;
  471.  
  472.    eval_ptr =  (char *) e4vary( index_ptr->compile ) ;
  473.    if ( eval_ptr == (char *) 0)  return( -1) ;
  474.  
  475.    index_ptr->i_type =    e4type() ;
  476.    if ( index_ptr->i_type == 'n' )  index_ptr->i_type = 'N' ;
  477.    if ( index_ptr->i_type == 'd' )  index_ptr->i_type = 'D' ;
  478.  
  479.    key_len =  e4length() ;
  480.  
  481.    #ifdef CLIPPER
  482.       if ( index_ptr->i_type == 'D' )
  483.          key_len =  8 ;  /* CCYYMMDD */
  484.  
  485.       /* Clipper Numeric Possibilities
  486.          Field 
  487.             - e4vary should return the value as 'n'.
  488.             - The fields number of decimals should be used.
  489.  
  490.          Calculation 
  491.             - e4vary should return the value as 'N'.
  492.             - Width of 'v4clipper_len' and 'v4clipper_dec' decimals should be used.
  493.       */
  494.  
  495.       if ( index_ptr->i_type == 'N' )
  496.       {
  497.      long  f_ref ;
  498.  
  499.          index_ptr->key_dec = v4clipper_dec ;
  500.          key_len =  v4clipper_len ;
  501.  
  502.          if ( e4type() == 'n' )
  503.          {
  504.             /* Its a field */
  505.         f_ref =  f4ref( index_ptr->expression ) ;
  506.             if ( f_ref >= 0 )
  507.             {
  508.                key_len =  f4width(f_ref ) ;
  509.                index_ptr->key_dec =  f4decimals(f_ref) ;
  510.             }
  511.          }
  512.    }
  513.    #else
  514.       if ( index_ptr->i_type == 'D' || index_ptr->i_type == 'N' )
  515.       {
  516.          key_len =  sizeof(double) ;
  517.      index_ptr->int_or_date =  1 ;
  518.       }
  519.       else
  520.      index_ptr->int_or_date =  0 ;
  521.    #endif
  522.  
  523.    if ( key_len > MAX_KEY_SIZE || key_len <= 0 )
  524.    {
  525.        u4error( E_KEY_LEN, index_ptr->name, "Expression:", index_ptr->expression, (char *) 0) ;
  526.        return( -1) ;
  527.    }
  528.  
  529.    index_ptr->key_len =  key_len ;
  530.    index_ptr->version =  index_ptr->old_version + 1 ;
  531.  
  532.    #ifdef CLIPPER
  533.       index_ptr->sign   =  6 ;
  534.       index_ptr->group_len =  group_len =  key_len+8 ;
  535.       index_ptr->keys_half =  (1020/ (group_len+2) - 1)/ 2;
  536.       index_ptr->keys_max  =  keys_max    =  index_ptr->keys_half *2 ;
  537.       if ( keys_max < 2 )
  538.       {
  539.      u4error( E_BAD_NDX, index_ptr->name, (char *) 0 ) ;
  540.      return( -1 ) ;
  541.       }
  542.    #else
  543.       #ifdef PORTABLE
  544.          group_len = key_len+3*sizeof(long) - key_len%sizeof(long) ;
  545.          if ( key_len%sizeof(long) == 0 )  group_len -=  sizeof(long) ;
  546.          index_ptr->group_len =  group_len ;
  547.       #else
  548.          index_ptr->group_len =  group_len =  key_len+8 + key_len%2 ;
  549.       #endif
  550.       index_ptr->keys_max  =  keys_max    =  504/ index_ptr->group_len ;
  551.       if ( keys_max < 4 )
  552.       {
  553.      u4error( E_BAD_NDX, index_ptr->name, (char *) 0 ) ;
  554.      return( -1 ) ;
  555.       }
  556.    #endif
  557.  
  558.    return 0 ;
  559. }
  560.  
  561. static int  write_header(void) ;
  562. static int  write_header()
  563. {
  564.    char  buffer[BLOCK_SIZE] ;
  565.    int   header_len ;
  566.  
  567.    memset( buffer, 0, (size_t) BLOCK_SIZE ) ;
  568.  
  569.    lseek( index_ptr->file_hand, 0L, 0) ;
  570.    #ifdef CLIPPER
  571.       /* These 'chsize' calls can be removed if the 'chsize' is not available.
  572.      It just reduces the size of the index file if it is smaller. */
  573.       #ifndef NO_CHSIZE
  574.      chsize(index_ptr->file_hand, index_ptr->root+ (long) BLOCK_SIZE ) ;
  575.       #endif
  576.       header_len =  (char *)(v4index+1) - (char *) &v4index->sign ;
  577.       memcpy( buffer, &index_ptr->sign, (size_t) header_len ) ;
  578.    #else
  579.       #ifndef NO_CHSIZE
  580.      chsize(index_ptr->file_hand, index_ptr->eof*BLOCK_SIZE) ;
  581.       #endif
  582.       header_len =  (char *)(v4index+1) - (char *) &v4index->root  ;
  583.       memcpy( (char *) buffer, (char *) &index_ptr->root, (size_t) header_len ) ;
  584.    #endif
  585.    if ( write( index_ptr->file_hand, (char *) buffer, BLOCK_SIZE) != BLOCK_SIZE )
  586.    {
  587.       u4error( E_WRITE, index_ptr->name, (char *) 0 ) ;
  588.       return( -1 ) ;
  589.    }
  590.  
  591.    return 0 ;
  592. }
  593.  
  594.  
  595. static int  calc_blocks_needed()
  596. {
  597.    int count ;
  598.    long  num_recs ;
  599.  
  600.    num_recs =  d4reccount() ;
  601.  
  602.    for ( count = 1;; count++ )
  603.    {
  604.       num_recs /=  index_ptr->keys_max ;
  605.       if ( num_recs == 0L )  return  count+1 ;
  606.    }
  607. }
  608.  
  609.  
  610. /* Returns the number of spools used; -1 if not enough memory */
  611.  
  612. static int  memory_init( unsigned buffer_size, int sort_len )
  613. {
  614.    buffer_len =  0 ;
  615.  
  616.    if ( (buffer_ptr = (char H_PTR) d4buf_alloc( (long) buffer_size,1)) == (char H_PTR) 0 )
  617.       return -1 ;
  618.  
  619.    buffer_len =  buffer_size ;
  620.  
  621.    return( u4sort_init( d4reccount(), sort_len, sizeof(long)) ) ;
  622. }
  623.  
  624.  
  625. static int reindex( int index_ref )
  626. {
  627.    int     rc ;
  628.  
  629.    index_ptr =    v4index + index_ref ;
  630.  
  631.    if ( index_ptr->compile != (char *) 0 )  h4free_memory( index_ptr->compile) ;
  632.    if ( e4parse( index_ptr->expression, &index_ptr->compile) < 0)  return(-1) ;
  633.  
  634.    if ( index_info(index_ref) < 0 )  return -1 ;
  635.    if ( e4string( index_ptr->compile ) == (char *) 0 )  return -1 ;
  636.  
  637.    sort_len =  e4length() ;
  638.    if ( sort_len > MAX_KEY_SIZE )  sort_len =  MAX_KEY_SIZE ;
  639.  
  640.    /* MEMORY ALLOCATION */
  641.  
  642.    /* Memory Buffer Operations. */
  643.    d4buf_avail_set() ;
  644.  
  645.    /* Determine the number of index file blocks necessary. */
  646.    if ( (block_start = (BLOCK H_PTR) d4buf_alloc((long) calc_blocks_needed(), sizeof(BLOCK))) == (BLOCK H_PTR) 0 )
  647.    {
  648.       u4error( E_SORT, i4name(index_ref), (char *) 0 ) ;
  649.       return -1 ;
  650.    }
  651.    d4buf_sub_set() ;  /* Minimum needed. Change sub-pool position. */
  652.  
  653.    if ( (rc = memory_init( 0xF800, sort_len)) != 0 )
  654.    {
  655.       if ( rc > 0 )
  656.          /* Memory Allocated by Sort using several buffers.  
  657.             Release and try again. */
  658.      u4sort_free() ;
  659.  
  660.       d4buf_avail_set() ;
  661.  
  662.       /* Reduce the number of spools by allocating less memory 
  663.          to read and write the database and index file. */
  664.       if ( memory_init( 0x2000, sort_len )  < 0 )
  665.       {
  666.          d4buf_avail_set() ;
  667.  
  668.          if ( memory_init( 0, sort_len )  < 0 )
  669.          {
  670.             u4error( E_SORT, index_ptr->name, (char *) 0 ) ;
  671.             return -1 ;
  672.          }
  673.       }
  674.    }
  675.  
  676.    /* MEMORY ALLOCATION - END */
  677.  
  678.    /* Sort the Information */
  679.    if ( build_sort(index_ref) < 0)
  680.       return( -1 ) ;
  681.  
  682.    /* Build the Index File */
  683.    rc =  build_index() ;
  684.    if ( rc < 0L)   return( -1) ;
  685.  
  686.    if ( u4write_flush() < 0 )  return -1 ;
  687.  
  688.    /* Write the Index File Control Information (Block 0) */
  689.    if ( write_header() < 0 )  return -1 ;
  690.  
  691.    #ifdef CLIPPER
  692.       if ( key_value.rec_num != 0 )
  693.       {
  694.      if ( i4add( index_ref, key_value.value, key_value.rec_num ) < 0 )
  695.         return -1 ;
  696.       }
  697.    #endif
  698.  
  699.    return( 0 ) ;
  700. }
  701.  
  702.  
  703. static int  reindex_w_clean( int index_ref )
  704. {
  705.    int  rc ;
  706.  
  707.    buffer_ptr =  (char H_PTR) 0 ;
  708.    buffer_len =  0 ;
  709.  
  710.    if ( reindex( index_ref ) < 0)
  711.       rc =  -1 ;
  712.    else
  713.       rc =   0 ;
  714.  
  715.    u4sort_free() ;
  716.    i4unlock( index_ref ) ;
  717.  
  718.    return rc ;
  719. }
  720.  
  721.  
  722. i4reindex( int index_ref )
  723. {
  724.    int      rc, index_on, old_base ;
  725.    H4BUF    buf_saved ;
  726.  
  727.    if ( index_ref >= 0)
  728.       old_base =  d4select( v4index[index_ref].base_ref) ;
  729.    else
  730.       old_base =  d4select(-1) ;
  731.  
  732.    #ifdef WINDOWS
  733.       if ( (rc = d4lock( v4lock_wait, 1)) < 0)  
  734.    #else
  735.       if ( (rc = d4lock_all( v4lock_wait, 1)) < 0)  
  736.    #endif
  737.    {
  738.       d4select( old_base) ;
  739.       return rc ;
  740.    }
  741.  
  742.    if ( d4flush( v4cur_base) < 0 )
  743.    {
  744.       d4select( old_base) ;
  745.       return -1 ;
  746.    }
  747.  
  748.    if ( d4buf_clear_lend(1) == -1 )
  749.    {
  750.       d4select( old_base) ;
  751.       return -1 ;
  752.    }
  753.  
  754.    d4buf_save_status( &buf_saved ) ;
  755.  
  756.    rec_count =  d4reccount() ;
  757.  
  758.    if ( index_ref >= 0 )
  759.       rc =  reindex_w_clean( index_ref ) ;
  760.    else
  761.       for ( rc = 0, index_on = d4ptr()->index_ref; rc == 0 && index_on >= 0;
  762.                                          index_on = v4index[index_on].prev )
  763.       {
  764.          rc =  reindex_w_clean(index_on) ;
  765.       }
  766.  
  767.    d4blank() ;
  768.    d4select(old_base) ;
  769.  
  770.    d4buf_restore_status( &buf_saved ) ;
  771.    d4buf_return() ;
  772.  
  773.    return( rc) ;
  774. }
  775.