/* PROGRAM: dsmRLwriter - Recovery log block writer thread * * * RETURNS: DSM_S_SUCCESS */ dsmStatus_t DLLEXPORT dsmRLwriter( dsmContext_t *pcontext) { dsmStatus_t returnCode = 0; #if OPSYS==WIN32API if (fWin95) return -1; #endif SETJMP_ERROREXIT(pcontext, returnCode) /* Ensure error exit address set */ if ((returnCode = dsmThreadSafeEntry(pcontext)) != DSM_S_SUCCESS) { returnCode = dsmEntryProcessError(pcontext, returnCode, (TEXT *)"dsmRLwriter"); goto done; } pcontext->pusrctl->uc_usrtyp = BIW; pcontext->pdbcontext->prlctl->abiwpid = pcontext->pusrctl->uc_pid; pcontext->pdbcontext->prlctl->qbiwq = QSELF(pcontext->pusrctl); rlbiclean(pcontext); if(pcontext->pdbcontext->pdbpub->shutdn) returnCode = DSM_S_SHUT_DOWN; done: dsmThreadSafeExit(pcontext); return returnCode; }
/* PROGRAM: dbXAinit - Initialize the global xid free list * * * RETURNS: DSM_S_SUCCESS on success */ dsmStatus_t dbxaInit(dsmContext_t *pcontext) { dbcontext_t *pdbcontext = pcontext->pdbcontext; dbshm_t *pdbshm = pdbcontext->pdbpub; LONG maxxids,amount; int i; dbxaTransaction_t *pxids, *plastxid = NULL; if (!pdbshm->maxxids) return 0; amount = pdbshm->maxxids; for(pdbshm->maxxids = 0; pdbshm->maxxids < amount; pdbshm->maxxids += 64 ) { /* Allocate the xids in chunks of 64 */ pxids = (dbxaTransaction_t *) stGet(pcontext, XSTPOOL(pdbcontext, pdbshm->qdbpool), 64 * sizeof(dbxaTransaction_t)); if(!pxids) { MSGD_CALLBACK(pcontext, "%gInsuffient storage to allocate xid table."); } if(plastxid) { /* Make last of previous batch of 64 point to this batch */ plastxid->qnextXID = P_TO_QP(pcontext,pxids); } if(!pdbshm->qxidFree) { pdbshm->qxidFree = P_TO_QP(pcontext,pxids); } for(i = 0; i < 64;i++,pxids++) { QSELF(pxids) = P_TO_QP(pcontext,pxids); pxids->qnextXID = P_TO_QP(pcontext,pxids + 1); } plastxid = pxids--; plastxid->qnextXID = 0; } return 0; }
/* PROGRAM: dbxaFree - Return the specified global transaction structure to the free list. RETURNS: nothing */ DSMVOID dbxaFree(dsmContext_t *pcontext, dbxaTransaction_t *ptran) { dbshm_t *pdbshm = pcontext->pdbcontext->pdbpub; ptran->flags = 0; ptran->trid = 0; ptran->referenceCount = 0; ptran->numSuspended = 0; ptran->lastRLblock = 0; ptran->lastRLoffset = 0; pdbshm->qxidAlloc = ptran->qnextXID; ptran->qnextXID = pdbshm->qxidFree; pdbshm->qxidFree = QSELF(ptran); return; }
/* PROGRAM: dbxaAllocate - Allocate a global transaction structure from the free list. Assumes the caller has locked the list before calling. RETURNS: pointer to global tx structure */ dbxaTransaction_t *dbxaAllocate(dsmContext_t *pcontext) { dbxaTransaction_t *pxaTran; dbcontext_t *pdbcontext = pcontext->pdbcontext; dbshm_t *pdbshm = pdbcontext->pdbpub; pxaTran = XXID(pdbcontext,pdbshm->qxidFree); if(pxaTran) { pdbshm->qxidFree = pxaTran->qnextXID; pxaTran->qnextXID = pdbshm->qxidAlloc; pdbshm->qxidAlloc = QSELF(pxaTran); } else { /* If the free list is empty we should wait for one to become free */ ; } return pxaTran; }
/* PROGRAM: rlaiseto - initialize aictl and buffers */ DSMVOID rlaiseto (dsmContext_t *pcontext) { dbcontext_t *pdbcontext = pcontext->pdbcontext; dbshm_t *pdbpub = pdbcontext->pdbpub; AICTL *paictl; BKTBL *pbktbl; AIBUF *paibuf = (AIBUF *)0; AIBUF *pn; int i; /* *** TODO: there is a memory leak when peforming aimage begin on a * database that has 2phase on already rlaiseto is called twice. Not * a big deal, but something to remember. */ if (pdbcontext->paictl != NULL) { /* memory leak! */ } /* allocate the ai control structure */ paictl = (AICTL *)stGet(pcontext, (STPOOL *)QP_TO_P(pdbcontext, pdbpub->qdbpool), sizeof(AICTL)); pdbpub->qaictl = P_TO_QP(pcontext, paictl); pdbcontext->paictl = paictl; /* initialize blocksize information based on masterblock info */ paictl->aiblksize = pdbcontext->pmstrblk->mb_aiblksize; paictl->aiFileType = BKAI; /* initialize block size log and mask constants for quick calculations */ paictl->aiblklog = bkblklog(paictl->aiblksize); paictl->aiblkmask = (ULONG)0xFFFFFFFF << paictl->aiblklog; /* * allocate buffer for ai writer to use for writing. This buffer is * used for making a copy of the current buffer prior to writing * it so that the ai writer can be writing while others are storing * more data in the next output buffer. Also used during extent switches. */ pbktbl = &paictl->aiwbktbl; QSELF (pbktbl) = P_TO_QP(pcontext, pbktbl); pbktbl->bt_raddr = -1; pbktbl->bt_dbkey = -1; /* BUM - Assuming aiFileType < 256 */ pbktbl->bt_ftype = (TEXT)paictl->aiFileType; if ( paictl->aiFileType == BKAI ) { paictl->aiArea = rlaiGetNextArea(pcontext, 1); if( pdbcontext->pmstrblk->mb_aibusy_extent ) { paictl->aiArea = pdbcontext->pmstrblk->mb_aibusy_extent; } } else { paictl->aiArea = DSMAREA_TL; } pbktbl->bt_area = paictl->aiArea; bmGetBufferPool(pcontext, pbktbl); /* must have at least one ai buffer */ if (pdbpub->argaibufs < 1) pdbpub->argaibufs = 1; /* allocate a ring of output ai buffer control blocks */ pn = NULL; for (i = pdbpub->argaibufs; i > 0; i--) { paibuf = (AIBUF *)stGet (pcontext, (STPOOL *)QP_TO_P(pdbcontext, pdbpub->qdbpool), sizeof(AIBUF)); QSELF (paibuf) = P_TO_QP(pcontext, paibuf); if (pn) { /* set previous buffer's link to next buffer in chain */ pn->aiqnxtb = QSELF (paibuf); } else { /* this is the first, current, and next to write buffer */ paictl->aiqbufs = QSELF (paibuf); paictl->aiqcurb = QSELF (paibuf); paictl->aiqwrtb = QSELF (paibuf); } pn = paibuf; } /* link the last one to the first one */ paibuf->aiqnxtb = paictl->aiqbufs; /* now allocate the ai block buffers themselves */ pn = XAIBUF(pdbcontext, paictl->aiqbufs); for (i = pdbpub->argaibufs; i > 0; i--) { pbktbl = &(pn->aibk); QSELF (pbktbl) = P_TO_QP(pcontext, pbktbl); pbktbl->bt_raddr = -1; pbktbl->bt_dbkey = -1; pbktbl->bt_area = paictl->aiArea; /* BUM - Assuming UCOUNT aiFileType < 256 */ pbktbl->bt_ftype = (TEXT)paictl->aiFileType; bmGetBufferPool(pcontext, pbktbl); pn = XAIBUF(pdbcontext, pn->aiqnxtb); } } /* rlaiseto */