.ad 8
.bm 8
.fm 4
.bt $Copyright (c) 1995-2005 SAP AG$$Page %$
.tm 12
.hm 6
.hs 3
.tt 1 $SQL$Project Distributed Database System$vni56c$
.tt 2 $$$
.tt 3 $$$1995-08-01$
***********************************************************
.nf

.nf

.nf

    ========== licence begin  GPL
    Copyright (c) 1995-2005 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end
.fo


.fo


.fo
.nf
.sp
Module  :
=========
.sp
Purpose :
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :

.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :

.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :

.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : 
.sp
.cp 3
Created : 1995-08-01
.sp
.cp 3
\Version : 1995-08-01
.sp
.cp 3
\Release :      Date :
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification: puplst (Erstellung von Tabellenlisten fuer 
	       multiples updcol und Verify) 

.CM *-END-* specification -------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:

.CM *-END-* description ---------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:

.CM *-END-* structure -----------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.oc _/1
.CM -lll-
Code    :
#include	<stdio.h>
#include	<stdlib.h>

int	compar (const void * a , const void * b) ;
char    * get_next () ;
/* PTS 6129 */
void create_lists () ;

EXEC SQL BEGIN DECLARE SECTION ;

#define KNL_IDENTIFIER_LEN 64
#define KNL_IDENTIFIER_LEN_C 65

EXEC SQL END DECLARE SECTION ;

struct tabent 
{		
	/* PTS 1001027 */
	char	tabname [KNL_IDENTIFIER_LEN_C] ;
	int	tabsize ;
} ;

struct tabent 	*tabarr ;
char   	      	fpref [50] ;
int	      	updcol = 0 ;
int	      	verbose = 0 ;

struct	s 
{  
   struct s	*next ;
	/* PTS 1001027 */
   char		tabname [KNL_IDENTIFIER_LEN_C] ;
   int		size ;
} ;

struct s	*a[50] ;
struct s	b[50] ;

main (argc,argv) 
int	argc ;
char	**argv ;
{

    EXEC SQL BEGIN DECLARE SECTION ;

	/* PTS 1001027 */
    char	tabname [KNL_IDENTIFIER_LEN_C] ;
    int	cnt ;
    EXEC SQL END DECLARE SECTION ;

    int	uncond = 0 ;
    int	ind = 0 ;
    int	anz = 0;
    int	pasum = 0 ;
    int	j = 0 , i= 0 ;
    int	zwisum = 0 ;
    int lstn = 0 ;
    int	src ;

    FILE	*f ;

    if ( argc < 2 || argc > 6 )
	usage () ;
    
    for (i=1; i < argc-1 ; i++)
    {
        if (argv[i][0] == '-')
            switch (argv[i][1])
            {
		case 'f' : strcpy ( fpref , argv [++i] ) ;
			   break ;
                case 'u' : uncond = 1 ;
                           break ;
		case 'v' : verbose = 1;
			   break ; 
		case 's' : updcol = 1;
			   break ; 
                default  : usage() ;
	    }
    }

    anz = atoi ( argv [argc-1] ) ;

    if ( anz < 1 || anz >= 50 )            
	usage () ;

    /* EXEC SQL SHOW (JOC$TTAB) TABLE ; */
	
	/* PTS xxxx */ 
    EXEC SQL CONNECT;
    if ( sqlca.sqlcode ) 
    {
         fprintf ( stderr , "DB connect error : %d\n" , sqlca.sqlcode ) ;
         exit (1) ;
    }

    EXEC SQL SELECT JOC$TTAB (OWNER,TABLENAME,TABLETYPE) FROM DOMAIN.TABLES 
      WHERE OWNER in (USER, USERGROUP) ;

    if ( sqlca.sqlcode ) 
    {
         fprintf ( stderr , "DB connect error : %d\n" , sqlca.sqlcode ) ;
         exit (1) ;
    }

    printf ("Collecting data, please wait ...\n");

    EXEC SQL SELECT COUNT (*) INTO :cnt FROM JOC$TTAB ;

    if ( ( tabarr = malloc ( cnt * sizeof ( struct tabent ) ) ) == NULL )
    {
        perror ("cannot allocate memory for table array" );
        EXEC SQL COMMIT WORK RELEASE ;
        exit (1) ;
    }

    EXEC SQL CREATE TABLE SQD$TPAGES
       ( TABNAME       char (64) key ,
         TDATE         char (10) ,
         PAGS          fixed (10) ) ;
    
    if ( sqlca.sqlcode == 0 )
    {
        uncond = 1 ;
        EXEC SQL COMMIT WORK ;
    }
    
    if ( updcol )
    {
	    EXEC SQL CREATE TABLE TEMP.JOC$IN
	        ( TABLENAME     char (64) KEY ) ;
	
	    EXEC SQL INSERT TEMP.JOC$IN 
		( SELECT tablename FROM INDEXCOLUMNS WHERE owner in (USER, USERGROUP) )
	        IGNORE DUPLICATES ;
				
    }

    EXEC SQL SELECT JOC$T1 (tablename) from JOC$TTAB
         WHERE OWNER in (USER, USERGROUP)
         AND ( TABLETYPE = 'TABLE' )
         AND TABLENAME NOT LIKE 'JOC$%' ;

    src = sqlca.sqlcode ;

    while ( src == 0 ) 
    {
	EXEC SQL FETCH JOC$T1 INTO :tabname ;  

	if ( src = sqlca.sqlcode ) break ;

	if ( uncond ) 
	{
	    if ( add_tabstat ( tabname  , ind ) ) 
	    {
		if ( verbose ) 
	            printf ( "%-16s %d\n" , tabarr [ind] .tabname ,  
		        tabarr [ind] . tabsize ) ;
	        pasum +=  tabarr [ind] . tabsize ;
	        ind++ ;
	    }
	}
	else
	{
	    if ( compare_stat ( tabname , ind  ) ) 
	    {
		pasum +=  tabarr [ind] . tabsize ;
		ind++ ;
	    }
        }
    }

    if ( verbose ) 
        printf ( "Summe %d\n" , pasum ) ;


    qsort ( (void *) tabarr , ind , sizeof ( struct tabent ) , compar ) ;

    create_lists ( anz , ind , pasum / anz) ;

    for ( i = 0 ; i <= anz ; i++ )
    {
	char	fn [40] ;
	int	zwisum = 0 ;

	sprintf ( fn , "%s.%d" , fpref , i ) ;

	if ( ( f = fopen ( fn , "w" ) ) == NULL )
	{
	    perror ("Open output file\n" ) ;
	    exit (1) ; 
	}

	
	a[i] = & b[i] ;

	if ( a[i]->size != -1 ) 
	do 
        {
	    fprintf ( f , "%s\n" , a[i]->tabname ) ;
	    zwisum += a[i]->size ;
	    a[i] = a[i]->next ;
	}
	while ( a[i] ) ;

        if ( verbose )
            printf ( "Liste %d : %d Pages\n" , i , zwisum ) ;

	fclose (f) ;

	if ( zwisum == 0 )
	{
	    unlink ( fn ) ;
	    zwisum = -1 ;
        }
	else
	    lstn++ ;
    }

    if ( verbose )
        printf ("Data for %d parallel update processes collected, %d pages \n",
	    lstn , pasum ) ;

    EXEC SQL COMMIT WORK RELEASE ;
    return (0) ;
}


add_tabstat ( tn , i ) 
int	i ;
char	*tn ;
{
	int rc ;

        if ( updcol && ! check_key_index ( tn ) ) 
	    return 0 ;
        
	if ( (rc = get_actstat ( tn ) ) != -1 )
	{ 
	    tabarr [i] . tabsize = rc ;
	    strcpy ( tabarr [i] . tabname , tn ) ;
	    return 1 ;
	}
	else
	    return 0 ;
}


compare_stat ( tn , i ) 
char 	*tn ;
{
    if ( check_stat (tn) )
    {
	if ( add_tabstat ( tn , i ) == 0 )
	    return 0 ; 
        printf ("%-16s added : %6d pages\n" , tn , tabarr [i] . tabsize ) ;
	return 1 ;
    }
    return 0 ;
}

get_actstat ( t ) 
char    *t ;
{
    EXEC SQL BEGIN DECLARE SECTION ;
    char    *tabname ;
    int     pages = 0 ;
    char    line [200] ;
    EXEC SQL END DECLARE SECTION ;

    tabname = t ;

/* ADIS 10001252 */

	EXEC SQL SELECT numeric_value INTO :pages FROM PAGES 
		WHERE TABLENAME = :tabname ;

	return ( pages ) ;
}

check_stat ( tabname ) 
char *tabname ;
{
    float npages , opages ;

    npages = (float) get_actstat ( tabname ) ;
    if ( npages == -1 ) 
	return (0) ;
    opages = (float) get_opages ( tabname ) ;
	
    if ( (int) npages == (int) opages ) return (0)  ; 

    if ( (int) opages == 0 && (int) npages != 0 ) return (1) ;

    if ( npages && opages && npages / opages < 1.5 && npages / opages > 0.6 )
	return (0)  ;
    
    return (1) ;
}

get_opages ( t1 )
char    *t1 ;
{
    EXEC SQL BEGIN DECLARE SECTION ;
    int  pages1 ;
    int  ipages ;
    char *tabname1 ;
    EXEC SQL END DECLARE SECTION ;

    tabname1 = t1 ;

    EXEC SQL
        SELECT pags INTO :pages1 :ipages
        FROM sqd$tpages WHERE tabname = :tabname1;

    return ( ( sqlca.sqlcode == 100 || ipages ) ? 0 : pages1 ) ;
}

check_key_index (tn )
char	*tn ;
{
   EXEC SQL BEGIN DECLARE SECTION ;
   char itabn [KNL_IDENTIFIER_LEN_C] ;
   char	cmd [300] ;
   EXEC SQL END DECLARE SECTION ;

   strcpy ( itabn , tn ) ;

   EXEC SQL SELECT TABLENAME 
        FROM TEMP.JOC$IN 
	WHERE tablename = :itabn ; 

   if ( sqlca.sqlcode == 0 ) 
     return (1) ;

   sprintf ( cmd , "SELECT COLUMNNAME FROM DOMAIN.COLUMNS WHERE OWNER = USER AND TABLENAME = \'%s\' AND COLUMNNAME <> 'SYSKEY' AND KEYPOS > 0 ORDER BY KEYPOS" , itabn ) ;
   EXEC SQL EXECUTE IMMEDIATE :cmd;

   if ( sqlca.sqlcode == 0 ) 
     return (1) ;

   sprintf ( cmd , "SELECT COLUMNNAME FROM DOMAIN.COLUMNS WHERE OWNER = USERGROUP AND TABLENAME = \'%s\' AND COLUMNNAME <> 'SYSKEY' AND KEYPOS > 0 ORDER BY KEYPOS" , itabn ) ;
   EXEC SQL EXECUTE IMMEDIATE :cmd;
   
   if ( sqlca.sqlcode == 0 ) 
     return (1) ;
	
   return (0) ;
}

usage ()
{
   fprintf ( stderr, "Usage: puclst [-u] count\n" ) ;
   exit (1) ;
}

compar ( avo , bvo )
const void * avo ;
const void * bvo ;
{
    int	o = 0 ;
	struct	tabent	* a ;
	struct	tabent	* b ;

	a = (struct	tabent	*) avo ;
	b = (struct	tabent	*) bvo ;

    if ( a->tabsize < b->tabsize)
	o = 1 ;
    else if ( a->tabsize > b->tabsize)
	o = -1 ;
    if ( verbose ) 
	printf ( "qsort: %s, %d, %s, %d, %d\n" ,
	  a->tabname , a->tabsize ,
	  b->tabname , b->tabsize ,
	  o ) ;
    return o ;
}

void create_lists (anz,tabs,maxsum) 
{
    int   k = 0 ;
    int   full [50] ;
    int   sum [50] ;
    int	  notfull = anz ;
    int   j ;

    if ( verbose )
	printf ("anz = %d, tabs = %d, maxsum = %d\n" , 
	    anz , tabs , maxsum ) ;

    /* PTS 1117962 */
    /* initialize first element of each list */
    for ( j = 0 ; j < anz ; j++ )
    {
      sum [j] = 0 ;
      full [j] = 0 ;
      a[j] = & b[j] ;
      a[j]->size = -1 ; 
	  a[j]->next = 0 ;
    }
	
    /* fill first element of each list */
    for ( j = 0 ; j < anz && k < tabs ; j++ )
    {
      strcpy (a[j]->tabname , tabarr[k].tabname ) ;
      a[j]->size = tabarr[k].tabsize ;
      sum [j] += a[j]->size ;
      k++ ;
    }

    /* fill all lists */
    while ( ( notfull ) && ( k < tabs ) )
    {
      for ( j = 0 ; j < anz && k < tabs ; j++ )
      {
	    if ( ! full [j] ) 
	    {
          a[j]->next = (struct s *) get_next () ;
          a[j] = a[j]->next ;
          a[j]->next = 0 ;
          a[j]->size = tabarr[k].tabsize ;
          strcpy (a[j]->tabname , tabarr[k].tabname ) ;
          sum [j] += a[j]->size ;
          if ( verbose ) 
		    printf ("Liste %d, %s %d\n" , j , a[j]->tabname , a[j]->size ) ;
	      k++ ;
	      if ( sum [j] > maxsum )
	      {
		    full [j] = 1 ;
  	 	    notfull-- ;
          }
	    }
      }
    }
}

char * get_next () 
{
    char  *rc ;
    if ( ( rc =  malloc ( sizeof (struct s) ) ) == NULL )
    {
	perror ("malloc failed") ;
	exit (1) ;
    }
	
    return ( rc ) ;
}

.CM *-END-* code ----------------------------------------
.sp 2
***********************************************************
*-PRETTY-*  statements    :           0
*-PRETTY-*  lines of code :           0
*-PRETTY-*  lines in file :           0
.pa
