/****************************************************************************
** (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: dbhistfile.sqc
**
** SAMPLE: How to read and update a database recovery history file entry.
**
** 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.
**
** DB2 APIs USED:
** db2HistoryCloseScan -- Close Recovery History File Scan
** db2HistoryGetEntry -- Get Next Recovery History File Entry
** db2HistoryOpenScan -- Open Recovery History File Scan
** db2HistoryUpdate -- Update Recovery History File
**
**
*****************************************************************************
**
** For more information on the sample programs, see the README file.
**
** For information on developing C applications, see the Application
** Development Guide.
**
** 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 DbRecoveryHistoryFileRead(char *);
int DbFirstRecoveryHistoryFileEntryUpdate(char *, char *, char *);
int HistoryEntryDataFieldsAlloc(struct db2HistoryData *);
int HistoryEntryDisplay(struct db2HistoryData );
int HistoryEntryDataFieldsFree(struct db2HistoryData *);
int main(int argc, char *argv[])
{
int rc = 0;
char nodeName[SQL_INSTNAME_SZ + 1] = { 0 };
char serverWorkingPath[SQL_PATH_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 READ A DATABASE RECOVERY HISTORY FILE \n");
printf("AND UPDATE A RECOVERY HISTORY FILE ENTRY. \n");
/* 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");
rc = DbRecoveryHistoryFileRead(dbAlias);
CHECKRC(rc, "DbRecoveryHistoryFileRead");
rc = DbFirstRecoveryHistoryFileEntryUpdate(dbAlias, user, pswd);
CHECKRC(rc, "DbFirstRecoveryHistoryFileEntryUpdate");
/* Detach from the local or remote instance */
rc = InstanceDetach(nodeName);
CHECKRC(rc, "InstanceDetach");
return 0;
} /* end main */
int DbRecoveryHistoryFileRead(char dbAlias[])
{
int rc = 0;
struct sqlca sqlca = { 0 };
struct db2HistoryOpenStruct dbHistoryOpenParam = { 0 };
sqluint32 numEntries = 0;
sqluint16 recoveryHistoryFileHandle = 0;
sqluint32 entryNb = 0;
struct db2HistoryGetEntryStruct dbHistoryEntryGetParam = { 0 };
struct db2HistoryData histEntryData = { 0 };
printf("\n*********************************************\n");
printf("*** READ A DATABASE RECOVERY HISTORY FILE ***\n");
printf("*********************************************\n");
printf("\nUSE THE DB2 APIs:\n");
printf(" db2HistoryOpenScan -- Open Recovery History File Scan\n");
printf(" db2HistoryGetEntry -- Get Next Recovery History File Entry\n");
printf(" db2HistoryCloseScan -- Close Recovery History File Scan\n");
printf("TO READ A DATABASE RECOVERY HISTORY FILE.\n");
/* initialize the data structures */
dbHistoryOpenParam.piDatabaseAlias = dbAlias;
dbHistoryOpenParam.piTimestamp = NULL;
dbHistoryOpenParam.piObjectName = NULL;
dbHistoryOpenParam.iCallerAction = DB2HISTORY_LIST_HISTORY;
dbHistoryEntryGetParam.pioHistData = &histEntryData;
dbHistoryEntryGetParam.iCallerAction = DB2HISTORY_GET_ALL;
rc = HistoryEntryDataFieldsAlloc(&histEntryData);
CHECKRC(rc, "HistoryEntryDataFieldsAlloc");
/*******************************************/
/* OPEN THE DATABASE RECOVERY HISTORY FILE */
/*******************************************/
printf("\n Open recovery history file for '%s' database.\n", dbAlias);
/* open the recovery history file to scan */
db2HistoryOpenScan(db2Version970, &dbHistoryOpenParam, &sqlca);
DB2_API_CHECK("database recovery history file -- open");
numEntries = dbHistoryOpenParam.oNumRows;
/* dbHistoryOpenParam.oHandle returns the handle for scan access */
recoveryHistoryFileHandle = dbHistoryOpenParam.oHandle;
dbHistoryEntryGetParam.iHandle = recoveryHistoryFileHandle;
/**********************************************/
/* READ AN ENTRY IN THE RECOVERY HISTORY FILE */
/**********************************************/
for (entryNb = 0; entryNb < numEntries; entryNb++)
{
printf("\n Read entry number %u.\n", entryNb);
/* get the next entry from the recovery history file */
db2HistoryGetEntry(db2Version970, &dbHistoryEntryGetParam, &sqlca);
DB2_API_CHECK("database recovery history file entry -- read")
/* display the entries in the recovery history file */
printf("\n Display entry number %u.\n", entryNb);
rc = HistoryEntryDisplay(histEntryData);
CHECKRC(rc, "HistoryEntryDisplay");
}
/********************************************/
/* CLOSE THE DATABASE RECOVERY HISTORY FILE */
/********************************************/
printf("\n Close recovery history file for '%s' database.\n", dbAlias);
/* The API db2HistoryCloseScan ends the recovery history file scan and
frees DB2 resources required for the scan. */
db2HistoryCloseScan(db2Version970, &recoveryHistoryFileHandle, &sqlca);
DB2_API_CHECK("database recovery history file -- close");
/* free the allocated memory */
rc = HistoryEntryDataFieldsFree(&histEntryData);
CHECKRC(rc, "HistoryEntryDataFieldsFree");
return 0;
} /* DbRecoveryHistoryFileRead */
int DbFirstRecoveryHistoryFileEntryUpdate(char dbAlias[], char user[],
char pswd[])
{
int rc = 0;
struct sqlca sqlca = { 0 };
struct db2HistoryOpenStruct dbHistoryOpenParam = { 0 };
sqluint16 recoveryHistoryFileHandle = 0;
struct db2HistoryGetEntryStruct dbHistoryEntryGetParam = { 0 };
struct db2HistoryData histEntryData = { 0 };
char newLocation[DB2HISTORY_LOCATION_SZ + 1] = { 0 };
char newComment[DB2HISTORY_COMMENT_SZ + 1] = { 0 };
struct db2HistoryUpdateStruct dbHistoryUpdateParam = { 0 };
printf("\n*****************************************************\n");
printf("*** UPDATE A DATABASE RECOVERY HISTORY FILE ENTRY ***\n");
printf("*****************************************************\n");
printf("\nUSE THE DB2 APIs:\n");
printf(" db2HistoryOpenScan -- Open Recovery History File Scan\n");
printf(" db2HistoryGetEntry -- Get Next Recovery History File Entry\n");
printf(" db2HistoryUpdate -- Update Recovery History File\n");
printf(" db2HistoryCloseScan -- Close Recovery History File Scan\n");
printf("TO UPDATE A DATABASE RECOVERY HISTORY FILE ENTRY.\n");
/* initialize data structures */
dbHistoryOpenParam.piDatabaseAlias = dbAlias;
dbHistoryOpenParam.piTimestamp = NULL;
dbHistoryOpenParam.piObjectName = NULL;
dbHistoryOpenParam.iCallerAction = DB2HISTORY_LIST_HISTORY;
dbHistoryEntryGetParam.pioHistData = &histEntryData;
dbHistoryEntryGetParam.iCallerAction = DB2HISTORY_GET_ALL;
rc = HistoryEntryDataFieldsAlloc(&histEntryData);
CHECKRC(rc, "HistoryEntryDataFieldsAlloc");
/*******************************************/
/* OPEN THE DATABASE RECOVERY HISTORY FILE */
/*******************************************/
printf("\n Open the recovery history file for '%s' database.\n",
dbAlias);
/* The API db2HistoryOpenScan starts a recovery history file scan */
db2HistoryOpenScan(db2Version970, &dbHistoryOpenParam, &sqlca);
DB2_API_CHECK("database recovery history file -- open");
/* dbHistoryOpenParam.oHandle returns the handle for scan access */
recoveryHistoryFileHandle = dbHistoryOpenParam.oHandle;
dbHistoryEntryGetParam.iHandle = recoveryHistoryFileHandle;
/*****************************************************/
/* READ THE FIRST ENTRY IN THE RECOVERY HISTORY FILE */
/*****************************************************/
printf("\n Read the first entry in the recovery history file.\n");
/* The API db2HistoryGetEntry gets the next entry from the recovery
history file. */
db2HistoryGetEntry(db2Version970, &dbHistoryEntryGetParam, &sqlca);
DB2_API_CHECK("first recovery history file entry -- read");
/* check if the recovery history file is empty */
if (sqlca.sqlcode == SQLE_RC_NOMORE)
{
printf(" The History File is Empty!\n");
printf(" No data to return.\n\n");
return 1;
}
printf("\n Display the first entry.\n");
/* HistoryEntryDisplay is a support function used to display the entries
in the recovery history file. */
rc = HistoryEntryDisplay(histEntryData);
CHECKRC(rc, "HistoryEntryDisplay");
/* update the first history file entry */
rc = DbConn(dbAlias, user, pswd);
CHECKRC(rc, "DbConn");
strcpy(newLocation, "this is the NEW LOCATION");
strcpy(newComment, "this is the NEW COMMENT");
printf("\n Update the first entry in the history file:\n");
printf(" new location = '%s'\n", newLocation);
printf(" new comment = '%s'\n", newComment);
dbHistoryUpdateParam.piNewLocation = newLocation;
dbHistoryUpdateParam.piNewDeviceType = NULL;
dbHistoryUpdateParam.piNewComment = newComment;
dbHistoryUpdateParam.iEID.ioNode = histEntryData.oEID.ioNode;
dbHistoryUpdateParam.iEID.ioHID = histEntryData.oEID.ioHID;
/* The API db2HistoryUpdate can be used to update the location,
device type, or comment in a history file entry. */
/* Call this API to update the location and comment of the first
entry in the history file: */
db2HistoryUpdate(db2Version970, &dbHistoryUpdateParam, &sqlca);
DB2_API_CHECK("first history file entry -- update");
rc = DbDisconn(dbAlias);
CHECKRC(rc, "DbDisconn");
/********************************************/
/* CLOSE THE DATABASE RECOVERY HISTORY FILE */
/********************************************/
printf("\n Close recovery history file for '%s' database.\n", dbAlias);
/* The API db2HistoryCloseScan ends the recovery history file scan and
frees DB2 resources required for the scan. */
db2HistoryCloseScan(db2Version970, &recoveryHistoryFileHandle, &sqlca);
DB2_API_CHECK("database recovery history file -- close");
/**********************************************/
/* RE-OPEN THE DATABASE RECOVERY HISTORY FILE */
/**********************************************/
printf("\n Open the recovery history file for '%s' database.\n",
dbAlias);
/* starts a recovery history file scan */
db2HistoryOpenScan(db2Version970, &dbHistoryOpenParam, &sqlca);
DB2_API_CHECK("database recovery history file -- open");
recoveryHistoryFileHandle = dbHistoryOpenParam.oHandle;
dbHistoryEntryGetParam.iHandle = recoveryHistoryFileHandle;
printf("\n Read the first recovery history file entry.\n");
/************************************************************************/
/* READ THE FIRST ENTRY IN THE RECOVERY HISTORY FILE AFTER MODIFICATION */
/************************************************************************/
db2HistoryGetEntry(db2Version970, &dbHistoryEntryGetParam, &sqlca);
DB2_API_CHECK("first recovery history file entry -- read");
printf("\n Display the first entry.\n");
rc = HistoryEntryDisplay(histEntryData);
CHECKRC(rc, "HistoryEntryDisplay");
/********************************************/
/* CLOSE THE DATABASE RECOVERY HISTORY FILE */
/********************************************/
printf("\n Close the recovery history file for '%s' database.\n",
dbAlias);
/* ends the recovery history file scan */
db2HistoryCloseScan(db2Version970, &recoveryHistoryFileHandle, &sqlca);
DB2_API_CHECK("database recovery history file -- close");
/* free the allocated memory */
rc = HistoryEntryDataFieldsFree(&histEntryData);
CHECKRC(rc, "HistoryEntryDataFieldsFree");
return 0;
} /* DbFirstRecoveryHistoryFileEntryUpdate */
/***************************************************************************/
/* HistoryEntryDataFieldsAlloc */
/* Allocates memory for all the fields in a database recovery history */
/* file entry */
/***************************************************************************/
int HistoryEntryDataFieldsAlloc(struct db2HistoryData *pHistEntryData)
{
int rc = 0;
sqluint32 tsNb = 0;
strcpy(pHistEntryData->ioHistDataID, "SQLUHINF");
pHistEntryData->oObjectPart.pioData = malloc(DB2HISTORY_OBJPART_SZ + 1);
pHistEntryData->oObjectPart.iLength = DB2HISTORY_OBJPART_SZ + 1;
pHistEntryData->oEndTime.pioData = malloc(DB2HISTORY_TIMESTAMP_SZ + 1);
pHistEntryData->oEndTime.iLength = DB2HISTORY_TIMESTAMP_SZ + 1;
pHistEntryData->oFirstLog.pioData = malloc(DB2HISTORY_LOGFILE_SZ + 1);
pHistEntryData->oFirstLog.iLength = DB2HISTORY_LOGFILE_SZ + 1;
pHistEntryData->oLastLog.pioData = malloc(DB2HISTORY_LOGFILE_SZ + 1);
pHistEntryData->oLastLog.iLength = DB2HISTORY_LOGFILE_SZ + 1;
pHistEntryData->oID.pioData = malloc(DB2HISTORY_ID_SZ + 1);
pHistEntryData->oID.iLength = DB2HISTORY_ID_SZ + 1;
pHistEntryData->oTableQualifier.pioData =
malloc(DB2HISTORY_TABLE_QUAL_SZ + 1);
pHistEntryData->oTableQualifier.iLength = DB2HISTORY_TABLE_QUAL_SZ + 1;
pHistEntryData->oTableName.pioData = malloc(DB2HISTORY_TABLE_NAME_SZ + 1);
pHistEntryData->oTableName.iLength = DB2HISTORY_TABLE_NAME_SZ + 1;
pHistEntryData->oLocation.pioData = malloc(DB2HISTORY_LOCATION_SZ + 1);
pHistEntryData->oLocation.iLength = DB2HISTORY_LOCATION_SZ + 1;
pHistEntryData->oComment.pioData = malloc(DB2HISTORY_COMMENT_SZ + 1);
pHistEntryData->oComment.iLength = DB2HISTORY_COMMENT_SZ + 1;
pHistEntryData->oCommandText.pioData = malloc(DB2HISTORY_COMMAND_SZ + 1);
pHistEntryData->oCommandText.iLength = DB2HISTORY_COMMAND_SZ + 1;
pHistEntryData->poEventSQLCA =
(struct sqlca *)malloc(sizeof(struct sqlca));
pHistEntryData->poTablespace = (db2Char *) malloc(10 * sizeof(db2Char));
for (tsNb = 0; tsNb < 10; tsNb++)
{
pHistEntryData->poTablespace[tsNb].pioData = malloc(18 + 1);
pHistEntryData->poTablespace[tsNb].iLength = 18 + 1;
}
pHistEntryData->iNumTablespaces = 10;
return 0;
} /* HistoryEntryDataFieldsAlloc */
/***************************************************************************/
/* HistoryEntryDisplay */
/* Displays the fields of an entry in the database recovery history file */
/***************************************************************************/
int HistoryEntryDisplay(struct db2HistoryData histEntryData)
{
int rc = 0;
int bufLen = 0;
char *buf = NULL;
sqluint32 tsNb = 0;
bufLen =
MIN(histEntryData.oObjectPart.oLength,
histEntryData.oObjectPart.iLength);
buf = malloc(bufLen + 1);
memcpy(buf, histEntryData.oObjectPart.pioData, bufLen);
buf[bufLen] = '\0';
printf(" object part: %s\n", buf);
free(buf);
bufLen =
MIN(histEntryData.oEndTime.oLength, histEntryData.oEndTime.iLength);
buf = malloc(bufLen + 1);
memcpy(buf, histEntryData.oEndTime.pioData, bufLen);
buf[bufLen] = '\0';
printf(" end time: %s\n", buf);
free(buf);
bufLen =
MIN(histEntryData.oFirstLog.oLength, histEntryData.oFirstLog.iLength);
buf = malloc(bufLen + 1);
memcpy(buf, histEntryData.oFirstLog.pioData, bufLen);
buf[bufLen] = '\0';
printf(" first log: %s\n", buf);
free(buf);
bufLen =
MIN(histEntryData.oLastLog.oLength, histEntryData.oLastLog.iLength);
buf = malloc(bufLen + 1);
memcpy(buf, histEntryData.oLastLog.pioData, bufLen);
buf[bufLen] = '\0';
printf(" last log: %s\n", buf);
free(buf);
bufLen = MIN(histEntryData.oID.oLength, histEntryData.oID.iLength);
buf = malloc(bufLen + 1);
memcpy(buf, histEntryData.oID.pioData, bufLen);
buf[bufLen] = '\0';
printf(" ID: %s\n", buf);
free(buf);
bufLen =
MIN(histEntryData.oTableQualifier.oLength,
histEntryData.oTableQualifier.iLength);
buf = malloc(bufLen + 1);
memcpy(buf, histEntryData.oTableQualifier.pioData, bufLen);
buf[bufLen] = '\0';
printf(" table qualifier: %s\n", buf);
free(buf);
bufLen =
MIN(histEntryData.oTableName.oLength, histEntryData.oTableName.iLength);
buf = malloc(bufLen + 1);
memcpy(buf, histEntryData.oTableName.pioData, bufLen);
buf[bufLen] = '\0';
printf(" table name: %s\n", buf);
free(buf);
bufLen =
MIN(histEntryData.oLocation.oLength, histEntryData.oLocation.iLength);
buf = malloc(bufLen + 1);
memcpy(buf, histEntryData.oLocation.pioData, bufLen);
buf[bufLen] = '\0';
printf(" location: %s\n", buf);
free(buf);
bufLen =
MIN(histEntryData.oComment.oLength, histEntryData.oComment.iLength);
buf = malloc(bufLen + 1);
memcpy(buf, histEntryData.oComment.pioData, bufLen);
buf[bufLen] = '\0';
printf(" comment: %s\n", buf);
free(buf);
bufLen =
MIN(histEntryData.oCommandText.oLength,
histEntryData.oCommandText.iLength);
buf = malloc(bufLen + 1);
memcpy(buf, histEntryData.oCommandText.pioData, bufLen);
buf[bufLen] = '\0';
printf(" command text: %s\n", buf);
printf(" history file entry ID: %u\n", histEntryData.oEID.ioHID);
printf(" table spaces:\n");
free(buf);
for (tsNb = 0; tsNb < histEntryData.oNumTablespaces; tsNb++)
{
bufLen =
MIN(histEntryData.poTablespace[tsNb].oLength,
histEntryData.poTablespace[tsNb].iLength);
buf = malloc(bufLen + 1);
memcpy(buf, histEntryData.poTablespace[tsNb].pioData, bufLen);
buf[bufLen] = '\0';
printf(" %s\n", buf);
free(buf);
}
printf(" oLastLSN: %d\n", histEntryData.oLastLSN);
printf(" type of operation: %c\n", histEntryData.oOperation);
printf(" granularity of the operation: %c\n", histEntryData.oObject);
printf(" operation type: %c\n", histEntryData.oOptype);
printf(" entry status: %c\n", histEntryData.oStatus);
printf(" device type: %c\n", histEntryData.oDeviceType);
printf(" SQLCA:\n");
printf(" sqlcode: %ld\n", histEntryData.poEventSQLCA->sqlcode);
bufLen = SQLUDF_SQLSTATE_LEN;
buf = malloc(bufLen + 1);
memcpy(buf, histEntryData.poEventSQLCA->sqlstate, bufLen);
buf[bufLen] = '\0';
printf(" sqlstate: %s\n", buf);
free(buf);
bufLen = histEntryData.poEventSQLCA->sqlerrml;
buf = malloc(bufLen + 1);
memcpy(buf, histEntryData.poEventSQLCA->sqlerrmc, bufLen);
buf[bufLen] = '\0';
printf(" message: %s\n", buf);
free(buf);
return 0;
} /* HistoryEntryDisplay */
/***************************************************************************/
/* HistoryEntryDataFieldsFree */
/* Deallocates the memory for database recovery history file structures */
/***************************************************************************/
int HistoryEntryDataFieldsFree(struct db2HistoryData *pHistEntryData)
{
int rc = 0;
sqluint32 tsNb = 0;
free(pHistEntryData->oObjectPart.pioData);
free(pHistEntryData->oEndTime.pioData);
free(pHistEntryData->oFirstLog.pioData);
free(pHistEntryData->oLastLog.pioData);
free(pHistEntryData->oID.pioData);
free(pHistEntryData->oTableQualifier.pioData);
free(pHistEntryData->oTableName.pioData);
free(pHistEntryData->oLocation.pioData);
free(pHistEntryData->oComment.pioData);
free(pHistEntryData->oCommandText.pioData);
free(pHistEntryData->poEventSQLCA);
pHistEntryData->oObjectPart.pioData = NULL;
pHistEntryData->oEndTime.pioData = NULL;
pHistEntryData->oFirstLog.pioData = NULL;
pHistEntryData->oLastLog.pioData = NULL;
pHistEntryData->oID.pioData = NULL;
pHistEntryData->oTableQualifier.pioData = NULL;
pHistEntryData->oTableName.pioData = NULL;
pHistEntryData->oLocation.pioData = NULL;
pHistEntryData->oComment.pioData = NULL;
pHistEntryData->oCommandText.pioData = NULL;
pHistEntryData->poEventSQLCA = NULL;
for (tsNb = 0; tsNb < 10; tsNb++)
{
free(pHistEntryData->poTablespace[tsNb].pioData);
pHistEntryData->poTablespace[tsNb].pioData = NULL;
}
free(pHistEntryData->poTablespace);
pHistEntryData->poTablespace = NULL;
return 0;
} /* HistoryEntryDataFieldsFree */