Release Notes


Data Links Manager Quick Beginnings


11.1 Dlfm start Fails with Message: "Error in getting the afsfid for prefix"

For a Data Links Manager running in the DCE-DFS environment, if dlfm start fails with the error:

   Error in getting the afsfid for prefix

contact IBM Service. The error may occur when a DFS file set that had been registered to the Data Links Manager using "dlfm add_prefix" was subsequently deleted.


11.2 Setting Tivoli Storage Manager Class for Archive Files

To specify which TSM management class to use for the archive files, set the DLFM_TSM_MGMTCLASS DB2 registry entry to the appropriate management class name.


11.3 Disk Space Requirements for DFS Client Enabler

The DFS Client Enabler is an optional component that you can select during DB2 Universal Database client or server installation. You cannot install a DFS Client Enabler without installing a DB2 Universal Database client or server product, even though the DFS Client Enabler runs on its own without the need for a DB2 UDB client or server. In addition to the 2 MB of disk space required for the DFS Client Enabler code, you should set aside an additional 40 MB if you are installing the DFS Client Enabler as part of a DB2 Run-Time Client installation. You will need more disk space if you install the DFS Client Enabler as part of a DB2 Administration Client or DB2 server installation. For more information about disk space requirements for DB2 Universal Database products, refer to the DB2 for UNIX Quick Beginnings manual.


11.4 Monitoring the Data Links File Manager Back-end Processes on AIX

There has been a change to the output of the dlfm see command. When this command is issued to monitor the Data Links File Manager back-end processes on AIX, the output that is returned will be similar to the following:

     PID     PPID     PGID   RUNAME    UNAME        ETIME DAEMON NAME
   17500    60182    40838     dlfm     root        12:18 dlfm_copyd_(dlfm)
   41228    60182    40838     dlfm     root        12:18 dlfm_chownd_(dlfm)
   49006    60182    40838     dlfm     root        12:18 dlfm_upcalld_(dlfm)
   51972    60182    40838     dlfm     root        12:18 dlfm_gcd_(dlfm)
   66850    60182    40838     dlfm     root        12:18 dlfm_retrieved_(dlfm)
   67216    60182    40838     dlfm     dlfm        12:18 dlfm_delgrpd_(dlfm)
   60182        1    40838     dlfm     dlfm        12:18 dlfmd_(dlfm)
 
DLFM SEE request was successful.

The name that is enclosed within the parentheses is the name of the dlfm instance, in this case "dlfm".


11.5 Installing and Configuring DB2 Data Links Manger for AIX: Additional Installation Considerations in DCE-DFS Environments

In the section called "Installation prerequisites", there is new information that should be added:

   You must also install either an e-fix for DFS 3.1,
   or PTF set 1 (when it becomes available). The e-fix is available from:
 
   http://www.transarc.com/Support/dfs/datalinks/efix_dfs31_main_page.html

Also:

   The dfs client must be running before you install the Data Links Manager.
   Use db2setup or smitty.

In the section called "Keytab file", there is an error that should be corrected as:

   The keytab file, which contains the principal and password information,
   should be called datalink.ktb and ....

The example below this paragraph uses the correct name: datalink.ktb The "Keytab file" section should be moved under "DCE-DFS Post-Installation Task", because the creation of this file cannot occur until after the DLMADMIN instance has been created.

In the section called "Data Links File Manager servers and clients", it should be noted that the Data Links Manager server must be installed before any of the Data Links Manager clients.

A new section, "Backup directory", should be added:

   If the backup method is to a local file system,
   this must be a directory in the DFS file system.
   Ensure that this DFS file set has been created by a
   DFS administrator. This should not be a DMLFS file set.

11.6 Failed "dlfm add_prefix" Command

For a Data Links Manager running in the DCE/DFS environment, the dlfm add_prefix command might fail with a return code of -2061 (backup failed). If this occurs, perform the following steps:

  1. Stop the Data Links Manager daemon processes by issuing the dlfm stop command.
  2. Stop the DB2 processes by issuing the dlfm stopdbm command.
  3. Get dce root credentials by issuing the dce_login root command.
  4. Start the DB2 processes by issuing the dlfm startdbm command.
  5. Register the file set with the Data Links Manager by issuing the dlfm add_prefix command.
  6. Start the Data Links Manager daemon processes by issuing the dlfm start command.

11.7 Installing and Configuring DB2 Data Links Manger for AIX: Installing DB2 Data Links Manager on AIX Using the db2setup Utility

In the section "DB2 database DLFM_DB created", the DLFM_DB is not created in the DCE_DFS environment. This must be done as a post-installation step.

In the section "DCE-DFS pre-start registration for DMAPP", Step 2 should be changed to the following:

   2. Commands are added to /opt/dcelocal/tcl/user_cmd.tcl to
      ensure that the DMAPP is started when DFS is started.

11.8 Installing and Configuring DB2 Data Links Manager for AIX: DCE-DFS Post-Installation Task

The following new section, "Complete the Data Links Manager Install", should be added:

On the Data Links Manager server, the following steps must be performed to complete the installation:

  1. Create the keytab file as outlined under "Keytab file" in the section "Additional Installation Considerations in DCE-DFS Environment", in the chapter "Installing and Configuring DB2 Data Links Manger for AIX".
  2. As root, enter the following commands to start the DMAPP:
       stop.dfs all
       start.dfs all
    
  3. Run "dlfm setup" using dce root credentials as follows:
    1. Login as the Data Links Manager administrator, DLMADMIN.
    2. As root, issue dce_login.
    3. Enter the command: dlfm setup.

On the Data Links Manager client, the following steps must be performed to complete the installation:

  1. Create the keytab file as outlined under "Keytab file" in the section "Additional Installation Considerations in DCE-DFS Environment", in the chapter "Installing and Configuring DB2 Data Links Manger for AIX".
  2. As root, enter the following commands to start the DMAPP:
       stop.dfs all
       start.dfs all
    

11.9 Installing and Configuring DB2 Data Links Manager for AIX: Manually Installing DB2 Data Links Manager Using Smit

Under the section, "SMIT Post-installation Tasks", modify step 7 to indicate that the command "dce_login root" must be issued before "dlfm setup". Step 11 is not needed. This step is performed automatically when Step 6 (dlfm server_conf) or Step 8 (dlfm client_conf) is done. Also remove step 12 (dlfm start). To complete the installation, perform the following steps:

  1. Create the keytab file as outlined under "Keytab file" in the section "Additional Installation Considerations in DCE-DFS Environment", in the chapter "Installing and Configuring DB2 Data Links Manger for AIX".
  2. As root, enter the following commands to start the DMAPP:
       stop.dfs all
       start.dfs all
    

11.10 Installing and Configuring DB2 Data Links DFS Client Enabler

In the section "Configuring a DFS Client Enabler", add the following to Step 2:

   Performing the "secval" commands will usually complete the configuration.
   It may, however, be necessary to reboot the machine as well.
   If problems are encountered in accessing READ PERMISSION DB files,
   reboot the machine where the DB2 DFS Client Enabler has just been installed.

11.11 Choosing a Backup Method for DB2 Data Links Manager on AIX

In addition to Disk Copy and XBSA, you can also use Tivoli Storage Manager (TSM) for backing up files that reside on a Data Links server.

To use Tivoli Storage Manager as an archive server:

  1. Install Tivoli Storage Manager on the Data Links server. For more information, refer to your Tivoli Storage Manager product documentation.
  2. Register the Data Links server client application with the Tivoli Storage Manager server. For more information, refer to your Tivoli Storage Manager product documentation.
  3. Add the following environment variables to the Data Links Manager Administrator's db2profile or db2cshrc script files:
       (for Bash, Bourne, or Korn shell)
       export DSMI_DIR=/usr/lpp/tsm/bin
       export DSMI_CONFIG=$HOME/tsm/dsm.opt
       export DSMI_LOG=$HOME/dldump
       export PATH=$PATH:/usr/lpp/tsm/bin
     
       (for C shell)
       setenv DSMI_DIR /usr/lpp/tsm/bin
       setenv DSMI_CONFIG ${HOME}/tsm/dsm.opt
       setenv DSMI_LOG ${HOME}/dldump
       setenv PATH=${PATH}:/usr/lpp/tsm/bin
     
    
  4. Ensure that the dsm.sys TSM system options file is located in the /usr/lpp/tsm/bin directory.
  5. Ensure that the dsm.opt TSM user options file is located in the INSTHOME/tsm directory, where INSTHOME is the home directory of the Data Links Manager Administrator.
  6. Set the PASSWORDACCESS option to generate in the /usr/lpp/tsm/bin/dsm.sys Tivoli Storage Manager system options file.
  7. Register TSM password with the generate option before starting the Data Links File Manager for the first time. This way, you will not need to provide a password when the Data Links File Manager initiates a connection to the TSM server. For more information, refer to your TSM product documentation.
  8. Set the DLFM_BACKUP_TARGET registry variable to TSM. The value of DLFM_BACKUP_DIR_NAME registry variable will be ignored in this case. This will activate the Tivoli Storage Manager backup option.

    Notes:

    1. If you change the setting of the DLFM_BACKUP_TARGET registry variable between TSM and disk at run time, you should be aware that the archived files are not moved to the newly specified archive location. For example, if you start the Data Links File Manager with the DLMF_BACKUP_TARGET registry value set to TSM, and change the registry value to a disk location, all newly archived files will be stored in the new location on the disk. The files that were previously archived to TSM will not be moved to the new disk location.

    2. To override the default TSM management class there is a new registry variable called DLFM_TSM_MGMTCLASS. If this registry variable is left unset then the default TSM management class will be used.
  9. Stop the Data Links File Manager by entering the dlfm stop command.
  10. Start the Data Links File Manager by entering the dlfm start command.

11.12 Choosing a Backup Method for DB2 Data Links Manager on Windows NT

Whenever a DATALINK value is inserted into a table with a DATALINK column that is defined for recovery, the corresponding DATALINK files on the Data Links server are scheduled to be backed up to an archive server. Currently, Disk Copy (default method) and Tivoli Storage Manager are the two options that are supported for file backup to an archive server. Future releases of DB2 Data Links Manager for Windows NT will support other vendors' backup media and software.

Disk Copy (default method)

When the backup command is entered on the DB2 server, it ensures that the linked files in the database are backed up on the Data Links server to the directory specified by the DLFM_BACKUP_DIR_NAME environment variable. The default value for this variable is c:\dlfmbackup, where c:\ represents the Data Links Manager backup installation drive.

To set this variable to c:\dlfmbackup, enter the following command:

   db2set -g DLFM_BACKUP_DIR_NAME=c:\dlfmbackup
 
The location specified by the DLFM_BACKUP_DIR_NAME environment variable must not located on a file system using a Data Links Filesystem Filter and that the required space is available in the directory you specified for the backup files.

Also, ensure that the DLFM_BACKUP_TARGET variable is set to LOCAL by entering the following command:

   db2set -g DLFM_BACKUP_TARGET=LOCAL

After setting or changing these variables, stop and restart the Data Links File Manager using the dlfm stop and dlfm start commands.

Tivoli Storage Manager

To use Tivoli Storage Manager as an archive server:

  1. Install Tivoli Storage Manager on the Data Links server. For more information, refer to your Tivoli Storage Manager product documentation.
  2. Register the Data Links server client application with the Tivoli Storage Manager server. For more information, refer to your Tivoli Storage Manager product documentation.
  3. Click on Start and select Settings --> Control Panel --> System. The System Properties window opens. Select the Environment tab and enter the following environment variables and corresponding values:
    Variable Value
    DSMI_DIR c:\tsm\baclient
    DSMI_CONFIG c:\tsm\baclient\dsm.opt
    DSMI_LOG c:\tsm\dldump
  4. Ensure that the dsm.sys TSM system options file is located in the c:\tsm\baclient directory.
  5. Ensure that the dsm.opt TSM user options file is located in the c:\tsm\baclient directory.
  6. Set the PASSWORDACCESS option to generate in the c:\tsm\baclient\dsm.sys Tivoli Storage Manager system options file.
  7. Register TSM password with the generate option before starting the Data Links File Manager for the first time. This way, you will not need to provide a password when the Data Links File Manager initiates a connection to the TSM server. For more information, refer to your TSM product documentation.
  8. Set the DLFM_BACKUP_TARGET environment variable to TSM using the following command:
       db2set -g DLFM_BACKUP_TARGET=TSM
    

    The value of the DLFM_BACKUP_DIR_NAME environment variable will be ignored in this case. This will activate the Tivoli Storage Manager backup option.

    Notes:

    1. If you change the setting of the DLFM_BACKUP_TARGET environment variable between TSM and LOCAL at run time, you should be aware that the archived files are not moved to the newly specified archive location. For example, if you start the Data Links File Manager with the DLMF_BACKUP_TARGET environment variable set to TSM, and change its value to LOCAL, all newly archived files will be stored in the new location on the disk. The files that were previously archived to TSM will not be moved to the new disk location.

    2. To override the default TSM management class there is a new environment variable called DLFM_TSM_MGMTCLASS. If this variable is left unset then the default TSM management class will be used.
  9. Stop the Data Links File Manager by entering the dlfm stop command.
  10. Start the Data Links File Manager by entering the dlfm start command.

11.13 Backing up a Journalized File System on AIX

The book states that the Data Links Manager must be stopped, and that an offline backup should be made of the file system. The following approach, which removes the requirement of stopping the Data Links Manager, is suggested for users who require higher availability.

  1. Extract the attached (see below) CLI source file quiesce.c and the shell script online.sh.
  2. Compile quiesce.c:
       xlC -o quiesce  -L$HOME/sqllib/lib --I$HOME/sqllib/include -c quiesce.c
    
  3. Run the script on the node that has the DLFS file system.

The shell script online.sh assumes that you have a catalog entry on the Data Link Manager node for each database that is registered with the Data Link Manager. It also assumes that /etc/filesystem has the complete entry for the DLFS file system. The shell script does the following:

The script must be modified to suit your environment as follows:

  1. Select the backup command and put in the do_backup function of the script.
  2. Set the following environment variables within the script:

Invoke the script as follows:

   online.sh <filesystem_name>
------------------------- start of 'online.sh' script ----------------------
#!/bin/ksh
 
# Sample script for performing a filesystem backup without bringing it
# offline for most of the duration of the backup
# Some sections of the script need to be modified by the users to suit their
# specific needs including replacing some of the parameters with their own.
#  Usage: onlineb <filesystem name>
 
#The dlfs filesystem being backed up would remain accessible in read-only mode
#for most of the time that the filesystem backup is going on.
#For a short while in between it may be necessary to have all users off the 
#filesystem. This would be required at two points; the first, when switching 
#the filesystem to read-only (an unmount followed by re-mount as read-only) 
#and the second when switching it back to read-write (unmount again followed by 
#re-mount as read-write)
 
# Environment dependent variables ...
# To be changed according to needs ...
DLFM_INST=sharada
PATH_OF_EXEC=/home/sharada/amit
 
 
# Local environment variables.
EXEC=quiesce
DLFM_DB_NAME=dlfm_db
 
 
# Function to check if root
check_id()  {
if [ `id -u` -ne 0 ]
then
	echo "You need to be root to run this"
	exit 1
fi
}
 
#
# Function to quiesce the tables with Datalinks value in databases registered
# with DLFM_DB
#
quiesce_tables()  
{
    echo "Starting DB2 ..."
    su - $DLFM_INST "-c db2start | tail -n 1"  # Print just the last line
    su - $DLFM_INST "-c $PATH_OF_EXEC/$EXEC -q $DLFM_DB_NAME"
}
 
#
# Function to make the dlfs filesystem read-only 
#
# [The filesystem should not be in use during this time; no user should even
# have 'cd'-ied into the filesystem]
# 	- If the filesystem is NFS exported, unexport it
#
unexport_fs() {
    if exportfs | grep -w $filesystem_name 
    then
        echo $filesystem_name " is NFS exported"
        nfs_export_existed=1
        echo "Unexporting " $filesystem_name
        exportfs -u $filesystem_name
        result=$?
        if [ $result -ne 0 ]
        then
            echo "Failed to unexport " $filesystem_name
            reset_tables
            exit 1
        fi
    else
        echo $filesystem_name " is not NFS exported"
    fi
}
 
#
# Function to Unmount the filesystem
#
umount_fs() {
    echo "Unmounting " $filesystem_name
    umount $filesystem_name
    result=$?
    if [ $result -ne 0 ]
    then
        echo "Unable to unmount " $filesystem_name
        echo "Filesystem " $filesystem_name " may be in use"
        echo "Please make sure that no one is using the filesystem and"
        echo "and then press a key"
        read $ans 
        umount $filesystem_name
        result=$?
    fi	
    if [ $result -ne 0 ]
    then
        echo "Unable to unmount " $filesystem_name
        echo "Aborting ..."
        echo "Resetting the quiesced tables ..."
        reset_tables
        exit 1
    fi
	
    echo "Successfully unmounted " $filesystem_name
}	
 
#  
# Function to remount the same filesystem back as read-only or
# read-write depending on the value of "RO" variable.
#
remount_fs()
{
    if [ $RO -eq 1 ] 
    then
        echo "Now re-mounting " $filesystem_name " as read-only"
        mount -v dlfs -r $filesystem_name
    else
        echo "Now re-mounting " $filesystem_name " as read-write"
        mount -v dlfs $filesystem_name
    fi
    result=$?
    if [ $result -ne 0 ]
    then
        echo "Failed to remount " $filesystem_name 
        echo "Aborting ..."
        reset_tables
        exit 1
    fi
    echo "Successfully re-mounted " $filesystem_name " as read-only"
}
 
 
#  
# Function: If this was NFS exported, then export it a read-only now
#
make_fs_ro() {
    if [ $nfs_export_existed ]
    then
        echo "Re-exporting for NFS as read-only"
        chnfsexp -d $filesystem_name -N -t ro
        result=$?
        if [ $result -ne 0 ]
        then
            echo "Warning: Unable to NFS export " $filesystem_name
            # Not aborting here - continuing with a warning
            # at least the filesystem is available locally
            ## TBD: Or perhaps it would be better to exit 
        else
            echo "Successfully exported " $filesystem_name " as read-only"
        fi
    fi
}
 
 
#
# Function to do the backup.
# Update this function with the backup command that you want to use.
#
do_backup()  {
 
    echo "Initiating backup of " $filesystem_name
 
#  [ Add lines here to issue your favourite backup command with the right
#    parameters, or uncomment one of the following ]
 
#  To invoke backup via smit, uncomment the following line
#  	smit fs	#  Select Backup a Filesystem
 
#	OR
#  To issue the backup command directly, uncomment and modify the following
#  line with your own options (for example full/incremental) and the 
#  appropriate parameters (you might want to replace /dev/rmt0 by the name of 
#  your backup device)
#	/usr/sbin/backup -f'/dev/rmt0' -'0' $filesystem_name
#	result=$?
#	if [ $result -ne 0 ]
#	then
#		echo "Backup failed"
#		# Do we exit here ? Or cleanup ?
#	else
#		echo "Successful backup"
#	fi
 
#	OR
# Put in your own backup script here
#
}
 
 
#
# Function to remount the filesystem as read-write. And NFS export it, if it
# was NFS exported to start with.
export_fs()  {
    if [ $nfs_export_existed ]
    then
        echo "Exporting back for NFS as read-write"
        chnfsexp -d $filesystem_name -N -t rw 
        result=$?
        if [ $result -ne 0 ]
        then
            echo "Warning: Unable to NFS export " $filesystem_name
            # Not aborting here - continuing with a warning
            # at least the filesystem is available locally
            # TBD: Or perhaps it would be better to exit 
        else
            echo "Successfully exported " $filesystem_name " as read-write"
        fi
    fi
}
 
# Function to reset Quiesced tables
reset_tables()  {
  su - $DLFM_INST "-c $PATH_OF_EXEC/$EXEC -r $DLFM_DB_NAME"
}
 
 
#***************** MAIN PORTION  starts here ...*****************
 
#Check args
#
if [ $# -lt 1 ]
then
    echo "Usage: " $0 " <filesystem_name>"
    exit 1
fi
 
check_id
 
#  Quiesce tables ( after waiting for all transactions to get over ...)
quiesce_tables
 
# (i)  umount and remount the filesystem as read-only
 
filesystem_name=$1
unexport_fs
umount_fs
RO=1
remount_fs	  # READ_ONLY
make_fs_ro
 
# (ii) Start BackUp
 
do_backup
 
# (iii) unmount and remount the filesystem as read-write 
 
umount_fs
RO=0
remount_fs  # READ_WRITE
export_fs
 
# Reset all Quiesced tables ...
 
reset_tables
# Now the filesystem is ready for normal operation of Datalinks
echo "Done"
exit 0
------------------------- end of 'online.sh' script ------------------------
 
------------------------- start of 'quiesce.c' script ------------------------
/**********************************************************************
*
*  OCO SOURCE MATERIALS
*
*  COPYRIGHT:  P#2 P#1
*              (C) COPYRIGHT IBM CORPORATION Y1, Y2
*
*  The source code for this program is not published or otherwise divested of
*  its trade secrets, irrespective of what has been deposited with the U.S.
*  Copyright Office.
*
*  Source File Name = quiesce.c                                (%W%)
*
*  Descriptive Name = Quiesce or Reset tables.
*
*  Function:  It quiesces ( OR resets ) the tables ( with datalinks column ) of
*             the databases which are registered with DLFM_DB 
*
*                This program expects the databases registered with DLFM_DB are 
*                catalogued. It also expects that db2 is started.
*
*  Dependencies: 
*
*  Restrictions: 
*
***********************************************************************/
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sqlcli1.h>
#include <sqlutil.h>
#include <sqlca.h>
 
#define MAX_UID_LENGTH 20
#define MAX_PWD_LENGTH 20
#define MAXCOLS 255
 
struct sqlca sqlca;
struct SQLB_TBSPQRY_DATA *sqlb;
#ifndef max
  #define max(a,b) (a > b ? a : b)
#endif
 
 
#define CHECK_HANDLE( htype, hndl, RC ) if ( RC != SQL_SUCCESS ) \
   { check_error( htype, hndl, RC, __LINE__, __FILE__ ) ; }
 
SQLRETURN check_error( SQLSMALLINT, SQLHANDLE, SQLRETURN, int, char * ) ;
 
SQLRETURN DBconnect( SQLHANDLE, SQLHANDLE * ) ;
 
SQLRETURN print_error( SQLSMALLINT, SQLHANDLE, SQLRETURN, int, char * ) ;
 
SQLRETURN prompted_connect( SQLHANDLE, SQLHANDLE * ) ;
 
SQLRETURN terminate( SQLHANDLE, SQLRETURN ) ;
 
SQLCHAR server[SQL_MAX_DSN_LENGTH + 1] ;
SQLCHAR uid[MAX_UID_LENGTH + 1] ;
SQLCHAR pwd[MAX_PWD_LENGTH + 1] ;
 
/* check_error - calls print_error(), checks severity of return code */
 
SQLRETURN check_error( SQLSMALLINT htype, /* A handle type identifier */
             SQLHANDLE   hndl,  /* A handle */
             SQLRETURN   frc,   /* Return code to be included with error msg  */
             int         line,  /* Used for output message, indicate where    */
             char *      file   /* the error was reported from  */
           ) {
 
    print_error( htype, hndl, frc, line, file ) ;
 
    switch ( frc ) {
      case SQL_SUCCESS:
        break ;
      case SQL_INVALID_HANDLE:
        printf( "\n>------ ERROR Invalid Handle --------------------------\n");
      case SQL_ERROR:
        printf( "\n>--- FATAL ERROR, Attempting to rollback transaction --\n");
        if ( SQLEndTran( htype, hndl, SQL_ROLLBACK ) != SQL_SUCCESS )
           printf( ">Rollback Failed, Exiting application\n" ) ;
        else
           printf( ">Rollback Successful, Exiting application\n" ) ;
        return( terminate( hndl, frc ) ) ;
      case SQL_SUCCESS_WITH_INFO:
        printf( "\n> ----- Warning Message,
 application continuing ------- \n");
        break ;
      case SQL_NO_DATA_FOUND:
        printf( "\n> ----- No Data Found, application continuing --------- \n");
        break ;
      default:
        printf( "\n> ----------- Invalid Return Code --------------------- \n");
        printf( "> --------- Attempting to rollback transaction ---------- \n");
        if ( SQLEndTran( htype, hndl, SQL_ROLLBACK ) != SQL_SUCCESS )
           printf( ">Rollback Failed, Exiting application\n" ) ;
        else
           printf( ">Rollback Successful, Exiting application\n" ) ;
        return( terminate( hndl, frc ) ) ;
    }
 
    return ( frc ) ;
 
}
 
/* connect without prompt */
 
SQLRETURN DBconnect( SQLHANDLE henv,
                     SQLHANDLE * hdbc
                   ) {
 
    /* allocate a connection handle */
    if ( SQLAllocHandle( SQL_HANDLE_DBC,
                         henv,
                         hdbc
                       ) != SQL_SUCCESS ) {
        printf( ">---ERROR while allocating a connection handle-----\n" ) ;
        return( SQL_ERROR ) ;
    }
 
    /* Set AUTOCOMMIT OFF */
    if ( SQLSetConnectAttr( * hdbc,
                            SQL_ATTR_AUTOCOMMIT,
                            ( void * ) SQL_AUTOCOMMIT_OFF, SQL_NTS
                          ) != SQL_SUCCESS ) {
        printf( ">---ERROR while setting AUTOCOMMIT OFF ------------\n" ) ;
        return( SQL_ERROR ) ;
    }
 
    if ( SQLConnect( * hdbc,
                     server, SQL_NTS,
                     uid,    SQL_NTS,
                     pwd,    SQL_NTS
                   ) != SQL_SUCCESS ) {
        printf( ">--- Error while connecting to database: %s -------\n",
                server
              ) ;
        SQLDisconnect( * hdbc ) ;
        SQLFreeHandle( SQL_HANDLE_DBC, * hdbc ) ;
        return( SQL_ERROR ) ;
    }
    else      /* Print Connection Information */
        printf( "\nConnected to %s\n", server ) ;
 
    return( SQL_SUCCESS ) ;
 
}
 
 
/*--> SQLL1X32.SCRIPT */
/* print_error - calls SQLGetDiagRec(), displays SQLSTATE and message **
**             - called by check_error                                */
 
SQLRETURN print_error( SQLSMALLINT htype, /* A handle type identifier */
             SQLHANDLE   hndl,  /* A handle */
             SQLRETURN   frc,   /* Return code to be included with error msg  */
             int         line,  /* Used for output message, indicate where    */
             char *      file   /* the error was reported from  */
            ) {
 
    SQLCHAR     buffer[SQL_MAX_MESSAGE_LENGTH + 1] ;
    SQLCHAR     sqlstate[SQL_SQLSTATE_SIZE + 1] ;
    SQLINTEGER  sqlcode ;
    SQLSMALLINT length, i ;
 
    printf( ">--- ERROR -- RC = %d Reported from %s, line %d ------------\n",
            frc,
            file,
            line
          ) ;
 
    i = 1 ;
    while ( SQLGetDiagRec( htype,
                           hndl,
                           i,
                           sqlstate,
                           &sqlcode,
                           buffer,
                           SQL_MAX_MESSAGE_LENGTH + 1,
                           &length
                         ) == SQL_SUCCESS ) {
       printf( "         SQLSTATE: %s\n", sqlstate ) ;
       printf( "Native Error Code: %ld\n", sqlcode ) ;
       printf( "%s \n", buffer ) ;
       i++ ;
    }
 
    printf( ">--------------------------------------------------\n" ) ;
 
    return( SQL_ERROR ) ;
 
}
/*<-- */
 
 
/* prompted_connect - prompt for connect options and connect */
 
SQLRETURN prompted_connect( SQLHANDLE henv,
                            SQLHANDLE * hdbc
                          ) {
 
    /* allocate a connection handle     */
    if ( SQLAllocHandle( SQL_HANDLE_DBC,
                         henv,
                         hdbc
                       ) != SQL_SUCCESS ) {
        printf( ">---ERROR while allocating a connection handle-----\n" ) ;
        return( SQL_ERROR ) ;
    }
 
    /* Set AUTOCOMMIT OFF */
    if ( SQLSetConnectAttr( * hdbc,
                            SQL_ATTR_AUTOCOMMIT,
                            ( void * ) SQL_AUTOCOMMIT_OFF, SQL_NTS
                          ) != SQL_SUCCESS ) {
       printf( ">---ERROR while setting AUTOCOMMIT OFF ------------\n" ) ;
       return( SQL_ERROR ) ;
    }
 
    if ( SQLConnect( * hdbc,
                     server, SQL_NTS,
                     uid,    SQL_NTS,
                     pwd,    SQL_NTS
                   ) != SQL_SUCCESS ) {
        printf( ">--- ERROR while connecting to %s -------------\n",
                server
              ) ;
        
        SQLDisconnect( * hdbc ) ;
        SQLFreeHandle( SQL_HANDLE_DBC, * hdbc ) ;
        return( SQL_ERROR ) ;
    }
    else              /* Print Connection Information */
        printf( "\nConnected to %s\n", server ) ;
 
    return( SQL_SUCCESS ) ;
 
}
 
/* terminate and free environment handle */
 
SQLRETURN terminate( SQLHANDLE henv,
                     SQLRETURN rc
                   ) {
 
    SQLRETURN lrc ;
 
    printf( ">Terminating ....\n" ) ;
    print_error( SQL_HANDLE_ENV,
                 henv,
                 rc,
                 __LINE__,
                 __FILE__
               ) ;
 
    /* Free environment handle */
    if ( ( lrc = SQLFreeHandle( SQL_HANDLE_ENV, henv ) ) != SQL_SUCCESS )
       print_error( SQL_HANDLE_ENV,
                    henv,
                    lrc,
                    __LINE__,
                    __FILE__
                  ) ;
 
    return( rc ) ;
 
}
void show_progress()
        {
        int i;
        for(i=0;i<3;i++)
        {
        printf("...");
/*        sleep(1);*/
        }
        printf("...  DONE.\n");
        }
void wrong_input(char *str)
        {
         printf("\n\n\t****************************************************************\n");
             printf("\t*   usage:  %s -q <DB-NAME> ( to Quiesce tables ..)       *\n",str);
             printf("\t*                         OR                                    *\n");
             printf("\t*   usage:  %s -r <DB-NAME> ( to reset Quiesced tables ..)*\n",str);
             printf("\t****************************************************************\n\n\n");
                
         exit(0);
        }
 
extern SQLCHAR server[SQL_MAX_DSN_LENGTH + 1] ;
extern SQLCHAR uid[MAX_UID_LENGTH + 1] ;
extern SQLCHAR pwd[MAX_PWD_LENGTH + 1] ;
 
#define MAX_STMT_LEN 500
 
int        reset=-1;
 
/*******************************************************************
** main 
*******************************************************************/
 
int main( int argc, char * argv[] ) {
 
    SQLHANDLE henv,hdbc[3], hstmt,hstmt1,hstmt2 ;
    SQLRETURN rc ;
 
    SQLCHAR * sqlstmt = ( SQLCHAR * ) "SELECT dbname,dbinst,password from dfm_dbid" ;/* for the primary db */
    SQLCHAR * stmt = ( SQLCHAR * ) "SELECT COLS.TBCREATOR, COLS.TBNAME FROM SYSIBM.SYSCOLUMNS COLS, "
          " SYSIBM.SYSCOLPROPERTIES PROPS WHERE COLS.TBCREATOR = PROPS.TABSCHEMA AND "
          " COLS.TBNAME = PROPS.TABNAME AND  COLS.TYPENAME='DATALINK' AND  SUBSTR(PROPS.DL_FEATURES, 2, 1) "
          " = 'F' GROUP BY COLS.TBCREATOR, COLS.TBNAME";/*test for the secondary db's*/
    SQLCHAR * stmt2 = ( SQLCHAR * ) "SELECT count(*) from dfm_xnstate where xn_state=3" ;/* for the primary db */
 
    SQLCHAR v_dbname[20] ;
    SQLINTEGER v_xnstate ;
    SQLCHAR v_usernm[20] ;
    SQLCHAR v_passwd[20] ;
    SQLINTEGER nullind;
    SQLVARCHAR v_tbname[128];
    SQLCHAR v_tbcreator[20];
    SQLINTEGER rowcount;
    int i,count;
    char state[6],v_tb[100];
    int flag=0;
    int xxx,tong=0;
 
    if( (argc != 2 && argc!=3)  || argv[1][0]!='-' || strlen(argv[1]) !=2) wrong_input(argv[0]);
 
/***  NOTE :   If argc==2 then DB-NAME the program would ask user to enter
 DB-Name else it would take the second argument to this program ( argv[2] )
 as DB-NAME ***/ 
 
 
if(argv[1][1]=='q' || argv[1][1]=='Q')
{
    reset=0;
}
else
{
    if(argv[1][1]!='r' || argv[1][1]!='R')
    {
      reset=1;
    }
    else
    {
      wrong_input(argv[0]);
    }
    if(reset==-1) wrong_input(argv[0]);
}
 
 
    SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv ) ;
        
        /*
     Before allocating any connection handles, set Environment wide
     Connect Options
     Set to Connect Type 2, Syncpoint 1
    */
    if ( SQLSetEnvAttr( henv,
                        SQL_CONNECTTYPE,
                        ( SQLPOINTER ) SQL_COORDINATED_TRANS,
                        0
                      ) != SQL_SUCCESS ) {
       printf( ">---ERROR while setting Connect Type 2 -------------\n" ) ;
       return( SQL_ERROR ) ;
    }
/*<-- */
/*--> */
    if ( SQLSetEnvAttr( henv,
                        SQL_SYNC_POINT,
                        ( SQLPOINTER ) SQL_ONEPHASE,
                        0
                      ) != SQL_SUCCESS ) {
       printf( ">---ERROR while setting Syncpoint One Phase -------------\n" ) ;
       return( SQL_ERROR ) ;
    }
        
        if(argc==3)
        {
                strcpy(server,argv[2]);
        }
        else
        {
                printf( ">Enter database Name:\n" ) ;
                gets( ( char * ) server ) ;
        }
 
 
        /*prompted_connect(henv,&hdbc[0]);*/
 
 
    /* allocate an environment handle */
    rc = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv ) ;
    if ( rc != SQL_SUCCESS ) return( terminate( henv, rc ) ) ;
 
    /* allocate a connect handle, and connect to the primary database*/
    
        rc = DBconnect( henv, &hdbc[0] ) ;
    if ( rc != SQL_SUCCESS ) return( terminate( henv, rc ) ) ;
 
 
        flag=1;
        if(reset!=1)
        {
        printf("\nWaiting for XNs to get over ...");
        while(flag)                         /* Outer While */
        {
        
        rc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc[0], &hstmt2 ) ;
    CHECK_HANDLE( SQL_HANDLE_DBC, hdbc[0], rc ) ;
 
        
    rc = SQLExecDirect( hstmt2, stmt2, SQL_NTS ) ;
    CHECK_HANDLE( SQL_HANDLE_STMT, hstmt, rc ) ;
        
 
        
        rc = SQLBindCol( hstmt2, 1, SQL_C_LONG, &v_xnstate, 0, &nullind) ;
    CHECK_HANDLE( SQL_HANDLE_STMT, hstmt2, rc ) ;
 
        while ( ( rc = SQLFetch( hstmt2 ) ) == SQL_SUCCESS )
        {
                /*printf( "\nCount of XNs Pending : %d \n",v_xnstate) ;*/
                
                if (v_xnstate > 0)
                {
                fflush(stdout);
                printf(".");
                        sleep(1);
                        break;
                }
                else flag=0;
                
        }  /* Inner While */
        
        /* Deallocation */
 
                rc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt2 ) ;
                CHECK_HANDLE( SQL_HANDLE_STMT, hstmt2, rc ) ;
 
                
        }  /* Outer While */
        } /*  IF */
 
        if(!reset) printf("XNs OVER !!\n");
 
 
    rc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc[0], &hstmt ) ;
    CHECK_HANDLE( SQL_HANDLE_DBC, hdbc[0], rc ) ;
 
    rc = SQLExecDirect( hstmt, sqlstmt, SQL_NTS ) ;
    CHECK_HANDLE( SQL_HANDLE_STMT, hstmt, rc ) ;
 
    rc = SQLBindCol( hstmt, 1, SQL_C_CHAR, v_dbname, sizeof(v_dbname), NULL) ;
    CHECK_HANDLE( SQL_HANDLE_STMT, hstmt, rc ) ;
 
    rc = SQLBindCol( hstmt, 2, SQL_C_CHAR, v_usernm, sizeof(v_usernm), NULL) ;
    CHECK_HANDLE( SQL_HANDLE_STMT, hstmt, rc ) ;
        v_passwd[0]='\0';
 
 
    rc = SQLBindCol( hstmt, 3, SQL_C_CHAR, v_passwd, sizeof(v_passwd), NULL) ;
    CHECK_HANDLE( SQL_HANDLE_STMT, hstmt, rc ) ;
 
    
    
    /* Counter for number of rows fetched from the primary db*/
    count=1;
        
    for (i=1;i<=count;i++)  /* For the FOR LOOP */
    {                                        
        while ( ( rc = SQLFetch( hstmt ) ) == SQL_SUCCESS )
        {
            printf( "\nDatabase Name : %s \n",v_dbname) ;
 
            count=count+1;                
            /* Depending on the no. of rows fetched from the primary db connect to the sec db's */
 
 
            if ( SQLAllocHandle( SQL_HANDLE_DBC,henv,&hdbc[i]) != SQL_SUCCESS ) 
            {
                printf(">---ERROR while allocating a connection handle-----\n");
                return( SQL_ERROR ) ;
            }
 
    /* Set AUTOCOMMIT ON */
            if ( SQLSetConnectAttr( * hdbc,SQL_ATTR_AUTOCOMMIT,( void * ) SQL_AUTOCOMMIT_ON, SQL_NTS) != SQL_SUCCESS ) 
            {
                printf(">---ERROR while setting AUTOCOMMIT OFF ------------\n");
                return( SQL_ERROR ) ;
            }
 
 
            rc = SQLConnect(hdbc[i],v_dbname,SQL_NTS,((v_passwd[0]=='\0') ? NULL : v_usernm),SQL_NTS,v_passwd,SQL_NTS);
            if ( rc != SQL_SUCCESS ) return( terminate( henv, rc ) ) ;
 
            /* tRYING OUT FOR SELECTION FROM THESE DB'S*/
 
            rc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc[i], &hstmt1 ) ;
            CHECK_HANDLE( SQL_HANDLE_DBC, hdbc[i], rc ) ;
 
            rc = SQLExecDirect( hstmt1, stmt, 276 ) ;
            CHECK_HANDLE( SQL_HANDLE_STMT, hstmt1, rc ) ;
 
            rc = SQLBindCol( hstmt1, 1, SQL_C_CHAR, v_tbcreator, sizeof(v_tbcreator), NULL) ;
            CHECK_HANDLE( SQL_HANDLE_STMT, hstmt1, rc ) ;
 
            rc = SQLBindCol( hstmt1, 2, SQL_C_CHAR, v_tbname, sizeof(v_tbname), NULL) ;
            CHECK_HANDLE( SQL_HANDLE_STMT, hstmt1, rc ) ;
 
 
 
            while ( ( rc = SQLFetch( hstmt1 ) ) == SQL_SUCCESS )
            {
 
                v_tb[0]= '\0';
                strcat(v_tb,v_tbcreator);
                strcat(v_tb,".");
                strcat(v_tb,v_tbname);
                printf("\tTABLE : %s ",v_tb);
                sqluvqdp (v_tb,(reset==1) ? 9 : 2, NULL, &sqlca); 
        
        /** 9 -> to RESET        2 -> to Quiesce ( exclusive) */
                
                if (sqlca.sqlcode==0)
                {
                    if (reset==1)
                    {
                     /* printf("The quiesced tablespace successfully reset.\n");        */
                        show_progress();
                    }
                    else
                    {
            /*          printf("The tablespace successfully quiesced\n");*/
                        show_progress();
                    }
                }
                else if (sqlca.sqlcode== -3805 ||sqlca.sqlcode==01004)
                {
 
                    if(reset==1)
                    {
                    /*  printf("The quiesced tablespace could not be reset.\n");*/
                        show_progress();
                    }
                    else
                    {
            /*        printf("The tablespace has already been quiesced\n");*/
                        show_progress();
                    }
 
                }
                else
                {
                    if(reset==1)
                    {
                      printf("The quiesced tablespace could not be reset.\n");
                    }
                    else
                    {
                        printf("The tablespace could not be quiesced. \n");
                    }
 
                printf("\t\tSQLCODE = %ld\n", sqlca.sqlcode);
                strncpy(state, sqlca.sqlstate, 5);
                state[5] = '\0';
                printf("\t\tSQLSTATE = %s\n", state);
                }
              }
 
                rc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt1 ) ;
                CHECK_HANDLE( SQL_HANDLE_STMT, hstmt1, rc ) ;
 
                rc = SQLDisconnect( hdbc[i] );
                CHECK_HANDLE( SQL_HANDLE_DBC, hdbc[i], rc ) ;
        
                rc = SQLFreeHandle( SQL_HANDLE_DBC, hdbc[i] ) ;
                CHECK_HANDLE( SQL_HANDLE_DBC, hdbc[i], rc ) ;
 
        }
                
        
    } 
 
    printf("The NO. of DATABASES is %d \n",count-1);
 
 
    if ( rc != SQL_NO_DATA_FOUND )
    CHECK_HANDLE( SQL_HANDLE_STMT, hstmt, rc ) ;
 
    /*  Commit the changes.  */
    rc = SQLEndTran( SQL_HANDLE_DBC, hdbc[0], SQL_COMMIT ) ;
    CHECK_HANDLE( SQL_HANDLE_DBC, hdbc[0], rc ) ;
 
 
    /*  Disconnect and free up CLI resources.  */
    rc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ;
    CHECK_HANDLE( SQL_HANDLE_STMT, hstmt, rc ) ;
 
 
 
  /* ******************************************************/
 
    printf( "\n>Disconnecting .....\n" ) ;
    rc = SQLDisconnect( hdbc[0] );
    CHECK_HANDLE( SQL_HANDLE_DBC, hdbc[0], rc ) ;
 
    rc = SQLFreeHandle( SQL_HANDLE_DBC, hdbc[0] ) ;
    CHECK_HANDLE( SQL_HANDLE_DBC, hdbc[0], rc ) ;
 
    /**********************************************************/
 
    rc = SQLFreeHandle( SQL_HANDLE_ENV,  henv ) ;
    if ( rc != SQL_SUCCESS ) return( terminate( henv, rc ) ) ;
        
    return( SQL_SUCCESS ) ;
 
}                                  /* end main */
------------------------- end of 'quiesce.c' script ------------------------


[ Top of Page | Previous Page | Next Page | Table of Contents ]