/* PROGRAM: dsmMandatoryFieldsGet - find cached file metadata. This cache * is stored in shared memory * * RETURNS: DSM_S_SUCCES * */ dsmStatus_t dsmMandatoryFieldsGet(dsmContext_t *pcontext, struct meta_filectl *pmetactl, /* mand. table from shm */ dsmDbkey_t fileDbkey, /* dbkey of _file record */ int fileNumber, /* file # of _file record */ dsmBoolean_t fileKey, /* dbkey/file# of _file */ dsmBoolean_t copyFound, /* flag to copy mand. flds */ struct mand *pmand) /* storage for mand. array */ { dbcontext_t *pdbcontext = pcontext->pdbcontext; dsmStatus_t returnCode; int metaSize; pdbcontext->inservice++; /* postpone signal handler processing */ SETJMP_ERROREXIT(pcontext, returnCode) /* Ensure error exit address set */ if ((returnCode = dsmThreadSafeEntry(pcontext)) != DSM_S_SUCCESS) { returnCode = dsmEntryProcessError(pcontext, returnCode, (TEXT *)"dsmMandatoryFieldsGet"); goto done; } MT_LOCK_SCC (); /* Check if the entry already exists */ dsmMandFindEntry(pcontext, &pmetactl, fileDbkey, fileNumber, fileKey); if (pmetactl != NULL) { DEBUG_FPRINTF(stderr, "dbmanb: cache entry found, returning\n"); if (copyFound != 0) { metaSize = (pmetactl->nmand+1)*sizeof(struct mand); bufcop((TEXT *)pmand, (TEXT *)pmetactl->mand, metaSize); } } MT_UNLK_SCC (); returnCode = DSM_S_SUCCESS; done: dsmThreadSafeExit(pcontext); pdbcontext->inservice--; return returnCode; }
LOCALF int rlaiVersion( dsmContext_t *pcontext, AIBLK *paiblk) /* Pointer to ai file header */ { LONG AiVersion; LONG rc = 1; /* Make sure that the header length is in the ball park */ if( paiblk->aihdr.aihdrlen > (COUNT)(sizeof(AIHDR) + sizeof(AIFIRST))) { /* This is not a Progress ai file */ MSGN_CALLBACK(pcontext, rlMSG104); return ( rc ); } /* Copy ai version to avoid alignment errors when testing the ai version in what is a bogus block. */ bufcop((TEXT *)&AiVersion, ((TEXT *)paiblk + paiblk->aihdr.aihdrlen - sizeof(LONG)), sizeof(LONG)); if( AiVersion != AIVERSION ) { /* Invalid after image version number found in ai file header */ MSGN_CALLBACK(pcontext, rlMSG100); if( paiblk->aihdr.aihdrlen != sizeof(AIHDR) + sizeof(AIFIRST)) { if ( paiblk->aihdr.aihdrlen == sizeof(AIHDRv0) + sizeof(AIFIRSTv0)) { /* This is a version 0 Progress ai file. */ MSGN_CALLBACK(pcontext, rlMSG101); /* The ai file must be truncated. */ MSGN_CALLBACK(pcontext, rlMSG102); /* See documentation for aimage truncate */ MSGN_CALLBACK(pcontext, rlMSG103); return ( rc ); } /* This is not a Progress ai file */ MSGN_CALLBACK(pcontext, rlMSG104); return ( rc ); } } rc = 0; return ( rc ); }
/* PROGRAM: utapath - given a file name, possibly fully qualified, * an optional suffix, a target buffer, and the length * of the target buffer, put the pieces of the file name * together into the output buffer. If the pathname is * not fully qualified, prepend the current working * directory. * * Needs work for MSDOS. * * RETURNS: the output buffer updated, truncated if the result is * too long * */ TEXT * utapath (TEXT *fullpath, /* fully qualified path name */ int pathlen, /* length of answer buffer */ TEXT *filename, /* file name, possibly qualified */ TEXT *suffix) /* suffix for file name */ { TEXT *ptxt; /* current location */ int used = 0; /* amount used */ int drvno = 0; #if OPSYS==WIN32API int i, j; #endif /* if file name not fully qualified, get pathname of current working directory into answer buffer */ #if OPSYS==UNIX if (*filename != '/') #endif #if OPSYS==WIN32API /* handle drive specfier, if any */ j = stlen(filename); for (i = 1, ptxt = filename; i <= j; i++, ptxt++) if (*ptxt == ':') break; if (i < j && i != 2) { /* file server volume name is specified */ bufcop(fullpath, filename, i); used += i; filename += i; } if ((i == 2) && (filename[1] == ':')) { bufcop(fullpath, filename, 2); used += 2; drvno = toupper(*filename) - 64; /* A = 1 B = 2 ..etc */ filename += 2; } else drvno = 0; /* means use current drive */ if ((*filename != '/') && (*filename != '\\')) #endif /* OPSYS == WIN32API */ { used += utpwd (fullpath+used, pathlen ,drvno); if (*filename) { if((*(fullpath+used-1) != '\\') && (*(fullpath+used-1) != '/')) { ptxt = (TEXT *)stcopy ( (TEXT *)fullpath+used, (TEXT *)"/" ); ++used; } } } ptxt = fullpath + used; /* move in filename and suffix */ used += stncop ( ptxt, filename, (pathlen - used) ); ptxt = fullpath + used; used += stncop ( ptxt, suffix, (pathlen - used) ); used = utfCompressPath(fullpath); /* return pointer to null terminator */ return (fullpath + used); }
/* PROGRAM: rlmemwt - write the transaction table and phy. backout flag * into an rlnote * * RETURNS: DSMVOID */ DSMVOID rlmemwt(dsmContext_t *pcontext) { dbcontext_t *pdbcontext = pcontext->pdbcontext; dbshm_t *pdbpub = pdbcontext->pdbpub; MEMNOTE note; TEXT *ptx; TX *ptrn; TEXT *pdata; COUNT dlen; TRANTAB *ptran = pdbcontext->ptrantab; int i,j,numToGo; TRACE_CB(pcontext, "rlmemwt") INITNOTE(note, RL_INMEM, RL_PHY ); note.rlpbkout = pdbcontext->prlctl->rlpbkout; note.lasttask = pdbcontext->pmstrblk->mb_lasttask; note.numLive = pdbcontext->ptrantab->numlive; note.numMemnotes = (note.numLive / (UCOUNT)MAX_ENTRIES_PER_NOTE) + 1; note.tmsize = sizeof (TX) - sizeof(txPlus_t); /* This is a funny note. It describes physical state but since no action is taken and no database blocks depend on it so we'll write it with... */ note.rlnote.rlArea = 0; /* bug 20000114-034 by dmeyer in v9.1b */ note.rlnote.rldbk = 0; note.rlnote.rlupdctr = 0; note.spare[0] = 0; note.spare[1] = 0; /* put 0 in the trn id part of the note */ note.rlnote.rlTrid = 0; if ( ptran->numlive > MAX_ENTRIES_PER_NOTE ) note.numThisNote = MAX_ENTRIES_PER_NOTE; else note.numThisNote = ptran->numlive; dlen = note.numThisNote * note.tmsize; /* bug 93-01-21-035: use stRent instead of stkpush */ pdata = (TEXT *)stRentd (pcontext, pdsmStoragePool, (unsigned)dlen); numToGo = ptran->numlive; ptrn = ptran->trn; for ( j = 0; j < (int)note.numMemnotes; j++) { note.noteSequence = j + 1; MT_LOCK_AIB(); note.aiupdctr = pdbcontext->pmstrblk->mb_aictr; note.ainew = pdbcontext->pmstrblk->mb_ai.ainew; if(pdbcontext->ptlctl) { note.tlWriteBlockNumber = pdbcontext->ptlctl->writeLocation; note.tlWriteOffset = pdbcontext->ptlctl->writeOffset; } else { note.tlWriteBlockNumber = 0; note.tlWriteOffset = 0; } if (pdbpub->qaictl) note.aiwrtloc = pdbcontext->paictl->ailoc + pdbcontext->paictl->aiofst; else note.aiwrtloc = 0; /* bug 20000114-034 by dmeyer in v9.1b */ MT_UNLK_AIB(); for(i=note.numThisNote, ptx = pdata; i > 0; ptrn++) { /* Only copy the transaction if it is in an active state */ if (ptrn->txstate && (ptrn->txstate != TM_TS_ALLOCATED) ) { bufcop (ptx, (TEXT *)ptrn, note.tmsize); ptx += note.tmsize; i--; } } /* Why not just use rlputnote here? */ rlwrite(pcontext, (RLNOTE *)¬e, dlen, pdata); if (rlainote (pcontext, (RLNOTE *)¬e)) { /* write note to ai also. Notice that the ai information which is recorded in the note will change when we do this. */ MT_LOCK_AIB (); rlaiwrt (pcontext, (RLNOTE *)¬e, dlen, pdata, ++pdbcontext->pmstrblk->mb_aictr, pcontext->pusrctl->uc_lstdpend); MT_UNLK_AIB (); } numToGo -= note.numThisNote; if( numToGo > MAX_ENTRIES_PER_NOTE ) note.numThisNote = MAX_ENTRIES_PER_NOTE; else { note.numThisNote = numToGo; dlen = numToGo * note.tmsize; } } /* bug 93-01-21-035: use stVacate instead of stkpop */ stVacate (pcontext, pdsmStoragePool, pdata); /* Write out the ready to commit tx table if there any */ if( pdbcontext->ptrcmtab != NULL ) rlrctwt(pcontext); } /* end rlmemwt */
dsmStatus_t dsmBlobDmp( dsmContext_t *pcontext, /* IN database context */ dsmBlob_t *pBlob, /* IN blob descriptor */ GBOOL silent) /* IN silent except if an error */ { dsmStatus_t returnCode; dbcontext_t *pdbcontext; xDbkey_t xDbkey; /* extended dbkey (area & recid) */ LONG recordSize, segRC; LONG maxRecordSize; dsmBuffer_t *pRecord; /* With the 1 byte indicator */ dsmBuffer_t *pSegTab; /* With the 1 byte indicator */ dsmBuffer_t *pST; /* within pSegTab */ LONG nent; /* number seg tab entries */ LONG segLen; LONG i; LONG remainder; long tl; LONG n_ds = 0, n_ss = 0; dsmBuffer_t pName [] = "bozo"; void printf (...); TRACE_CB(pcontext, "dsmBlobDmp"); pdbcontext = pcontext->pdbcontext; if (pdbcontext->usertype & SELFSERVE) { if (pdbcontext->resyncing || lkservcon(pcontext)) return DSM_S_CTRLC; /* Self-service only */ } xDbkey.dbkey = pBlob->blobId; if (!silent) printf ("\nBlobId: %10ld ", xDbkey.dbkey); returnCode = omIdToArea (pcontext, DSMOBJECT_BLOB, (COUNT)pBlob->blobObjNo, &(xDbkey.area)); if (returnCode) { if (!silent) printf ("omIdToArea for object Type: %ld blobObjNo: %ld returned %ld <--\n", DSMOBJECT_BLOB, pBlob->blobObjNo, returnCode); return returnCode; } pdbcontext->inservice++; maxRecordSize = DSMBLOBMAXLEN + 1; pRecord = (dsmBuffer_t *)utmalloc (maxRecordSize); if (!pRecord) { pdbcontext->inservice--; returnCode = DSM_S_BLOBNOMEMORY; return returnCode; } /* returns size of record if record is found. Returns * a negative number if record is not found. */ recordSize = rmFetchRecord(pcontext, xDbkey.area, xDbkey.dbkey, pRecord, (COUNT)maxRecordSize, 0 /* not continuation */); if (recordSize == 4 && xlng (pRecord) == 0) { pBlob->segLength = 0; returnCode = DSM_S_BLOBDNE; if (!silent) printf ("D.N.E. recordSize: 4, record: 0 0 0 0 <--\n"); } else if (recordSize < 0) { pBlob->segLength = 0; returnCode = (dsmStatus_t) recordSize; if (!silent) printf ("returnCode: %ld <--\n", returnCode); } else { returnCode = DSM_S_BLOBOK; /* Set the total length of the blob */ if (*pRecord == DSMBLOBDATA) { n_ds++; pBlob->totLength = recordSize - 1; } else if (recordSize > 10) pBlob->totLength = xlng (pRecord + 7); else { pBlob->totLength = 0; returnCode = DSM_S_BLOBBAD; } if (!silent) printf ("Length: %10ld Type: %s\n", pBlob->totLength, (char *) ((*pRecord == DSMBLOBDATA) ? "Direct" : (*pRecord == DSMBLOBSEG) ? "Segmented" : "Bad <--")); tl = remainder = pBlob->totLength; if (returnCode == DSM_S_BLOBOK && *pRecord != DSMBLOBDATA) { if (xlng(pRecord+3) == 0) /* Only 1 seg table */ pSegTab = utmalloc (recordSize); else pSegTab = utmalloc (BLOBMAXSEGTAB); if (!pSegTab) { utfree (pRecord); pdbcontext->inservice--; returnCode = DSM_S_BLOBNOMEMORY; return returnCode; } bufcop (pSegTab, pRecord, recordSize); while (returnCode == DSM_S_BLOBOK) { n_ss++; pST = pSegTab + SEGHDR_LEN; nent = xct (pSegTab + 1); if (!silent) printf (" SegTab: %10ld number entries: %d %s\n", xDbkey.dbkey, nent, ((nent < 1 || nent > MAXSEGENT) ? "<--" : "")); if (nent < 1 || nent > MAXSEGENT) { returnCode = DSM_S_BLOBBAD; break; } for (i = 0; i < nent; i++, pST += SEGENT_LEN) { segLen = xct (pST); xDbkey.dbkey = xlng (pST + 2); segRC = rmFetchRecord(pcontext, xDbkey.area, xDbkey.dbkey, pRecord, (COUNT)maxRecordSize, 0); if (segRC <= 0) { printf (" Seg%3d: %10ld returnCode: %d <--\n", i, xDbkey.dbkey, segRC); returnCode = (dsmStatus_t) (segRC ? segRC : DSM_S_BLOBBAD); break; } if (segRC - 1 != xct (pST) || *pRecord != DSMBLOBDATA) { printf (" Seg%3d: %10ld Len: %d ActualLen: %d type: %d <--\n", i, xDbkey.dbkey, xct (pST), segRC - 1, *pRecord); returnCode = DSM_S_BLOBBAD; break; } if (!silent) printf (" Seg%3d: %10ld Len: %d\n", i, xDbkey.dbkey, xct (pST)); n_ds++; remainder -= xct (pST); } /* for i ... < nent */ if (returnCode != DSM_S_BLOBOK) break; xDbkey.dbkey = xlng (pSegTab + 3); if (!silent) printf (" N Seg: %10ld\n", xDbkey.dbkey); if (!xDbkey.dbkey) { break; } returnCode = dbBlobFetch (pcontext, &xDbkey, pSegTab, BLOBMAXSEGTAB, DSMBLOBSEG, pName); } /* while remainder */ if (remainder) printf ("Length error: remainder: %10ld <--\n", remainder); utfree (pSegTab); } /* inital blob segemnt ok */ } /* initial rmfetch ok */ utfree (pRecord); pdbcontext->inservice--; if (!silent) printf ("tl: %10ld ds: %4d ss: %4d\n", tl, n_ds, n_ss); return returnCode; }
int cxDoSplit( dsmContext_t *pcontext, dsmTable_t table, /* Table number the index is on */ FINDP *pfndp, /* parameter block for the FIND */ CXBAP *pbap, /* block access params at the next higher level. */ /* Its descrption is put here */ int leftents) /* number of entry left in the left block by split*/ { CXBLK *pixblk; /* the idx block to be split */ TEXT *pos; TEXT *pend; COUNT len1, len2; CXSPLIT note; int cs; TEXT tmp[MAXDBBLOCKSIZE+MAXKEYSZ]; pixblk = pfndp->pblkbuf; /* get a firm grip on both blocks */ /**** the in use count guaranties that the old block is there */ /* get new block - the right block */ cxGetNewBlock(pcontext, table, pfndp->pkykey->index, pfndp->pkykey->area,pbap); /* decide the split point */ pos = pfndp->position; /* split position */ len1 = pos - pixblk->ixchars; len2 = pixblk->IXLENENT - len1; INITNOTE( note, RL_CXSP1, RL_PHY ); INIT_S_CXSPLIT_FILLERS( note ); /* bug 20000114-034 by dmeyer in v9.1b */ bufcop( &(note.ixhdr1), &(pixblk->ix_hdr), sizeof(note.ixhdr1) ); bufcop( &(note.ixhdr2), &(pixblk->ix_hdr), sizeof(note.ixhdr2) ); note.extracs = 0; /* if (len2 && *pos) if key in split position is compressed */ cs = CS_GET(pos); if (len2 && cs) /* if key in split position is compressed */ { /* the 1st entry in the new block is compressed, we must have the missing part in the note to allow decompression */ /* note.extracs = *pos; */ note.extracs = cs; pend = pixblk->ixchars + pixblk->IXLENENT; if ((MAXIXCHRS - pixblk->IXLENENT) < note.extracs) { /* no space in the block, use tmp area */ bufcop(&tmp[0], pos, len2); bufcop(&tmp[0] + len2, pfndp->pinpkey, note.extracs); pos = &tmp[0]; } else { /* there is space to attach the extra at end of the block data */ bufcop(pend, pfndp->pinpkey, note.extracs); } } note.ixhdr1.ih_lnent = len1; note.ixhdr2.ih_lnent = len2 + note.extracs; note.ixhdr1.ih_nment = leftents; note.ixhdr2.ih_nment -= leftents; /* Do the original block */ rlLogAndDo (pcontext, (RLNOTE *)¬e, pfndp->bufHandle, (COUNT)(len2+note.extracs), (TEXT *)pos); /* and then the new block */ note.rlnote.rlcode = RL_CXSP2; rlLogAndDo (pcontext, (RLNOTE *)¬e, pbap->bufHandle, (COUNT)(len2+note.extracs), (TEXT *)pos); return(0); } /* cxDoSplit */
/* PROGRAM: dsmMandatoryFieldsCachePut - build mandatory field cache and it * is stored in shared memory * * RETURNS: DSM_S_SUCCES * */ dsmStatus_t dsmMandatoryFieldsPut(dsmContext_t *pcontext, struct meta_filectl *pInMetactl, /* new metadata ctl for cache */ struct meta_filectl *pOldmetactl, /* old metadata ctl for cache */ DL_VECT *pdl_vect_in, /* next dl column vector */ DL_VECT *pdl_col_in, /* next dl columns list to use */ int ndl_ent, /* # delayed columns */ int mandtblSize, /* size of mand fld table */ int useCache, /* use shm cache ? */ struct mand *pmand) /* storage for all mand flds */ { dbcontext_t *pdbcontext = pcontext->pdbcontext; dbshm_t *pdbshm = pdbcontext->pdbpub; dsmStatus_t returnCode; SHPTR *pmandhashtbl, qhashentry; struct meta_filectl *pmetactl = NULL; pdbcontext->inservice++; /* postpone signal handler processing */ SETJMP_ERROREXIT(pcontext, returnCode) /* Ensure error exit address set */ if ((returnCode = dsmThreadSafeEntry(pcontext)) != DSM_S_SUCCESS) { returnCode = dsmEntryProcessError(pcontext, returnCode, (TEXT *)"dsmMandatoryFieldsPut"); goto done; } /* get the schema cache latch */ MT_LOCK_SCC (); /* Check if the entry already exists */ dsmMandFindEntry(pcontext, &pmetactl, pInMetactl->fildbk, pInMetactl->filno, FILE_IDENT_DBKEY); if (pmetactl != NULL) { /* entry had already been made */ goto okdone; } /* get ptr to hash table array */ if (pdbshm->qmandctl) pmandhashtbl = (SHPTR *) QP_TO_P(pdbcontext, pdbshm->qmandctl); else /* need to allocate it */ { pmandhashtbl = (SHPTR *) stRent(pcontext, XSTPOOL(pdbcontext, pdbshm->qdbpool), SIZE_MAND_HASH * sizeof(SHPTR)); pdbshm->qmandctl = P_TO_QP(pcontext, pmandhashtbl); } /* allocate storage in shm */ pmetactl = (struct meta_filectl *)stRent(pcontext, XSTPOOL(pdbcontext, pdbshm->qdbpool), (unsigned)(sizeof(struct meta_filectl) + mandtblSize)); pmetactl->fildbk = pInMetactl->fildbk; pmetactl->filno = pInMetactl->filno; pmetactl->nmand = pInMetactl->nmand; pmetactl->schemavers = pInMetactl->schemavers; if ( (useCache != MANB_USECACHE_NONE) && (mandtblSize > 0) ) { bufcop(pmetactl->mand, pmand, (int) mandtblSize); } if ((useCache == MANB_USECACHE_PHYSICAL) && (pOldmetactl != NULL)) { pOldmetactl->filno = 0; pOldmetactl->fildbk = 0; } /* Chain this structure in shared memory. The assumption is that an entry for this fildbk does not already exist on the cache. */ qhashentry = pmandhashtbl[ABS(pmetactl->filno) % SIZE_MAND_HASH]; pmetactl->qnext = qhashentry; pmandhashtbl[ABS(pmetactl->filno) % SIZE_MAND_HASH] = P_TO_QP(pcontext, pmetactl); DEBUG_FPRINTF(pmetactl, "dbmanb (chained to sh mem):"); okdone: MT_UNLK_SCC (); returnCode = DSM_S_SUCCESS; done: dsmThreadSafeExit(pcontext); pdbcontext->inservice--; return returnCode; }