home *** CD-ROM | disk | FTP | other *** search
-
- /* i4reindex.c (c)Copyright Sequiter Software Inc., 1987-1990. All rights reserved.
-
- Reindexes an Index File
- */
-
- #include "p4misc.h"
- #include "d4all.h"
- #include "u4error.h"
-
- #include <string.h>
- #ifndef UNIX
- #include <io.h>
- #endif
-
- #ifdef WINDOWS_L
- #define WINDOWS
- #endif
- #ifdef WINDOWS_G
- #define WINDOWS
- #endif
-
- static int add_key(KEY H_PTR) ;
- static int reindex(int) ;
- static int build_sort(int) ;
- static int index_info( int ) ;
- static int reindex_w_clean(int) ;
- static int calc_blocks_needed(void) ;
- static int memory_init(unsigned, int) ;
- static int build_index(void) ;
- extern INDEX *v4index ;
- extern BASE *v4base ;
- extern int v4cur_base ;
- extern int v4last_base ;
- extern long v4sort_memory_max ;
- extern int v4lock_wait ;
- extern int v4type ;
-
- static char H_PTR buffer_ptr = 0 ;
- static unsigned buffer_len = 0 ;
- static int sort_len = 0 ;
-
- static long rec_count ;
-
- #ifdef CLIPPER
- static KEY key_value ;
- #endif
-
- static BLOCK H_PTR block_start ;
- static INDEX *index_ptr ;
- static int block_on ;
- static int block_max ;
- static long file_block ;
- static int group_len ;
- static int key_len ;
- static int keys_max ;
-
- #define MAX_SPOOL 300
-
- static int build_sort( int index_ref )
- {
- long on_rec ;
- int rc ;
- char *eval_ptr ;
- BASE *base_ptr ;
-
- base_ptr = v4base + v4cur_base ;
-
- rc = u4read_init( base_ptr->file_hand, buffer_ptr, buffer_len, (long) base_ptr->header_len ) ;
- if ( rc < 0 ) return -1 ;
-
- for ( on_rec = 1; on_rec <= rec_count; on_rec++)
- {
- base_ptr->rec_num = on_rec ;
- if ( u4read( base_ptr->buffer, base_ptr->buffer_len ) != 0 ) return -1 ;
-
- rc = i4filter_check(index_ref) ;
- if ( rc < 0 ) return -1 ;
- if ( rc ) continue ;
-
- eval_ptr = e4string( index_ptr->compile ) ;
- if ( eval_ptr == (char *) 0) return( -1) ;
-
- #ifndef CLIPPER
- if ( v4type == (int) 'D' )
- if ( *eval_ptr == ' ' )
- *eval_ptr = 0xFF ;
- #endif
-
- u4sort_add( eval_ptr, (char *) &on_rec ) ;
- }
-
- return( 0) ;
- }
-
-
- #ifdef CLIPPER
- static int build_index()
- {
- BLOCK H_PTR block_ptr ;
- KEY H_PTR key_ptr;
- char H_PTR from_ptr ;
- char last_ptr[MAX_KEY_SIZE+2] ;
- int first_time ;
-
- if ( u4write_init( index_ptr->file_hand, buffer_ptr, buffer_len, (long) BLOCK_SIZE ) < 0 ) return -1 ;
-
- first_time = 1 ;
-
- block_on = block_max = -1 ;
- block_ptr= block_start + block_on ;
-
- file_block = BLOCK_SIZE ;
-
- while( 1)
- {
- /* Retrieves Keys in Sorted Order */
- if ( u4sort_get( &from_ptr ) < 0 ) return -1 ;
-
- if ( index_ptr->unique )
- {
- if ( ! first_time )
- {
- while ( from_ptr != (char H_PTR) 0 )
- {
- extern int v4unique_error ;
- if ( u4huge_cmp( (unsigned char H_PTR) from_ptr,
- (unsigned char H_PTR) last_ptr,
- (unsigned) sort_len) != 0) break ;
-
- /* Filter out any repeat keys. */
- if ( v4unique_error )
- {
- u4error( E_UNIQUE, index_ptr->name, (char *) 0) ;
- return( -1) ;
- }
- if ( u4sort_get( &from_ptr ) < 0 ) return -1 ;
- }
- }
- if ( from_ptr != (char H_PTR) 0 )
- u4huge_cpy( (char H_PTR) last_ptr, from_ptr, (long) sort_len ) ;
-
- first_time = 0 ;
- }
-
- if ( from_ptr == (char H_PTR) 0 )
- {
- /* Observe
- 1. Full Blocks will have been written if the entry which
- points the the block has been entered.
- 2. Either the bottom block may be written and give a starting
- block pointer or the last block written is a good starting
- block pointer.
- 3. There may be one stranded entry which may be added later.
- 4. file_block is the next address to be written
- */
-
- /* The key_value is not yet active */
- memset( &key_value, 0, sizeof(key_value) ) ;
-
- /* Check for no Entries */
- if ( block_max < 0 )
- {
- add_key( &key_value ) ;
- block_start[0].num_keys = 0 ;
-
- if( u4write( (char H_PTR) &block_start->num_keys, BLOCK_SIZE) != 0 )
- return( -1) ;
-
- file_block += BLOCK_SIZE ;
- }
- else
- {
- if ( block_start[0].num_keys == 0 )
- {
- while ( block_start[++block_on].num_keys == 0 ) ;
-
- block_ptr = block_start + block_on ;
- u4huge_cpy( (char H_PTR) &key_value, (char H_PTR) &block_ptr->num_keys +
- block_ptr->pointers[block_ptr->num_keys-1], (long) group_len) ;
- block_ptr->num_keys-- ;
- if ( block_ptr->num_keys != 0 ) block_on-- ;
- }
- }
-
- while( block_on < block_max )
- {
- block_on++ ;
- block_ptr = block_start+ block_on ;
-
- if ( block_ptr->num_keys > 0 )
- {
- key_ptr = (KEY H_PTR) ((char H_PTR) &block_ptr->num_keys+
- block_ptr->pointers[block_ptr->num_keys]) ;
- if ( block_on > 0 )
- key_ptr->file_block = file_block - BLOCK_SIZE ;
-
- if (u4write((char H_PTR) &block_ptr->num_keys, BLOCK_SIZE) != 0)
- return( -1) ;
-
- file_block += BLOCK_SIZE ;
- }
- }
- index_ptr->root = file_block - BLOCK_SIZE ;
- index_ptr->virtual_eof = index_ptr->eof = 0L ;
-
- return( 0 ) ;
- }
-
- u4huge_cpy( (char H_PTR) key_value.value, from_ptr, (long) key_len ) ;
- u4huge_cpy( (char H_PTR) &key_value.rec_num, from_ptr+sort_len, (long) sizeof(long) ) ;
- key_value.file_block = 0 ;
- if( add_key( &key_value ) < 0 ) return -1 ;
- }
- }
-
- #else
-
- static int build_index()
- {
- BLOCK H_PTR block_ptr ;
- KEY H_PTR key_ptr ;
- char H_PTR from_ptr ;
- char last_ptr[MAX_KEY_SIZE+2] ;
- int i, first_time ;
-
- if ( u4write_init( index_ptr->file_hand, buffer_ptr, buffer_len, (long) BLOCK_SIZE ) < 0 ) return -1 ;
-
- first_time = 1 ;
-
- block_on = block_max = 0 ;
- block_ptr= block_start + block_on ;
- u4huge_set( ((char H_PTR)block_ptr)+2*sizeof(int), 0,
- (long) (sizeof(BLOCK)-2*sizeof(int)) ) ;
-
- block_ptr->num_keys = keys_max ;
- file_block = 1 ;
-
- while( 1)
- {
- key_ptr = (KEY H_PTR) ((char H_PTR)&block_ptr->key - group_len) ;
- for( i=0; i< keys_max; i++)
- {
- /* Retrieves Keys in Sorted Order */
- if ( u4sort_get( &from_ptr ) < 0 ) return -1 ;
-
- if ( from_ptr != (char H_PTR) 0 && v4type == (int) 'D' )
- if ( *from_ptr == (char) 0xFF )
- *from_ptr = ' ' ;
-
- if ( index_ptr->unique )
- {
- if ( ! first_time )
- {
- while ( from_ptr != (char H_PTR) 0 )
- {
- extern int v4unique_error ;
-
- if ( u4huge_cmp((unsigned char H_PTR) from_ptr,
- (unsigned char H_PTR) last_ptr,
- (unsigned) sort_len) != 0 ) break ;
-
- /* Filter out any repeat keys. */
- if ( v4unique_error )
- {
- u4error( E_UNIQUE, index_ptr->name, (char *) 0) ;
- return( -1) ;
- }
- if ( u4sort_get( &from_ptr ) < 0 ) return -1 ;
- }
- }
- if ( from_ptr != (char H_PTR) 0 )
- u4huge_cpy( (char H_PTR) last_ptr, from_ptr, (long) sort_len ) ;
- first_time = 0 ;
- }
-
- if ( from_ptr == (char H_PTR) 0 && (i > 0 || block_max == block_on))
- {
- block_ptr->num_keys = i ;
- key_ptr = (KEY H_PTR) ((char H_PTR)&block_ptr->key+
- i * group_len) ;
- break ;
- }
-
- if ( from_ptr == (char H_PTR) 0)
- {
- while( ++block_on)
- {
- block_ptr = block_start+ block_on ;
-
- key_ptr = (KEY H_PTR) ((char H_PTR)&block_ptr->key+
- block_ptr->num_keys * group_len) ;
-
- if ( block_ptr->num_keys > 0)
- {
- if( u4write((char H_PTR)&block_ptr->num_keys, BLOCK_SIZE) != 0)
- return( -1) ;
- key_ptr->file_block = file_block++ ;
- }
- if ( block_on >= block_max)
- {
- index_ptr->root = file_block -1 ;
- index_ptr->eof = file_block ;
- return( 0 ) ;
- }
- if ( block_ptr->num_keys >= 0 )
- add_key( key_ptr ) ;
- }
- }
-
- key_ptr = (KEY H_PTR) ((char H_PTR)key_ptr + group_len) ;
- switch( index_ptr->i_type )
- {
- case 'C':
- u4huge_cpy( (char H_PTR) key_ptr->value, from_ptr, (long) key_len ) ;
- break ;
-
- case 'D':
- {
- char dbf_date[8] ;
- double d_index ;
- u4huge_cpy( (char H_PTR) dbf_date, from_ptr, (long) sizeof(dbf_date) ) ;
- c4dt_julian( dbf_date, &d_index ) ;
- u4huge_cpy( (char H_PTR) key_ptr->value, (char H_PTR) &d_index, (long) sizeof(double) ) ;
- break ;
- }
-
- case 'N':
- {
- double d ;
- char temp[MAX_KEY_SIZE+2] ;
- int i ;
-
- u4huge_cpy( (char H_PTR) temp, from_ptr, (long) sort_len ) ;
- temp[sort_len] = '\000' ;
-
- if ( temp[0] < 0x30 )
- {
- for ( i=0; i< sort_len; i++ )
- temp[i] = (char) 0x5c - temp[i] ;
-
- d = -c4atod( temp, sort_len ) ;
- }
- else
- d = c4atod( temp, sort_len ) ;
-
- u4huge_cpy( (char H_PTR) key_ptr->value, &d, (long) sizeof(d) ) ;
- break ;
- }
- }
-
- u4huge_cpy( (char H_PTR) &key_ptr->rec_num, from_ptr+sort_len, (long) sizeof(long)) ;
- }
- if( u4write((char H_PTR)&block_ptr->num_keys, BLOCK_SIZE) != 0)
- return( -1 ) ;
-
- key_ptr->file_block = file_block++ ;
- if( add_key(key_ptr ) < 0) return( -1 ) ;
- key_ptr->file_block = 0 ;
- }
- }
-
- #endif
-
-
- #ifdef CLIPPER
-
- static int add_key( KEY H_PTR key_ptr )
- {
- BLOCK H_PTR block_ptr ;
- int i, i_block ;
-
- block_on ++ ;
- block_ptr = block_start+ block_on ;
-
- if ( block_on > block_max )
- {
- /* Initialization for this block level */
- u4huge_set( ((char H_PTR)block_ptr)+2*sizeof(int), 0,
- (long) (sizeof(BLOCK)-2*sizeof(int)) ) ;
-
- i_block = keys_max*2 + 4 ;
- for (i=0; i<= keys_max; i++, i_block+= group_len)
- block_ptr->pointers[i] = i_block ;
-
- block_ptr->num_keys = 0 ;
- block_max = block_on ;
- }
-
- if ( block_ptr->num_keys >= keys_max )
- {
- u4huge_cpy( (char H_PTR)&block_ptr->num_keys +
- block_ptr->pointers[block_ptr->num_keys],
- (char H_PTR) &key_ptr->file_block, 4L) ;
-
- if( u4write((char H_PTR) &block_ptr->num_keys, BLOCK_SIZE) != 0)
- return( -1) ;
-
- key_ptr->file_block = file_block ;
- file_block += BLOCK_SIZE ;
- if( add_key( key_ptr) < 0) return( -1) ;
-
- block_ptr->num_keys = 0 ;
- }
- else
- {
- u4huge_cpy( (char H_PTR)&block_ptr->num_keys +
- block_ptr->pointers[block_ptr->num_keys],
- (char H_PTR) key_ptr, (long) group_len) ;
- block_ptr->num_keys++ ;
- }
-
- block_on -- ;
- return(0) ;
- }
-
- #else
-
- static int add_key( KEY H_PTR key_ptr )
- {
- BLOCK H_PTR block_ptr ;
-
- block_on ++ ;
- block_ptr = block_start+ block_on ;
-
- if ( block_on > block_max )
- {
- /* Initialization for this block level */
- u4huge_set( ((char H_PTR)block_ptr)+2*sizeof(int), 0,
- (long) (sizeof(BLOCK)-2*sizeof(int)) ) ;
- block_ptr->num_keys = -1 ;
- block_max = block_on ;
- }
-
- key_ptr->rec_num = 0 ;
-
- if ( ++block_ptr->num_keys >= keys_max )
- {
- u4huge_cpy( (char H_PTR)&block_ptr->key + block_ptr->num_keys*group_len,
- (char H_PTR) key_ptr, (long) sizeof(long)) ;
-
- if( u4write((char H_PTR) &block_ptr->num_keys, BLOCK_SIZE) != 0 )
- return( -1) ;
- key_ptr->file_block = file_block++ ;
- if( add_key( key_ptr) < 0) return( -1) ;
-
- block_ptr->num_keys = -1 ;
- }
- else
- u4huge_cpy( (char H_PTR)&block_ptr->key + block_ptr->num_keys*group_len,
- (char H_PTR) key_ptr, (long) group_len) ;
-
- block_on -- ;
- return(0) ;
- }
-
- #endif
-
- #ifdef CLIPPER
- int v4clipper_len = 17 ;
- int v4clipper_dec = 2 ;
- #endif
-
- static int index_info( int index_ref )
- {
- INDEX *index_ptr ;
- char *eval_ptr ;
-
- index_ptr = v4index + index_ref ;
- memset( d4ptr()->buffer, (int) ' ', (size_t) d4ptr()->buffer_len) ;
-
- eval_ptr = (char *) e4vary( index_ptr->compile ) ;
- if ( eval_ptr == (char *) 0) return( -1) ;
-
- index_ptr->i_type = e4type() ;
- if ( index_ptr->i_type == 'n' ) index_ptr->i_type = 'N' ;
- if ( index_ptr->i_type == 'd' ) index_ptr->i_type = 'D' ;
-
- key_len = e4length() ;
-
- #ifdef CLIPPER
- if ( index_ptr->i_type == 'D' )
- key_len = 8 ; /* CCYYMMDD */
-
- /* Clipper Numeric Possibilities
- Field
- - e4vary should return the value as 'n'.
- - The fields number of decimals should be used.
-
- Calculation
- - e4vary should return the value as 'N'.
- - Width of 'v4clipper_len' and 'v4clipper_dec' decimals should be used.
- */
-
- if ( index_ptr->i_type == 'N' )
- {
- long f_ref ;
-
- index_ptr->key_dec = v4clipper_dec ;
- key_len = v4clipper_len ;
-
- if ( e4type() == 'n' )
- {
- /* Its a field */
- f_ref = f4ref( index_ptr->expression ) ;
- if ( f_ref >= 0 )
- {
- key_len = f4width(f_ref ) ;
- index_ptr->key_dec = f4decimals(f_ref) ;
- }
- }
- }
- #else
- if ( index_ptr->i_type == 'D' || index_ptr->i_type == 'N' )
- {
- key_len = sizeof(double) ;
- index_ptr->int_or_date = 1 ;
- }
- else
- index_ptr->int_or_date = 0 ;
- #endif
-
- if ( key_len > MAX_KEY_SIZE || key_len <= 0 )
- {
- u4error( E_KEY_LEN, index_ptr->name, "Expression:", index_ptr->expression, (char *) 0) ;
- return( -1) ;
- }
-
- index_ptr->key_len = key_len ;
- index_ptr->version = index_ptr->old_version + 1 ;
-
- #ifdef CLIPPER
- index_ptr->sign = 6 ;
- index_ptr->group_len = group_len = key_len+8 ;
- index_ptr->keys_half = (1020/ (group_len+2) - 1)/ 2;
- index_ptr->keys_max = keys_max = index_ptr->keys_half *2 ;
- if ( keys_max < 2 )
- {
- u4error( E_BAD_NDX, index_ptr->name, (char *) 0 ) ;
- return( -1 ) ;
- }
- #else
- #ifdef PORTABLE
- group_len = key_len+3*sizeof(long) - key_len%sizeof(long) ;
- if ( key_len%sizeof(long) == 0 ) group_len -= sizeof(long) ;
- index_ptr->group_len = group_len ;
- #else
- index_ptr->group_len = group_len = key_len+8 + key_len%2 ;
- #endif
- index_ptr->keys_max = keys_max = 504/ index_ptr->group_len ;
- if ( keys_max < 4 )
- {
- u4error( E_BAD_NDX, index_ptr->name, (char *) 0 ) ;
- return( -1 ) ;
- }
- #endif
-
- return 0 ;
- }
-
- static int write_header(void) ;
- static int write_header()
- {
- char buffer[BLOCK_SIZE] ;
- int header_len ;
-
- memset( buffer, 0, (size_t) BLOCK_SIZE ) ;
-
- lseek( index_ptr->file_hand, 0L, 0) ;
- #ifdef CLIPPER
- /* These 'chsize' calls can be removed if the 'chsize' is not available.
- It just reduces the size of the index file if it is smaller. */
- #ifndef NO_CHSIZE
- chsize(index_ptr->file_hand, index_ptr->root+ (long) BLOCK_SIZE ) ;
- #endif
- header_len = (char *)(v4index+1) - (char *) &v4index->sign ;
- memcpy( buffer, &index_ptr->sign, (size_t) header_len ) ;
- #else
- #ifndef NO_CHSIZE
- chsize(index_ptr->file_hand, index_ptr->eof*BLOCK_SIZE) ;
- #endif
- header_len = (char *)(v4index+1) - (char *) &v4index->root ;
- memcpy( (char *) buffer, (char *) &index_ptr->root, (size_t) header_len ) ;
- #endif
- if ( write( index_ptr->file_hand, (char *) buffer, BLOCK_SIZE) != BLOCK_SIZE )
- {
- u4error( E_WRITE, index_ptr->name, (char *) 0 ) ;
- return( -1 ) ;
- }
-
- return 0 ;
- }
-
-
- static int calc_blocks_needed()
- {
- int count ;
- long num_recs ;
-
- num_recs = d4reccount() ;
-
- for ( count = 1;; count++ )
- {
- num_recs /= index_ptr->keys_max ;
- if ( num_recs == 0L ) return count+1 ;
- }
- }
-
-
- /* Returns the number of spools used; -1 if not enough memory */
-
- static int memory_init( unsigned buffer_size, int sort_len )
- {
- buffer_len = 0 ;
-
- if ( (buffer_ptr = (char H_PTR) d4buf_alloc( (long) buffer_size,1)) == (char H_PTR) 0 )
- return -1 ;
-
- buffer_len = buffer_size ;
-
- return( u4sort_init( d4reccount(), sort_len, sizeof(long)) ) ;
- }
-
-
- static int reindex( int index_ref )
- {
- int rc ;
-
- index_ptr = v4index + index_ref ;
-
- if ( index_ptr->compile != (char *) 0 ) h4free_memory( index_ptr->compile) ;
- if ( e4parse( index_ptr->expression, &index_ptr->compile) < 0) return(-1) ;
-
- if ( index_info(index_ref) < 0 ) return -1 ;
- if ( e4string( index_ptr->compile ) == (char *) 0 ) return -1 ;
-
- sort_len = e4length() ;
- if ( sort_len > MAX_KEY_SIZE ) sort_len = MAX_KEY_SIZE ;
-
- /* MEMORY ALLOCATION */
-
- /* Memory Buffer Operations. */
- d4buf_avail_set() ;
-
- /* Determine the number of index file blocks necessary. */
- if ( (block_start = (BLOCK H_PTR) d4buf_alloc((long) calc_blocks_needed(), sizeof(BLOCK))) == (BLOCK H_PTR) 0 )
- {
- u4error( E_SORT, i4name(index_ref), (char *) 0 ) ;
- return -1 ;
- }
- d4buf_sub_set() ; /* Minimum needed. Change sub-pool position. */
-
- if ( (rc = memory_init( 0xF800, sort_len)) != 0 )
- {
- if ( rc > 0 )
- /* Memory Allocated by Sort using several buffers.
- Release and try again. */
- u4sort_free() ;
-
- d4buf_avail_set() ;
-
- /* Reduce the number of spools by allocating less memory
- to read and write the database and index file. */
- if ( memory_init( 0x2000, sort_len ) < 0 )
- {
- d4buf_avail_set() ;
-
- if ( memory_init( 0, sort_len ) < 0 )
- {
- u4error( E_SORT, index_ptr->name, (char *) 0 ) ;
- return -1 ;
- }
- }
- }
-
- /* MEMORY ALLOCATION - END */
-
- /* Sort the Information */
- if ( build_sort(index_ref) < 0)
- return( -1 ) ;
-
- /* Build the Index File */
- rc = build_index() ;
- if ( rc < 0L) return( -1) ;
-
- if ( u4write_flush() < 0 ) return -1 ;
-
- /* Write the Index File Control Information (Block 0) */
- if ( write_header() < 0 ) return -1 ;
-
- #ifdef CLIPPER
- if ( key_value.rec_num != 0 )
- {
- if ( i4add( index_ref, key_value.value, key_value.rec_num ) < 0 )
- return -1 ;
- }
- #endif
-
- return( 0 ) ;
- }
-
-
- static int reindex_w_clean( int index_ref )
- {
- int rc ;
-
- buffer_ptr = (char H_PTR) 0 ;
- buffer_len = 0 ;
-
- if ( reindex( index_ref ) < 0)
- rc = -1 ;
- else
- rc = 0 ;
-
- u4sort_free() ;
- i4unlock( index_ref ) ;
-
- return rc ;
- }
-
-
- i4reindex( int index_ref )
- {
- int rc, index_on, old_base ;
- H4BUF buf_saved ;
-
- if ( index_ref >= 0)
- old_base = d4select( v4index[index_ref].base_ref) ;
- else
- old_base = d4select(-1) ;
-
- #ifdef WINDOWS
- if ( (rc = d4lock( v4lock_wait, 1)) < 0)
- #else
- if ( (rc = d4lock_all( v4lock_wait, 1)) < 0)
- #endif
- {
- d4select( old_base) ;
- return rc ;
- }
-
- if ( d4flush( v4cur_base) < 0 )
- {
- d4select( old_base) ;
- return -1 ;
- }
-
- if ( d4buf_clear_lend(1) == -1 )
- {
- d4select( old_base) ;
- return -1 ;
- }
-
- d4buf_save_status( &buf_saved ) ;
-
- rec_count = d4reccount() ;
-
- if ( index_ref >= 0 )
- rc = reindex_w_clean( index_ref ) ;
- else
- for ( rc = 0, index_on = d4ptr()->index_ref; rc == 0 && index_on >= 0;
- index_on = v4index[index_on].prev )
- {
- rc = reindex_w_clean(index_on) ;
- }
-
- d4blank() ;
- d4select(old_base) ;
-
- d4buf_restore_status( &buf_saved ) ;
- d4buf_return() ;
-
- return( rc) ;
- }
-