home *** CD-ROM | disk | FTP | other *** search
- /* (c)Copyright Sequiter Software Inc., 1987-1990. All rights reserved.
-
- u4sort.c
-
- Sort and Spool Module
- */
-
- #include "p4misc.h"
- #include "d4all.h"
- #include "u4error.h"
-
- #include <string.h>
- #include <stdio.h>
- #ifndef UNIX
- #include <io.h>
- #endif
-
- #define MAX_SPOOLS 300
-
- typedef struct spool_st
- {
- char H_PTR ptr ; /* Pointer to the current buffer position */
- char H_PTR end ; /* Pointer to the end buffer position */
- long disk ; /* Current Disk Position, Offset from start of 'spool'
- >= 'spool_bytes' means nothing is on disk. */
- short spool_i ; /* The spool number of this spool */
- short dummy ; /* To make 0x10000 divisiable by sizeof(SPOOL) */
- } SPOOL ;
-
- static unsigned width_sort ; /* The width of each records sort information. */
- static unsigned width_add ; /* The width of additional information */
- static unsigned width_total ; /* The total spool record width */
-
- static long spool_num_rec; /* The number of records in each spool set */
- static long spool_bytes ; /* The number of bytes in each spool record set */
- static short spool_num ; /* The number of spools */
- static short spool_i ; /* The spool currently being written to. */
- static int spool_handle = -1 ; /* The handle to the spool file */
- static char spool_name[9]; /* The name of the spool file */
- SPOOL H_PTR spool ; /* Each element of the spool array describes a 'spool' */
-
- static long sub_bytes ; /* The number of bytes in each sub-spool */
- static long sub_num_rec ; /* The number of spool records in each sub-spool */
- static short sub_index ; /* An index into 'spool' of the smallest value */
- static short first_spool_get ;
-
- static char H_PTR huge_buffer = 0 ;
- static char H_PTR H_PTR huge_pointers = 0 ; /* A huge array of huge pointers */
- static long i_pointers = 0L ;
-
- static int u4spool( long, int ) ;
- static int u4spool_read(short) ;
- static int u4sort_alloc( short, long, int ) ;
-
- static H4BUF saved_status = { -1L, -1L, -1L, 0 } ;
-
- extern int v4cur_base ;
-
- /* Generic Spool and Merge,
-
- Format: Sort Data, Related Info.
-
- Sorted information comes first.
- */
-
- int u4sort_init( long num_records, int sort_width, int info_width )
- {
- short i ;
-
- d4buf_save_status( &saved_status ) ;
-
- /* Sort Initialization Starts Now */
- width_sort = sort_width ;
- width_add = info_width ;
- width_total= sort_width + info_width ;
-
- first_spool_get = 1 ;
- spool_handle = -1 ;
- i_pointers = 0L ;
-
- if ( u4sort_alloc( 0, num_records, width_total) == 0 ) return 0 ;
-
- for( i = 2; i <= MAX_SPOOLS; i++ )
- {
- d4buf_restore_status( &saved_status ) ;
- if ( u4sort_alloc( i, num_records, width_total) == 0 ) return i ;
- }
-
- u4sort_free() ;
- return -2 ;
- }
-
- static int u4sort_alloc( short num_spools, long tot_records, int tot_width )
- {
- long i_rec ;
- union
- {
- char H_PTR p ;
- char H_PTR H_PTR pp ;
- } ptr ;
-
- spool_i = 0 ;
- spool_num = num_spools ;
- if ( num_spools <= 1 )
- spool_num_rec = tot_records ;
- else
- spool_num_rec = (tot_records+num_spools-1)/num_spools ;
- spool_bytes = spool_num_rec * width_total ;
-
- /* Note: One extra record of space for the quick sort algorithim. */
- ptr.p = (char H_PTR) d4buf_alloc( spool_num_rec+1, sizeof(char H_PTR) ) ;
- if ( ptr.p == (char H_PTR) 0 ) return -1 ;
- huge_pointers = ptr.pp ;
-
- spool = (SPOOL H_PTR) d4buf_alloc( (long) spool_num, sizeof(SPOOL)) ;
- if ( spool == (SPOOL H_PTR) 0) return -1 ;
-
- huge_pointers[0] =
- huge_buffer = (char H_PTR) d4buf_alloc((long) (spool_num_rec+1)*tot_width, 1);
- if ( huge_buffer == (char H_PTR) 0 ) return -1 ;
-
- for ( i_rec = 1L; i_rec <= spool_num_rec; i_rec++ )
- huge_pointers[i_rec] = (char *) u4huge_norm(huge_pointers[i_rec-1] + tot_width) ;
-
- d4buf_sub_set() ;
- return 0 ;
- }
-
-
- int u4sort_add( char *sort_data_ptr, char *info_ptr )
- {
- if ( i_pointers < spool_num_rec )
- {
- memcpy( (char *) huge_pointers[i_pointers], sort_data_ptr, (size_t) width_sort ) ;
- memcpy( (char *)(huge_pointers[i_pointers++]+width_sort), info_ptr, (size_t) width_add ) ;
- }
- else
- {
- if ( u4spool( spool_num_rec, 0 ) < 0 ) return -1 ;
- i_pointers = 0L ;
- u4sort_add( sort_data_ptr, info_ptr ) ;
- }
-
- return 0 ;
- }
-
-
- /* u4spool
-
- - 'ptr' points to a big block of memory which is to be spooled.
- - 'num_items' must always be less than or equal to the first
- 'num_items' value.
- */
-
- static int u4spool( long num_rec, int is_last )
- {
- long write_bytes, i_on, i_free ;
- char H_PTR i_on_ptr, H_PTR free_pointer ;
- short i ;
-
- spool_i++ ;
-
- /* Sort the spool items. */
- u4sort_quick( huge_pointers, num_rec, width_sort );
-
- if ( is_last )
- {
- if ( spool_i == 1)
- {
- /* First and Last time through 'u4spool' */
- /* No need to spool to disk. Initialize for 'u4sort_get' */
- spool_num = 0 ;
- spool_num_rec = i_pointers ;
- return 0 ;
- }
-
- sub_index = 0 ;
- }
-
- write_bytes = i_pointers * width_total ;
-
- if ( spool_i > spool_num )
- {
- u4error( E_SORT_ADD, (char *) 0 ) ;
- u4sort_free() ;
- return -1 ;
- }
-
- if ( spool_i == 1 )
- {
- /* First time through 'u4spool' */
- /* Open the temporary File */
- strcpy( spool_name, "T4" ) ;
- if ( (spool_handle = u4temp_create(spool_name)) < 0 )
- {
- u4sort_free() ;
- return -1 ;
- }
- lseek( spool_handle, 0L, 0) ;
- }
-
- /* Make the Sorted Values Consecutive in Memory */
- for( i_on = 0L, i_on_ptr = huge_buffer; i_on < i_pointers; )
- {
- if ( huge_pointers[i_on] == i_on_ptr )
- {
- i_on_ptr += width_total ;
- i_on++ ;
- continue ;
- }
-
- u4huge_cpy( huge_pointers[spool_num_rec], huge_pointers[i_on], (long) width_total) ;
-
- free_pointer = huge_pointers[i_on] ;
- huge_pointers[i_on] = huge_pointers[spool_num_rec] ;
-
- do
- {
- i_free = (free_pointer - huge_buffer) / width_total ;
- u4huge_cpy( free_pointer, huge_pointers[i_free], (long) width_total) ;
- free_pointer = huge_pointers[i_free] ;
- huge_pointers[i_free] = huge_buffer + i_free*width_total ;
- } while ( free_pointer != huge_pointers[spool_num_rec] ) ;
- }
-
- if ( u4huge_write( spool_handle, huge_buffer, write_bytes) < 0)
- {
- u4sort_free() ;
- return -1 ;
- }
-
- if ( is_last )
- {
- spool_num = spool_i ;
- sub_bytes = spool_bytes / spool_num ;
- sub_num_rec= sub_bytes / width_total ;
- sub_bytes = sub_num_rec * width_total ;
-
- if ( sub_num_rec == 0L )
- {
- u4error( E_MEMORY, "Reindexing a File", (char *) 0 ) ;
- u4sort_free() ;
- return -1 ;
- }
-
- /* Initialize for the calls to 'u4sort_get' */
- for ( i=0; i< spool_num; i++ )
- {
- spool[i].disk = 0L ;
- spool[i].spool_i = i ;
- if ( u4spool_read(i) < 0 ) return -1 ;
- }
- }
- return 0 ;
- }
-
-
- /* u4spool_read
-
- Returns
-
- 0 OK
- -1 Error
- */
-
- static int u4spool_read(short sub_index)
- {
- long bytes_read, ask_read ;
-
- /* Is there anything still on disk ? */
- if ( spool[sub_index].disk >= spool_bytes )
- {
- if ( spool_num > 0)
- {
- /* Nothing left for Buffer */
- u4huge_cpy( spool+sub_index, spool+sub_index+1,
- (long) sizeof(SPOOL)*(spool_num-sub_index-1) ) ;
- spool_num-- ;
- }
- return( 0) ;
- }
-
- spool[sub_index].ptr = (char H_PTR) u4huge_norm( huge_buffer+ spool[sub_index].spool_i*sub_bytes) ;
-
- ask_read = spool_bytes - spool[sub_index].disk ;
- if (ask_read > sub_bytes) ask_read = sub_bytes ;
-
- /* Read in the rest of the buffer from disk */
- lseek( spool_handle,
- spool[sub_index].spool_i*spool_bytes+ spool[sub_index].disk, 0) ;
- bytes_read = u4huge_read( spool_handle, spool[sub_index].ptr, ask_read ) ;
- if ( bytes_read < 0L)
- {
- u4sort_free() ;
- return -1 ;
- }
-
- /* Check for Error */
- if ( bytes_read % width_total != 0 )
- {
- u4error( E_READ, "Temporary Spool File:", spool_name, (char *) 0 ) ;
- u4sort_free() ;
- return -1 ;
- }
-
- if ( bytes_read < sub_bytes )
- {
- spool[sub_index].disk = spool_bytes ; /* Flag nothing on disk. */
-
- if ( bytes_read == 0L )
- /* Nothing on disk and nothing in memory. */
- return( u4spool_read(sub_index) ) ;
- }
- else
- spool[sub_index].disk += bytes_read ;
-
- spool[sub_index].end = spool[sub_index].ptr + bytes_read ;
-
- return 0 ;
- }
-
-
- /* u4sort_get
-
- Returns
-
- 0 - OK
- -1 - Error
- -2 - None Left
- */
-
- int u4sort_get( char H_PTR *ptr_ptr )
- {
- char H_PTR current ;
- int i ;
-
- if ( first_spool_get )
- {
- first_spool_get = 0 ;
- if ( u4spool( i_pointers, 1 ) < 0 ) return -1 ;
-
- i_pointers = 0L ;
- }
-
- *ptr_ptr = (char H_PTR) 0 ;
- if ( spool_num < 0 ) return 0 ;
-
- if ( spool_num == 0 )
- {
- /* Get from the memory buffer which has never been spooled */
- if (i_pointers >= spool_num_rec )
- {
- spool_num = -1 ;
- u4sort_free() ;
- }
- else
- *ptr_ptr = huge_pointers[i_pointers++] ;
-
- return 0 ;
- }
-
- /* Check to make sure the last buffer accessed is up to date. */
- if ( (char H_PTR) spool[sub_index].ptr >= (char H_PTR) spool[sub_index].end )
- if ( u4spool_read(sub_index) < 0 ) return -1 ;
-
- if ( spool_num <= 0 )
- {
- u4sort_free() ;
- return 0 ; /* Nothing left */
- }
-
- /* Search for the smallest value. If the values are equal, use the
- first spool value. */
-
- current = spool[0].ptr ;
- sub_index = 0 ;
-
- for ( i= 1; i< spool_num; i++ )
- {
- if ( u4huge_cmp( (unsigned char H_PTR) current,
- (unsigned char H_PTR) spool[i].ptr, width_sort) > 0 )
- {
- current = spool[i].ptr ;
- sub_index = i ;
- }
- }
-
- *ptr_ptr = spool[sub_index].ptr ;
- spool[sub_index].ptr += width_total ;
-
- return 0 ;
- }
-
-
- void u4sort_free()
- {
- if ( spool_handle >= 0 )
- {
- close( spool_handle ) ;
- spool_handle = -1 ;
- u4remove(spool_name) ;
- }
-
- if ( saved_status.len >= 0L )
- {
- d4buf_restore_status( &saved_status ) ;
- saved_status.len = -1L ;
- }
-
- huge_pointers = (char H_PTR H_PTR) 0 ;
- spool_num = -1 ;
- }
-
-
-