/****************************************************************************
** (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 file entry
**
** DB2 APIs USED:
** db2HistoryOpenScan -- OPEN RECOVERY HISTORY FILE SCAN
** db2HistoryGetEntry -- GET NEXT RECOVERY HISTORY FILE ENTRY
** db2HistoryUpdate -- UPDATE RECOVERY HISTORY FILE
** db2HistoryCloseScan -- CLOSE RECOVERY HISTORY FILE SCAN
**
**
*****************************************************************************
**
** 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
****************************************************************************/
#ifdef DB2NT
#include "utilrecov.cxx"
#else
#include "utilrecov.C"
#endif
class DbHistFile: public UtilRecov
{
public:
int DbRecoveryHistoryFileRead(DbEmb *);
int DbFirstRecoveryHistoryFileEntryUpdate(DbEmb *);
private:
int HistoryEntryDataFieldsAlloc(struct db2HistoryData *);
int HistoryEntryDisplay(struct db2HistoryData);
int HistoryEntryDataFieldsFree(struct db2HistoryData *);
};
//**************************************************************************
// HistoryEntryDataFieldsAlloc
// Allocates memory for all the fields in a database recovery history
// file entry
//**************************************************************************
int DbHistFile::
HistoryEntryDataFieldsAlloc(struct db2HistoryData *pHistEntryData)
{
int rc = 0;
sqluint32 tsNb;
strcpy(pHistEntryData->ioHistDataID, "SQLUHINF");
pHistEntryData->oObjectPart.pioData = new char[DB2HISTORY_OBJPART_SZ + 1];
pHistEntryData->oObjectPart.iLength = DB2HISTORY_OBJPART_SZ + 1;
pHistEntryData->oEndTime.pioData = new char[DB2HISTORY_TIMESTAMP_SZ + 1];
pHistEntryData->oEndTime.iLength = DB2HISTORY_TIMESTAMP_SZ + 1;
pHistEntryData->oFirstLog.pioData = new char[DB2HISTORY_LOGFILE_SZ + 1];
pHistEntryData->oFirstLog.iLength = DB2HISTORY_LOGFILE_SZ + 1;
pHistEntryData->oLastLog.pioData = new char[DB2HISTORY_LOGFILE_SZ + 1];
pHistEntryData->oLastLog.iLength = DB2HISTORY_LOGFILE_SZ + 1;
pHistEntryData->oID.pioData = new char[DB2HISTORY_ID_SZ + 1];
pHistEntryData->oID.iLength = DB2HISTORY_ID_SZ + 1;
pHistEntryData->oTableQualifier.pioData =
new char[DB2HISTORY_TABLE_QUAL_SZ + 1];
pHistEntryData->oTableQualifier.iLength = DB2HISTORY_TABLE_QUAL_SZ + 1;
pHistEntryData->oTableName.pioData =
new char[DB2HISTORY_TABLE_NAME_SZ + 1];
pHistEntryData->oTableName.iLength = DB2HISTORY_TABLE_NAME_SZ + 1;
pHistEntryData->oLocation.pioData = new char[DB2HISTORY_LOCATION_SZ + 1];
pHistEntryData->oLocation.iLength = DB2HISTORY_LOCATION_SZ + 1;
pHistEntryData->oComment.pioData = new char[DB2HISTORY_COMMENT_SZ + 1];
pHistEntryData->oComment.iLength = DB2HISTORY_COMMENT_SZ + 1;
pHistEntryData->oCommandText.pioData = new char[DB2HISTORY_COMMAND_SZ + 1];
pHistEntryData->oCommandText.iLength = DB2HISTORY_COMMAND_SZ + 1;
pHistEntryData->poEventSQLCA = new sqlca;
pHistEntryData->poTablespace = new db2Char[10];
for (tsNb = 0; tsNb < 10; tsNb = tsNb + 1)
{
pHistEntryData->poTablespace[tsNb].pioData = new char[18 + 1];
pHistEntryData->poTablespace[tsNb].iLength = 18 + 1;
}
pHistEntryData->iNumTablespaces = 10;
return 0;
} // DbHistFile::HistoryEntryDataFieldsAlloc
//**************************************************************************
// HistoryEntryDisplay
// Displays the fields of an entry in the database recovery history file
//**************************************************************************
int DbHistFile::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 = new char[bufLen + 1];
memcpy(buf, histEntryData.oObjectPart.pioData, bufLen);
buf[bufLen] = '\0';
cout << " object part: " << buf << endl;
delete [] buf;
bufLen =
MIN(histEntryData.oEndTime.oLength, histEntryData.oEndTime.iLength);
buf = new char[bufLen + 1];
memcpy(buf, histEntryData.oEndTime.pioData, bufLen);
buf[bufLen] = '\0';
cout << " end time: " << buf << endl;
delete [] buf;
bufLen =
MIN(histEntryData.oFirstLog.oLength, histEntryData.oFirstLog.iLength);
buf = new char[bufLen + 1];
memcpy(buf, histEntryData.oFirstLog.pioData, bufLen);
buf[bufLen] = '\0';
cout << " first log: " << buf << endl;
delete [] buf;
bufLen =
MIN(histEntryData.oLastLog.oLength, histEntryData.oLastLog.iLength);
buf = new char[bufLen + 1];
memcpy(buf, histEntryData.oLastLog.pioData, bufLen);
buf[bufLen] = '\0';
cout << " last log: " << buf << endl;
delete [] buf;
bufLen = MIN(histEntryData.oID.oLength, histEntryData.oID.iLength);
buf = new char[bufLen + 1];
memcpy(buf, histEntryData.oID.pioData, bufLen);
buf[bufLen] = '\0';
cout << " ID: " << buf << endl;
delete [] buf;
bufLen =
MIN(histEntryData.oTableQualifier.oLength,
histEntryData.oTableQualifier.iLength);
buf = new char[bufLen + 1];
memcpy(buf, histEntryData.oTableQualifier.pioData, bufLen);
buf[bufLen] = '\0';
cout << " table qualifier: " << buf << endl;
delete [] buf;
bufLen =
MIN(histEntryData.oTableName.oLength, histEntryData.oTableName.iLength);
buf = new char[bufLen + 1];
memcpy(buf, histEntryData.oTableName.pioData, bufLen);
buf[bufLen] = '\0';
cout << " table name: " << buf << endl;
delete [] buf;
bufLen =
MIN(histEntryData.oLocation.oLength, histEntryData.oLocation.iLength);
buf = new char[bufLen + 1];
memcpy(buf, histEntryData.oLocation.pioData, bufLen);
buf[bufLen] = '\0';
cout << " location: " << buf << endl;
delete [] buf;
bufLen =
MIN(histEntryData.oComment.oLength, histEntryData.oComment.iLength);
buf = new char[bufLen + 1];
memcpy(buf, histEntryData.oComment.pioData, bufLen);
buf[bufLen] = '\0';
cout << " comment: " << buf << endl;
delete [] buf;
bufLen =
MIN(histEntryData.oCommandText.oLength,
histEntryData.oCommandText.iLength);
buf = new char[bufLen + 1];
memcpy(buf, histEntryData.oCommandText.pioData, bufLen);
buf[bufLen] = '\0';
cout << " command text: " << buf << endl;
delete [] buf;
cout << " history file entry ID: " << histEntryData.oEID.ioHID << endl;
cout << " tablespaces:" << endl;
for (tsNb = 0; tsNb < histEntryData.oNumTablespaces; tsNb = tsNb + 1)
{
bufLen =
MIN(histEntryData.poTablespace[tsNb].oLength,
histEntryData.poTablespace[tsNb].iLength);
buf = new char[bufLen + 1];
memcpy(buf, histEntryData.poTablespace[tsNb].pioData, bufLen);
buf[bufLen] = '\0';
cout << " " << buf << endl;
delete [] buf;
}
cout << " oLastLSN: " << histEntryData.oLastLSN.lsnU64 << endl;
cout << " type of operation: " << histEntryData.oOperation << endl;
cout << " granularity of the operation: " << histEntryData.oObject << endl;
cout << " operation type: " << histEntryData.oOptype << endl;
cout << " entry status: " << histEntryData.oStatus << endl;
cout << " device type: " << histEntryData.oDeviceType << endl;
cout << " SQLCA:" << endl;
cout << " sqlcode: " << histEntryData.poEventSQLCA->sqlcode << endl;
bufLen = SQLUDF_SQLSTATE_LEN;
buf = new char[bufLen + 1];
memcpy(buf, histEntryData.poEventSQLCA->sqlstate, bufLen);
buf[bufLen] = '\0';
cout << " sqlstate: " << buf << endl;
delete [] buf;
bufLen = histEntryData.poEventSQLCA->sqlerrml;
buf = new char[bufLen + 1];
memcpy(buf, histEntryData.poEventSQLCA->sqlerrmc, bufLen);
buf[bufLen] = '\0';
cout << " message: " << buf << endl;
delete [] buf;
return 0;
} // DbHistFile::HistoryEntryDisplay
//**************************************************************************
// HistoryEntryDataFieldsFree
// Deallocates the memory for database recovery history file structures
//**************************************************************************
int DbHistFile::
HistoryEntryDataFieldsFree(struct db2HistoryData *pHistEntryData)
{
int rc = 0;
sqluint32 tsNb = 0;
delete [] pHistEntryData->oObjectPart.pioData;
delete [] pHistEntryData->oEndTime.pioData;
delete [] pHistEntryData->oFirstLog.pioData;
delete [] pHistEntryData->oLastLog.pioData;
delete [] pHistEntryData->oID.pioData;
delete [] pHistEntryData->oTableQualifier.pioData;
delete [] pHistEntryData->oTableName.pioData;
delete [] pHistEntryData->oLocation.pioData;
delete [] pHistEntryData->oComment.pioData;
delete [] pHistEntryData->oCommandText.pioData;
delete pHistEntryData->poEventSQLCA;
for (tsNb = 0; tsNb < 10; tsNb = tsNb + 1)
{
delete [] pHistEntryData->poTablespace[tsNb].pioData;
}
delete [] pHistEntryData->poTablespace;
return 0;
} // DbHistFile::HistoryEntryDataFieldsFree
//**************************************************************************
// DbRecoveryHistoryFileRead
// Reads the database recovery history file
//**************************************************************************
int DbHistFile::DbRecoveryHistoryFileRead(DbEmb *db)
{
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 };
cout << "\n*********************************************\n";
cout << "*** READ A DATABASE RECOVERY HISTORY FILE ***\n";
cout << "*********************************************\n";
cout << "\nUSE THE DB2 APIs:" << endl;
cout << " db2HistoryOpenScan -- OPEN RECOVERY HISTORY FILE SCAN" << endl;
cout << " db2HistoryGetEntry -- GET NEXT RECOVERY HISTORY FILE ENTRY"
<< endl;
cout << " db2HistoryCloseScan -- CLOSE RECOVERY HISTORY FILE SCAN"
<< endl;
cout << "TO READ A DATABASE RECOVERY HISTORY FILE." << endl;
// Initialize data structures
dbHistoryOpenParam.piDatabaseAlias = db->getAlias();
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 database recovery history file
cout << "\n Open the recovery history file for '" << db->getAlias()
<< "' database." << endl;
// OPEN RECOVERY HISTORY FILE SCAN
db2HistoryOpenScan(db2Version970, &dbHistoryOpenParam, &sqlca);
DB2_API_CHECK("database recovery history file -- open");
numEntries = dbHistoryOpenParam.oNumRows;
recoveryHistoryFileHandle = dbHistoryOpenParam.oHandle;
// Read and display the history file entries
dbHistoryEntryGetParam.iHandle = recoveryHistoryFileHandle;
for (entryNb = 0; entryNb < numEntries; entryNb = entryNb + 1)
{
// Read the recovery history file entry
cout << "\n Read entry number " << entryNb << "." << endl;
// GET NEXT RECOVERY HISTORY FILE ENTRY
db2HistoryGetEntry(db2Version970, &dbHistoryEntryGetParam, &sqlca);
DB2_API_CHECK("database recovery history file entry -- read")
// display the recovery history file entry
cout << "\n Display entry number " << entryNb << "." << endl;
rc = HistoryEntryDisplay(histEntryData);
CHECKRC(rc, "HistoryEntryDisplay");
}
// close the database recovery history file
cout << "\n Close recovery history file for '" << db->getAlias()
<< "' database." << endl;
// CLOSE RECOVERY HISTORY FILE SCAN
db2HistoryCloseScan(db2Version970, &recoveryHistoryFileHandle, &sqlca);
DB2_API_CHECK("database recovery history file -- close");
// Release the memory allocated
rc = HistoryEntryDataFieldsFree(&histEntryData);
CHECKRC(rc, "HistoryEntryDataFieldsFree");
return 0;
} // DbHistFile::DbRecoveryHistoryFileRead
//**************************************************************************
// DbFirstRecoveryHistoryFileEntryUpdate
// Updates the first entry in the database recovery history file
//**************************************************************************
int DbHistFile::DbFirstRecoveryHistoryFileEntryUpdate(DbEmb *db)
{
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 };
cout << "\n*****************************************************\n";
cout << "*** UPDATE A DATABASE RECOVERY HISTORY FILE ENTRY ***\n";
cout << "*****************************************************\n";
cout << "\nUSE THE DB2 APIs:" << endl;
cout << " db2HistoryOpenScan -- OPEN RECOVERY HISTORY FILE SCAN" << endl;
cout << " db2HistoryGetEntry -- GET NEXT RECOVERY HISTORY FILE ENTRY"
<< endl;
cout << " db2HistoryUpdate -- UPDATE RECOVERY HISTORY FILE" << endl;
cout << " db2HistoryCloseScan -- CLOSE RECOVERY HISTORY FILE SCAN"
<< endl;
cout << "TO UPDATE A DATABASE RECOVERY HISTORY FILE ENTRY." << endl;
// Initialize the data structures
dbHistoryOpenParam.piDatabaseAlias = db->getAlias();
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
cout << "\n Open the recovery history file for '" << db->getAlias()
<< "' database." << endl;
// OPEN RECOVERY HISTORY FILE SCAN
db2HistoryOpenScan(db2Version970, &dbHistoryOpenParam, &sqlca);
DB2_API_CHECK("database recovery history file -- open");
recoveryHistoryFileHandle = dbHistoryOpenParam.oHandle;
// Read and display first history file entry
dbHistoryEntryGetParam.iHandle = recoveryHistoryFileHandle;
cout << "\n Read the first entry in the recovery history file." << endl;
// GET NEXT RECOVERY HISTORY FILE ENTRY
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)
{
cout << " The History File is Empty! " << endl;
cout << " No data to return. " << endl << endl;
return 1;
}
cout << "\n Display the first entry." << endl;
rc = HistoryEntryDisplay(histEntryData);
CHECKRC(rc, "HistoryEntryDisplay");
// Update the first history file entry
rc = db->Connect();
CHECKRC(rc, "db->Connect");
strcpy(newLocation, "this is the NEW LOCATION");
strcpy(newComment, "this is the NEW COMMENT");
cout << "\n Update the first entry in the history file:" << endl;
cout << " new location = '" << newLocation << "'" << endl;
cout << " new comment = '" << newComment << "'" << endl;
dbHistoryUpdateParam.piNewLocation = newLocation;
dbHistoryUpdateParam.piNewDeviceType = NULL;
dbHistoryUpdateParam.piNewComment = newComment;
dbHistoryUpdateParam.iEID.ioNode = histEntryData.oEID.ioNode;
dbHistoryUpdateParam.iEID.ioHID = histEntryData.oEID.ioHID;
// UPDATE RECOVERY HISTORY FILE
db2HistoryUpdate(db2Version970, &dbHistoryUpdateParam, &sqlca);
DB2_API_CHECK("first history file entry -- update");
rc = db->Disconnect();
CHECKRC(rc, "db->Disconnect");
// Read and dispaly the first history file entry again
cout << "\n Close recovery history file for '" << db->getAlias()
<< "' database." << endl;
// CLOSE RECOVERY HISTORY FILE SCAN
db2HistoryCloseScan(db2Version970, &recoveryHistoryFileHandle, &sqlca);
DB2_API_CHECK("database recovery history file -- close");
cout << "\n Open the recovery history file for '" << db->getAlias()
<< "' database." << endl;
// OPEN RECOVERY HISTORY FILE SCAN
db2HistoryOpenScan(db2Version970, &dbHistoryOpenParam, &sqlca);
DB2_API_CHECK("database recovery history file -- open");
recoveryHistoryFileHandle = dbHistoryOpenParam.oHandle;
dbHistoryEntryGetParam.iHandle = recoveryHistoryFileHandle;
cout << "\n Read the first entry in the recovery history file." << endl;
// GET NEXT RECOVERY HISTORY FILE ENTRY
db2HistoryGetEntry(db2Version970, &dbHistoryEntryGetParam, &sqlca);
DB2_API_CHECK("first recovery history file entry -- read");
cout << "\n Display the first entry." << endl;
rc = HistoryEntryDisplay(histEntryData);
CHECKRC(rc, "HistoryEntryDisplay");
// Close the database recovery history file
cout << "\n Close the recovery history file for '" << db->getAlias()
<< "' database." << endl;
// CLOSE RECOVERY HISTORY FILE SCAN
db2HistoryCloseScan(db2Version970, &recoveryHistoryFileHandle, &sqlca);
DB2_API_CHECK("database recovery history file -- close");
// Release the allocated memory
rc = HistoryEntryDataFieldsFree(&histEntryData);
CHECKRC(rc, "HistoryEntryDataFieldsFree");
return 0;
} // DbHistFile::DbFirstRecoveryHistoryFileEntryUpdate
int main(int argc, char *argv[])
{
int rc = 0;
CmdLineArgs check;
char serverWorkingPath[SQL_PATH_SZ + 1] = { 0 };
Instance inst;
DbEmb db;
DbHistFile histFile;
// Check the command line arguments
rc = check.CmdLineArgsCheck3(argc, argv, db, inst);
CHECKRC(rc, "check.CmdLineArgsCheck3");
cout << "\nTHIS SAMPLE SHOWS HOW TO READ A DATABASE RECOVERY HISTORY FILE \n";
cout << "AND UPDATE A RECOVERY HISTORY FILE ENTRY. \n";
// Attach to a local or remote instance
rc = inst.Attach();
CHECKRC(rc, "inst.Attach");
// Get a server working path
rc = histFile.ServerWorkingPathGet(&db, serverWorkingPath);
CHECKRC(rc, "histFile.ServerWorkingPathGet");
// Call the sample functions
rc = histFile.DbRecoveryHistoryFileRead(&db);
CHECKRC(rc, "histFile.DbRecoveryHistoryFileRead");
rc = histFile.DbFirstRecoveryHistoryFileEntryUpdate(&db);
CHECKRC(rc, "histFile.DbFirstRecoveryHistoryFileEntryUpdate");
// Detach from the local or remote instance
rc = inst.Detach();
CHECKRC(rc, "inst.Detach");
return 0;
} // main