/*******************************************************************************
**
** Source File Name = backrest.c  1.4
**
** Licensed Materials - Property of IBM
**
** (C) COPYRIGHT International Business Machines Corp. 1995, 1999 
** All Rights Reserved.
**
** US Government Users Restricted Rights - Use, duplication or
** disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
**
**    PURPOSE :
**       an example showing how to use BACKUP & RESTORE APIs in order to:
**          - backup a database
**          - restore a database
**          - ROLL FORWARD DATABASE to return the database to a state it was
**            in prior to the damage...
**
**    APIs USED :
**       BACKUP DATABASE                   sqlubkp()
**       RESTORE DATABASE                  sqlurestore()
**       UPDATE DATABASE CONFIGURATION     sqlfudb()
**       GET TABLESPACE CONTAINER QUERY    sqlbtcq()
**       SET TABLESPACE CONTAINERS         sqlbstsc()
**       ROLL FORWARD DATABASE             sqluroll()
**
**    STRUCTURES USED :
**       sqlu_tablespace_bkrst_list
**       SQLB_TBSCONTQRY_DATA
**       sqlu_media_list
**       rfwd_input
**       rfwd_output
**       sqlurf_info
**       sqlca
**
**    OTHER FUNCTIONS DECLARED :
**       'C' COMPILER LIBRARY :
**          stdio.h  -  printf
**
**       internal :
**
**       external :
**          check_error :     Checks for SQLCODE error, and prints out any
**          [in util.c]          related information available.
**                               This procedure is located in the util.c file.
**
**    EXTERNAL DEPENDENCIES :
**       - Ensure existence of database for precompile purposes.
**       - Compile and link with the IBM Cset++ compiler (AIX and OS/2)
**         or the Microsoft Visual C++ compiler (Windows) 
**         or the compiler supported on your platform.
**
** For more information about these samples see the README file.
**
** For more information on programming in C, see the:
**   -  "Programming in C and C++" section of the Application Development Guide
** For more information on Building C Applications, see the:
**   -  "Building C Applications" section of the Application Building Guide.
**
** For more information on the SQL language see the SQL Reference.
**
*******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlutil.h>
#include <sqlenv.h>
#include "util.h"

#define  CHECKERR(CE_STR)   if (check_error (CE_STR, &sqlca) != 0) return 1;

/* You can change the following path to another directory for which */
/* you have permission. create the "backup" directory in the same path. */

   #define TEMPDIR "."

int main (int argc, char *argv[]) {

   /* Variables for the BACKUP API */
   unsigned long buff_size;
   unsigned long num_buff;
   struct sqlu_tablespace_bkrst_list *tablespace_list;
   struct SQLB_TBSCONTQRY_DATA *cont;
   struct sqlca sqlca;
   struct sqlu_media_entry media_entry;
   struct sqlu_media_list media_list;
   char applid[SQLU_APPLID_LEN+1];
   char timestamp[SQLU_TIME_STAMP_LEN+1];
   char *target_path;

   unsigned long tsc_id;
   unsigned long num_cont;

   /* variables for the Update Database Configuration API */
   struct sqlfupd itemList;
   short log_retain;

   /* variables for the ROLL FORWARD API */
   struct rfwd_input rfwdInput;
   char dbAlias[] = "TESTBACK";
   char overFlowLogPath[SQL_PATH_SZ] = TEMPDIR;

   struct rfwd_output rfwdOutput;
   long   numReplies;
   struct sqlurf_info nodeInfo;

   printf ("\nThis is sample program : backrest.c\n\n");
 
   printf ("NOTE:   Ensure the database is not in use prior to running this program.\n\n");

   if (argc != 4) {
      printf ("\nUSAGE: backrest database userID password\n\n");
      return 1;
   } /* endif */

   /* Altering the default Database Configuration to enable roll-forward
      recovery of the TESTBACK database. */

   log_retain = 1;
   itemList.token = SQLF_DBTN_LOG_RETAIN;
 
   itemList.ptrvalue = (char *) &log_retain;


   printf ("Updating the %s database configuration parameter LOGRETAIN \n", argv[1]);   
   printf ("to 'ON' to enable roll-forward recovery.\n\n");

   /******************************************\
   * UPDATE DATABASE CONFIGURATION API called *
   \******************************************/
   sqlfudb(argv[1], 1, &itemList, &sqlca);
   CHECKERR("updating the database configuration");



  /* Initialize the BACKUP API variables */
   buff_size = 16;
   num_buff = 1;
   tablespace_list = NULL;
   media_list.media_type = 'L';
   media_list.sessions = 1;

   strcpy (media_entry.media_entry, TEMPDIR);

   media_list.target.media = &media_entry;
   printf ("Backing up the '%s' database.\n", argv[1]);
   /*****************\
   * BACKUP DATABASE *
   \*****************/
   sqlubkp (argv[1],
             buff_size,
             SQLUB_OFFLINE,
             SQLUB_FULL,
             SQLUB_BACKUP,
             applid,
             timestamp,
             num_buff,
             tablespace_list,
             &media_list,
             argv[2],
             argv[3],
             NULL,
             0,
             NULL,
             1,
             NULL,
             NULL, 
             NULL,
             &sqlca);

   CHECKERR ("backing up the database");
   printf ("The database has been successfully backed up.\n\n");


   
   /* Altering the default Database Configuration to disable roll-forward
      recovery of the TESTBACK database. */

   log_retain = 0;
   itemList.token = SQLF_DBTN_LOG_RETAIN;
   itemList.ptrvalue = (char *) &log_retain;


   printf ("Updating the %s database configuration parameter LOGRETAIN \n", argv[1]);   
   printf ("to 'OFF'.\n\n");

   /******************************************\
   * UPDATE DATABASE CONFIGURATION API called *
   \******************************************/
   sqlfudb(argv[1], 1, &itemList, &sqlca);
   CHECKERR("updating the database configuration");



   
   /* Initialize the variables for the RESTORE API */
   buff_size = 1024;
   target_path = NULL;
   printf ("Restoring the database '%s' as 'TESTBACK' (1st pass).\n", argv[1]);
   printf ("Should get returned value = SQLUD_INACCESSABLE_CONTAINER.\n");
   /******************\
   * RESTORE DATABASE *
   \******************/
   sqlurestore(argv[1],
             "TESTBACK",
             buff_size,
             SQLUD_ROLLFWD,
             SQLUD_DATALINK,
             SQLUD_FULL,
             SQLUD_OFFLINE,
             SQLUD_RESTORE_STORDEF,
             applid,
             timestamp,
             target_path,
             num_buff,
             NULL,
             tablespace_list,
             &media_list,
             argv[2],
             argv[3],
             NULL,
             0,
             NULL,
             1,
             NULL,
             NULL,
             NULL,
             &sqlca);
   if (sqlca.sqlcode != SQLUD_INACCESSABLE_CONTAINER)
      CHECKERR ("restoring database");

   printf ("SQLUD_INACCESSABLE_CONTAINER is returned.\n\n");
   printf ("Need to SET TABLESPACES CONTAINERS\n");
   /* Set the containers structure to a new list of containers */
   tsc_id = 1;
   cont = (struct SQLB_TBSCONTQRY_DATA *) malloc
      (sizeof(struct SQLB_TBSCONTQRY_DATA));

   /********************************\
   * GET TABLESPACE CONTAINER QUERY *
   \********************************/
   sqlbtcq (&sqlca, tsc_id, &num_cont, &cont);
   CHECKERR ("GET TABLESPACE CONTAINER QUERY");
   printf ("Tablespace container information for tablespace 1 obtained.\n");
   /***************************\
   * SET TABLESPACE CONTAINERS *
   \***************************/
   sqlbstsc (&sqlca,
             SQLB_SET_CONT_INIT_STATE,
             tsc_id,
             num_cont,
             cont);
   CHECKERR ("SET TABLESPACE CONTAINERS");
   printf ("Tablespace containers have been set for tablespace 1.\n\n");

   printf ("Restoring the database '%s' as 'TESTBACK' (2nd pass).\n", argv[1]);
   /******************\
   * RESTORE DATABASE *
   \******************/
   sqlurestore (argv[1],
             "TESTBACK",
             buff_size,
             SQLUD_ROLLFWD,
             SQLUD_DATALINK,
             SQLUD_FULL,
             SQLUD_OFFLINE,
             SQLUD_CONTINUE,
             applid,
             timestamp,
             target_path,
             num_buff,
             NULL,
             tablespace_list,
             &media_list,
             argv[2],
             argv[3],
             NULL,
             0,
             NULL,
             1,
             NULL,
             NULL,
             NULL,
             &sqlca);
   CHECKERR ("restoring database 2");
   printf ("Database %s has been restored as 'TESTBACK'.\n\n", argv[1]);


   /***********************\
   * ROLL FORWARD DATABASE *
   \***********************/
   rfwdInput.version=SQLUM_RFWD_VERSION;
   rfwdInput.pDbAlias=dbAlias;
   rfwdInput.CallerAction=SQLUM_ROLLFWD;
   rfwdInput.pStopTime=SQLUM_INFINITY_TIMESTAMP;
   rfwdInput.pUserName=argv[2];
   rfwdInput.pPassword=argv[3];
   rfwdInput.pOverflowLogPath=overFlowLogPath;
   rfwdInput.NumChngLgOvrflw=0;
   rfwdInput.pChngLogOvrflw=NULL;
   rfwdInput.ConnectMode=SQLUM_OFFLINE;
   rfwdInput.pTablespaceList=NULL;
   rfwdInput.AllNodeFlag= SQLURF_ALL_NODES;
   rfwdInput.NumNodes=0;
   rfwdInput.pNodeList=NULL;
   rfwdInput.NumNodeInfo=1;
   rfwdInput.DlMode=0;
   rfwdInput.pReportFile=NULL;
   rfwdInput.pDroppedTblID=NULL;
   rfwdInput.pExportDir=NULL;


   rfwdOutput.pApplicationId=applid;  
   rfwdOutput.pNumReplies=&numReplies;
   rfwdOutput.pNodeInfo=&nodeInfo;


   sqluroll( &rfwdInput,
             &rfwdOutput,
             &sqlca);
   CHECKERR ("rolling forward database");
   printf ("The database 'TESTBACK' has been successfully rolled forward.\n\n", argv[1]);


   /***************\
   * DROP DATABASE *
   \***************/
   sqledrpd ("TESTBACK",
             &sqlca);
   CHECKERR ("DROP DATABASE");
   printf ("The database 'TESTBACK' has been successfully dropped.\n");


   return 0;
}