/****************************************************************************
** (c) Copyright IBM Corp. 2007 All rights reserved.
** 
** The following sample of source code ("Sample") is owned by International 
** Business Machines Corporation or one of its subsidiaries ("IBM") and is 
** copyrighted and licensed, not sold. You may use, copy, modify, and 
** distribute the Sample in any form without payment to IBM, for the purpose of 
** assisting you in the development of your applications.
** 
** The Sample code is provided to you on an "AS IS" basis, without warranty of 
** any kind. IBM HEREBY EXPRESSLY DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR 
** IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Some jurisdictions do 
** not allow for the exclusion or limitation of implied warranties, so the above 
** limitations or exclusions may not apply to you. IBM shall not be liable for 
** any damages you suffer as a result of using, copying, modifying or 
** distributing the Sample, even if IBM has been advised of the possibility of 
** such damages.
*****************************************************************************
**
** SOURCE FILE NAME: dbrestore.sqc
**
** SAMPLE: How to restore a database from a backup
**
**         This program ends in ".sqc" even though it does not contain
**         embedded SQL statements. It links in  the embedded SQL utility
**         file for database connection and disconnection, so it needs the
**         embedded SQL extension for the precompiler.
**
**         Note:
**           You must be disconnected from the sample database to run
**           this program. To ensure you are, enter 'db2 connect reset'
**           on the command line prior to running dbrestore. 
**
** DB2 API USED:
**         db2Backup -- Backup Database
**         db2CfgSet -- Set Configuration
**         db2Restore -- Restore Database
**
**                           
*****************************************************************************
**
** For detailed information about database backup and database recovery, see
** the Data Recovery and High Availability Guide and Reference. This manual
** will help you to determine which database and table space recovery methods
** are best suited to your business environment.
**
** For more information on the sample programs, see the README file.
**
** For information on developing embedded SQL applications see the Developing Embedded SQL Applications book.
**
** For information on using SQL statements, see the SQL Reference.
**
** For information on DB2 APIs, see the Administrative API Reference.
**
** For the latest information on programming, building, and running DB2
** applications, visit the DB2 Information Center:
**     http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp
****************************************************************************/
#include "utilrecov.c"

/* local function prototypes */
int DbBackupAndRestore(char *, char *, char *, char *, char *);

int main(int argc, char *argv[])
{
  int rc = 0;
  char nodeName[SQL_INSTNAME_SZ + 1] = { 0 };
  char serverWorkingPath[SQL_PATH_SZ + 1] = { 0 };
  sqluint16 savedLogRetainValue = 0;
  char restoredDbAlias[SQL_ALIAS_SZ + 1] = { 0 };
  char dbAlias[SQL_ALIAS_SZ + 1] = { 0 };
  char user[USERID_SZ + 1] = { 0 };
  char pswd[PSWD_SZ + 1] = { 0 };

  /* check the command line arguments */
  rc = CmdLineArgsCheck3(argc, argv, dbAlias, nodeName, user, pswd);
  CHECKRC(rc, "CmdLineArgsCheck3");

  printf("\nTHIS SAMPLE SHOWS HOW TO RESTORE A DATABASE FROM A\n");
  printf("BACKUP.\n");

  strcpy(restoredDbAlias, dbAlias);

  /* attach to a local or remote instance */
  rc = InstanceAttach(nodeName, user, pswd);
  CHECKRC(rc, "Instance Attach");

  /* get the server working path */
  rc = ServerWorkingPathGet(dbAlias, serverWorkingPath);
  CHECKRC(rc, "ServerWorkingPathGet");

  printf("\nNOTE: Backup images will be created on the server\n");
  printf("        in the directory %s,\n", serverWorkingPath);
  printf("        and will not be deleted by the program.\n");

  /* save log retain value */
  rc = DbLogRetainValueSave(dbAlias, &savedLogRetainValue);
  CHECKRC(rc, "DbLogRetainValueSave");

  /* prune the recovery history file */
  rc = DbRecoveryHistoryFilePrune(dbAlias, user, pswd);
  CHECKRC(rc, "DbRecoveryHistoryFilePrune");

  /* call the function to backup and restore the database */
  rc = DbBackupAndRestore(dbAlias,
                          restoredDbAlias, user, pswd, serverWorkingPath);
  CHECKRC(rc, "DbBackupAndRestore");

  /* restore logretain value */
  rc = DbLogRetainValueRestore(dbAlias, &savedLogRetainValue);
  CHECKRC(rc, "DbLogRetainValueRestore");

  /* detach from the local or remote instance */
  rc = InstanceDetach(nodeName);
  CHECKRC(rc, "InstanceDetach");

  return 0;
} /* end main */

int DbBackupAndRestore(char dbAlias[],
                       char restoredDbAlias[], char user[], 
                       char pswd[], char serverWorkingPath[])
{
  int rc = 0;
  struct sqlca sqlca = { 0 };
  db2CfgParam cfgParameters[1] = { 0 };
  db2Cfg cfgStruct = { 0 };
  unsigned short logretain = 0;
  char restoreTimestamp[SQLU_TIME_STAMP_LEN + 1] = { 0 };

  db2BackupStruct backupStruct = { 0 };
  db2TablespaceStruct tablespaceStruct = { 0 };
  db2MediaListStruct mediaListStruct = { 0 };
  db2Uint32 backupImageSize = 0;
  db2RestoreStruct restoreStruct = { 0 };
  db2TablespaceStruct rtablespaceStruct = { 0 };
  db2MediaListStruct rmediaListStruct = { 0 };

  printf("\n**************************************\n");
  printf("*** BACK UP AND RESTORE A DATABASE ***\n");
  printf("**************************************\n");
  printf("\nUSE THE DB2 APIs:\n");
  printf("  db2CfgSet -- Set Configuration\n");
  printf("  db2Backup -- Backup Database\n");
  printf("  db2Restore -- Restore Database\n");
  printf("TO BACK UP AND RESTORE A DATABASE.\n");

  printf("\n  Update \'%s\' database configuration:\n", dbAlias);
  printf("    - Disable the database configuration parameter LOGRETAIN\n");
  printf("        i.e., set LOGRETAIN = OFF/NO\n");

  /* initialize cfgParameters */
  /* SQLF_DBTN_LOG_RETAIN is a token of the updatable database configuration
     parameter 'logretain'; it is used to update the database configuration
     file */
  cfgParameters[0].flags = 0;
  cfgParameters[0].token = SQLF_DBTN_LOG_RETAIN;
  cfgParameters[0].ptrvalue = (char *)&logretain;

  /* disable the database configuration parameter 'logretain' */
  logretain = SQLF_LOGRETAIN_DISABLE;

  /* initialize cfgStruct */
  cfgStruct.numItems = 1;
  cfgStruct.paramArray = cfgParameters;
  cfgStruct.flags = db2CfgDatabase | db2CfgDelayed;
  cfgStruct.dbname = dbAlias;

  /* set database configuration */
  db2CfgSet(db2Version970, (void *)&cfgStruct, &sqlca);
  DB2_API_CHECK("Db Log Retain -- Disable");

  /******************************/
  /*    BACKUP THE DATABASE    */
  /******************************/

  /* Calling up the routine for database backup */ 
  rc = DbBackup(dbAlias, user, pswd, serverWorkingPath, &backupStruct);
  CHECKRC(rc, "DbBackup");

  /******************************/
  /*    RESTORE THE DATABASE    */
  /******************************/

  strcpy(restoreTimestamp, backupStruct.oTimestamp);

  printf("\n  Restoring a database ...\n");
  printf("    - source image alias     : %s\n", dbAlias);
  printf("    - source image time stamp: %s\n", restoreTimestamp);
  printf("    - target database        : %s\n", restoredDbAlias);

  rtablespaceStruct.tablespaces = NULL;
  rtablespaceStruct.numTablespaces = 0;

  rmediaListStruct.locations = &serverWorkingPath;
  rmediaListStruct.numLocations = 1;
  rmediaListStruct.locationType = SQLU_LOCAL_MEDIA;

  restoreStruct.piSourceDBAlias = dbAlias;
  restoreStruct.piTargetDBAlias = restoredDbAlias;

  restoreStruct.piTimestamp = restoreTimestamp;
  restoreStruct.piTargetDBPath = NULL;
  restoreStruct.piReportFile = NULL;
  restoreStruct.piTablespaceList = &rtablespaceStruct;
  restoreStruct.piMediaList = &rmediaListStruct;
  restoreStruct.piUsername = user;
  restoreStruct.piPassword = pswd;
  restoreStruct.piNewLogPath = NULL;
  restoreStruct.piVendorOptions = NULL;
  restoreStruct.iVendorOptionsSize = 0;
  restoreStruct.iParallelism = 1;
  restoreStruct.iBufferSize = 1024;     /*  1024 x 4KB */
  restoreStruct.iNumBuffers = 2;
  restoreStruct.iCallerAction = DB2RESTORE_RESTORE;
  restoreStruct.iOptions =
    DB2RESTORE_OFFLINE | DB2RESTORE_DB | DB2RESTORE_NODATALINK |
    DB2RESTORE_NOROLLFWD;

  /* The API db2Restore is used to restore a database that has been backed
     up using the API db2Backup. */
  db2Restore(db2Version970, &restoreStruct, &sqlca);
  EXPECTED_WARN_CHECK("database restore -- start");

  while (sqlca.sqlcode != 0)
  {
    /* continue the restore operation */
    printf("\n  Continuing the restore operation...\n");

    /* depending on the sqlca.sqlcode value, user action may be
       required, such as mounting a new tape */

    restoreStruct.iCallerAction = DB2RESTORE_CONTINUE;

    /* restore the database */
    db2Restore(db2Version970, &restoreStruct, &sqlca);
    DB2_API_CHECK("database restore -- continue");
  }

  printf("\n  Restore finished.\n");

  return 0;
} /* DbBackupAndRestore */