//****************************************************************************** //****************************************************************************** // Code disclaimer information //------------------------------------------------------------------------------ // This file contains programming code examples. // // IBM grants you a nonexclusive copyright license to use all programming // code examples from which you can generate similar functions tailored to // your own specific needs. // // All sample code is provided by IBM for illustrative purposes only. // These examples have not been thoroughly tested under all conditions. IBM, // therefore, cannot guarantee or imply reliability, serviceability, or // function of these programs. // // All programs contained herein are provided to you "AS IS" without any // warranties of any kind. The implied warranties of non-infringement, // merchantability, and fitness for a particular purpose are expressly // disclaimed. //****************************************************************************** //****************************************************************************** //-- START OF SPECIFICATIONS ------------------------------------------------ // // Source File Name : fidtbl.C // // Module Name : FIDTBL // // Service Program Name : FIDTBL // // Source File Description: Class member functions for classes FIDTableEntry // and FIDTable. This is a simple // implementation of File ID mapping between a // source and target system. However, please note // that the table is primed by assuming that the // source and target systems are the same system. // For demo purposes, we usually will only have one // iSeries system available, so we are using a remote // journal on the same source system. // //****** WARNING ***** PLEASE READ ME ****************************************** // USE OF THIS SOURCE CODE IS AT YOUR OWN RISK. // This code is being used in the IFS Journaling Replication demo that was // first used at COMMON in March 2003. This code is NOT a complete replication // solution, and should not be used to provide object or data replication. // It was written to provide a way to demo replication of a small subset of IFS // journal entries using a remote journal on the SAME system. It is being made // available for public browsing as an example what was really involved in // performing some of the steps required in providing IFS object/data // replication. Therefore, some of the code within this demo takes shortcuts // that would not be available in a normal replication environment involving // separate source and target systems. //****************************************************************************** // // Change Activity : // // CFD List : // // FLAG REASON RELEASE DATE PGMR CHANGE DESCRIPTION // ---- --------- ---------- ------ --------- ---------------------------------- // $A0= DEMO xxxx 030129 IBMG8PA: New module // // End CFD List. // // Additional notes about the Change Activity // // End Change Activity. // //------------------------------------------------------------------------------ #include "fidtbl.H" #include //---- START OF MEMBER FUNCTION SPECIFICATION ---------------------------------- // // Member Function Name : FIDTableEntry (constructor) // // Descriptive Name : Constructor for File ID Table Entry. // // Prototype Location : fidtbl.H // // Notes : None. // //---- END OF MEMBER FUNCTION SPECIFICATION ------------------------------------ FIDTableEntry::FIDTableEntry(Qp0lFID_t inSrcFID, Qp0lFID_t inTgtFID, char *srcPathP, char *tgtPathP) : nextP(NULL), prevP(NULL) { memcpy(srcFID,inSrcFID,sizeof(Qp0lFID_t)); memcpy(tgtFID,inTgtFID,sizeof(Qp0lFID_t)); strcpy(srcPath,srcPathP); strcpy(tgtPath,tgtPathP); }; //---- START OF MEMBER FUNCTION SPECIFICATION ---------------------------------- // // Member Function Name : FIDTable (constructor) // // Descriptive Name : Constructor for File ID Table. // // Prototype Location : fidtbl.H // // Notes : None. // //---- END OF MEMBER FUNCTION SPECIFICATION ------------------------------------ FIDTable::FIDTable(char *srcDirPathP, char *tgtDirPathP) : headP(NULL), lastP(NULL) { int rc = 0; unsigned int numBytesReturned; Qp0lFID_t srcFID; Qp0lFID_t tgtFID; struct pnstruct { Qlg_Path_Name_T qlg_struct; char pn[MAX_PATH_LENGTH]; } pns; struct attrStruct { Qp0l_AttrTypes_List_t attrList; uint attrs[1]; } attrTypes; char attrBuf[100]; Qp0l_Attr_Header_t *attrHdrP = (Qp0l_Attr_Header_t *)attrBuf; unsigned int attrBufSizeNeeded; // First, setup our next available entry pointer. We will simply // start placing the entries following "this" FIDTable object. nextAvailP = (FIDTableEntry *)(this + 1); attrTypes.attrList.Number_Of_ReqAttrs = 1; attrTypes.attrs[0] = QP0L_ATTR_FILE_ID; memset(&pns,0,sizeof(pns)); pns.qlg_struct.CCSID = 37; memcpy(pns.qlg_struct.Country_ID,"US",2); memcpy(pns.qlg_struct.Language_ID,"ENU",3); pns.qlg_struct.Path_Type = 0; memcpy(pns.qlg_struct.Path_Name_Delimiter,"/",1); pns.qlg_struct.Path_Length = strlen(srcDirPathP); memcpy(pns.pn,srcDirPathP,strlen(srcDirPathP)); //------------------------------------------------ // Get the source FID from constant source path. //------------------------------------------------ rc = Qp0lGetAttr((Qlg_Path_Name_T *) &pns, (Qp0l_AttrTypes_List_t *) &attrTypes, (char *)attrHdrP, sizeof(attrBuf), &attrBufSizeNeeded, &numBytesReturned, QP0L_DONOT_FOLLOW_SYMLNK); if (rc) { printf("FIDTable constr, 1st getattr failed %d\n",rc); } memcpy(srcFID, ((char *)attrBuf + sizeof(Qp0l_Attr_Header_t)), sizeof(Qp0lFID_t)); //------------------------------------------------ // Get the target FID from the target path. //------------------------------------------------ pns.qlg_struct.Path_Length = strlen(tgtDirPathP); memcpy(pns.pn,tgtDirPathP,strlen(tgtDirPathP)); rc = Qp0lGetAttr((Qlg_Path_Name_T *) &pns, (Qp0l_AttrTypes_List_t *) &attrTypes, (char *)attrHdrP, sizeof(attrBuf), &attrBufSizeNeeded, &numBytesReturned, QP0L_DONOT_FOLLOW_SYMLNK); if (rc) { // If failed, return here w/o adding the entry. // Things will fail pretty quick or fail to do anything since FIDTable is empty. printf("FIDTable constr, 2nd getattr failed %d\n",rc); return; } memcpy(tgtFID, ((char *)attrBuf + sizeof(Qp0l_Attr_Header_t)), sizeof(Qp0lFID_t)); //------------------------------------------------ // Add the entry. //------------------------------------------------ addEntry(srcFID, tgtFID, srcDirPathP, tgtDirPathP); }; //---- START OF MEMBER FUNCTION SPECIFICATION ---------------------------------- // // Member Function Name : FIDTable (destructor) // // Descriptive Name : Destructor for File ID Table. // // Prototype Location : fidtbl.H // // Notes : None. // //---- END OF MEMBER FUNCTION SPECIFICATION ------------------------------------ FIDTable::~FIDTable() { FIDTableEntry *entP = headP; FIDTableEntry *nextP; while(entP != NULL) { nextP = entP->nextP; delete entP; entP = nextP; } } //---- START OF MEMBER FUNCTION SPECIFICATION ---------------------------------- // // Member Function Name : FIDTable::addEntry // // Descriptive Name : Add an entry to the FIDTable. // // Prototype Location : fidtbl.H // // Notes : None. // //---- END OF MEMBER FUNCTION SPECIFICATION ------------------------------------ int FIDTable::addEntry(Qp0lFID_t srcFID, Qp0lFID_t tgtFID, char *srcPathP, char *tgtPathP) { char path[MAX_PATH_LENGTH]; // If we have at least 1 entry in the FID table, then allocate new entry and hang // it off the end. if (headP != NULL) { FIDTableEntry *tmpLastP = new(nextAvailP) FIDTableEntry(srcFID, tgtFID, srcPathP, tgtPathP); // If the constructor with placement failed, then fail. if (tmpLastP != nextAvailP) { printf("addEntry failed, additional\n"); return -1; } lastP->nextP = tmpLastP; // Set old last entry's next pointer. tmpLastP->prevP = lastP; // Set new entry's prev pointer. lastP = tmpLastP; // Set new "last" entry. } // Else, we don't have any entries yet. Allocate the new entry and hang it at // the head. else { headP = lastP = new(nextAvailP) FIDTableEntry(srcFID, tgtFID, srcPathP, tgtPathP); // If the constructor with placement failed, then fail. if (headP != nextAvailP) { printf("addEntry failed, first\n"); return -1; } } ++nextAvailP; // Bump the next available FIDTableEntry // pointer to next location. return 0; } //---- START OF MEMBER FUNCTION SPECIFICATION ---------------------------------- // // Member Function Name : FIDTable::rmvEntry // // Descriptive Name : Remove an entry from the FIDTable. // // Prototype Location : fidtbl.H // // Notes : None. // //---- END OF MEMBER FUNCTION SPECIFICATION ------------------------------------ void FIDTable::rmvEntry(Qp0lFID_t srcFID) { FIDTableEntry *tmpEntP = findEntry(srcFID); // If we arent' at the head of the list. if (tmpEntP != NULL) { // Connect the remaining, surrounding, entries. if (tmpEntP->prevP != NULL) // If not at the head. { // First, connect the previous entry to the next entry. tmpEntP->prevP->nextP = tmpEntP->nextP; // Then connect the next entry to the previous entry. // Only need to do this if the removed entry wasn't at the end, // because if it was at the end, there wouldn't be any "next" // entry to be updated. if (tmpEntP->nextP != NULL) { tmpEntP->nextP->prevP = tmpEntP->prevP; } else // Removing the last entry. Set last pointer to new last. { lastP = tmpEntP->prevP; } } // Else, the prev entry ptr is NULL. We are removing the head. // We need to make the "found" entry's next pointer the head pointer. else { headP = tmpEntP->nextP; } // Delete the entry. delete(tmpEntP); } } //---- START OF MEMBER FUNCTION SPECIFICATION ---------------------------------- // // Member Function Name : FIDTable::findEntry // // Descriptive Name : Find an entry in the FIDTable. // // Prototype Location : fidtbl.H // // Notes : None. // //---- END OF MEMBER FUNCTION SPECIFICATION ------------------------------------ FIDTableEntry * FIDTable::findEntry(Qp0lFID_t srcFID) { FIDTableEntry *entP = headP; while(entP != NULL) { if (0 == memcmp(entP->srcFID,srcFID,sizeof(Qp0lFID_t))) { return(entP); } entP = entP->nextP; } return(NULL); } //---- START OF MEMBER FUNCTION SPECIFICATION ---------------------------------- // // Member Function Name : FIDTable::getTgtPath // // Descriptive Name : Get the target path for an entry in the FIDTable. // // Prototype Location : fidtbl.H // // Notes : None. // //---- END OF MEMBER FUNCTION SPECIFICATION ------------------------------------ int FIDTable::getTgtPath(char *pathP, Qp0lFID_t srcFID) { FIDTableEntry *entP = findEntry(srcFID); if (entP != NULL) { strcpy(pathP, entP->tgtPath); return 0; } printf("getTgtPath failed. No entry found.\n"); return -1; }