Пример #1
0
/* PROGRAM: wrtmsg - do the correct type of write call depending on opsys
 *
 * RETURNS: DSMVOID
 */
LOCALF DSMVOID
wrtmsg (
        dsmContext_t *pcontext,
        int           fd,
	TEXT         *msgbuf,
	int           msglen)
{
    int    ret=0;         /* return code */
    int    retrycnt = 0;
#if OPSYS==WIN32API
    /* Do STDOUT properly to allow redirection by parent process */
    if (1 == fd)
        {
            WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),
                      msgbuf, msglen, &ret, NULL);
            return;
        }
#endif  /* OPSYS == WIN32API */
retry:
    errno = 0;
    ret = write(fd, (char *) msgbuf, msglen);
               
    if (ret != msglen)
    {
        switch (errno)
        {
         case EFBIG:
                MSGN_CALLBACK(pcontext, utMSG178, "wrtmsg");
                break;
         case ENOSPC:
                MSGN_CALLBACK(pcontext, utMSG179);
                break;
         default:
            /* interrupted io to screen? */
            if (errno!=EIO && fd==1 && ++retrycnt < 100 && ret >= 0)
            {  msglen -= ret; msgbuf += ret; goto retry;  }
/* We get EINTR errno when we received a signal while doing a synchronous
   write.  For some OSs
   the write fails once and subsequently succeeds, while on others it
   forever after returns -1 with errno set to EINTR, thus the retry
   count */
            if( ++retrycnt < 100 && errno == EINTR && ret == -1 )
                goto retry;
        }
    }
 
    return;

} /* end wrtmsg */
Пример #2
0
/*
 * PROGRAM: rlaiCompare - compare the "on disk" size with the "as written"
 *                        size of the ai file 
 *
 * This function compares the size of the ai file on disk with the size as
 * written that is stored in the header. The "on-disk" size is determined 
 * using bkflen (passed in) which returns the number of blocks. The size 
 * as stored in the header is the number of bytes. To do the comparison
 * we'll expand the "as stored" size to blocks and then round up by one 
 * block.
 *
 * RETURNS; 0 if files compare, 1 if they do not
 */
LOCALF int
rlaiCompare(
	dsmContext_t *pcontext,
	AIBLK        *paiblk, /* ptr to 1st ai block in ai file or extent */
	AICTL        *paictl) /* pointer to ai control structure */
{
    dbcontext_t     *pdbcontext = pcontext->pdbcontext;
    LONG onDiskBlocks;
    LONG asWrittenBlocks;

    onDiskBlocks = paictl->aisize / pdbcontext->pmstrblk->mb_aiblksize;
    
    if (paiblk->aifirst.aieof % pdbcontext->pmstrblk->mb_aiblksize)
    {
        asWrittenBlocks = 
            paiblk->aifirst.aieof / pdbcontext->pmstrblk->mb_aiblksize + 1;
    }
    else
    {
        asWrittenBlocks = 
            paiblk->aifirst.aieof / pdbcontext->pmstrblk->mb_aiblksize;
    }

    
    if ( onDiskBlocks < asWrittenBlocks )
    {
        /* Issue a message indicating that we have an incomplete ai file */
	MSGN_CALLBACK(pcontext, rlMSG145, asWrittenBlocks, onDiskBlocks);
        return -1;
    }
    return 0;
}
Пример #3
0
/*
 * PROGRAM: rlaiblksize - validate ai file blocksize with ai subsystem
 *
 * This function compares the blocksize stored in the first ai block with
 * the blocksize stored in the ai control structure.  If they do not match
 * then we cannot continue.  This code does not issue a fatal exception, but
 * it is important that no I/O be done to the ai file or it will be damaged.
 *
 * RETURNS; 0 if blocksize matches, 1 if it does not match
 */
LOCALF int
rlaiblksize(
	dsmContext_t	*pcontext,
	AIBLK		 *paiblk, /* ptr to 1st ai block in ai file or extent */
	AICTL		*paictl) /* pointer to ai control structure */
{
    
    if (paiblk->aifirst.aiblksize == paictl->aiblksize)
    {
	/* blocksize matches should be ok */
	return 0;
    }
    else
    {
	/* Invalid blocksize in ai file found %d, expected %l */
	MSGN_CALLBACK(pcontext, rlMSG060,
                      paiblk->aifirst.aiblksize, paictl->aiblksize);
	return 1;
    }
} /* rlaiblksize */
Пример #4
0
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 );
}
Пример #5
0
/* PROGRAM: rlaiopn - open the	after-image (transaction-log) file
 *
 *
   Updates:
	    allocates an aictl
	    aictl.aibktbl will be setup.  If the ai is opened for output,
			  then that buffer will contain the current output
			  block of the ai file (the last block containing
			  valid data).	If the ai is opened for input,
			  then that buffer will contain the first blk of
			  the ai file.
	    aictl.aimode  will be set appropriately
	    aictl.aisize - physical EOF
	    aictl.ailoc  - input: start of file, output: logical EOF
	    aictl.aiofst - offset of ailoc within current ai block

   Some of the updates is diffrent for an off-line Transaction-log file
   which doe not use the noral AI mechanism, but is very similar to it.
									
 * NOTE: rlaiopn can be called by normal progress to open the .ai file	*
 *	 for input or output.						*
 *									*
 *	When being called for output, The caller should check		*
 *	pmstrblk->mb_ai.ainew and should not call rlaiopn if it is 0.	*
 *
 * RETURNS: 0 - on success
 *         -1 - on failure
 *          1 - only a partial ai file was detected
 */
int
rlaiopn(
	dsmContext_t	*pcontext,
	int  aimode,        /* AIINPUT or AIOUTPUT	*/
	TEXT *pname,        /* name of the .ai file	*/
	int  execmode,      /* non-zero => open for input with intent to rf */
	int  tmplog,        /* 1 for off-line TL file.   */
        int  retry)         /* 1 - retry active, 0 - retry inactive */  
{
    dbcontext_t     *pdbcontext = pcontext->pdbcontext;
    MSTRBLK *pmstr = pdbcontext->pmstrblk;
    AICTL	*paictl;
    AIBLK	*paiblk;
    BKTBL	*pbktbl;
struct  bkftbl  *pbkftbl = (struct bkftbl *)NULL;
    COUNT 	 buffmode;
    LONG	 ret;
    TEXT         timeString[TIMESIZE];
    UCOUNT       returnCode = 0;

    if (aimode == AIOUTPUT && pmstr->mb_aisync==UNBUFFERED && !tmplog)
	buffmode = UNBUFFERED;
    else buffmode = BUFFERED;

    /* allocate all buffers and control structures */
    rlaiseto (pcontext);

    /* get local pointer to global structure */
    paictl = pdbcontext->paictl;

    /* get the ai file size in bytes */
    if( pmstr->mb_aibusy_extent > (TEXT)0 )
    {
	/* using an extent, get the length of busy extent */
        paictl->aisize = rlaielen(pcontext, paictl->aiArea);
    }
    else
    {
	/* *** TODO: bkflen returns size in terms of database blocks */
	/* using a named file get the length directly */
        paictl->aisize = bkflen(pcontext, paictl->aiArea) *
            pdbcontext->pmstrblk->mb_aiblksize;
    }

    /* read the first ai block into current buffer */
    pbktbl = &(XAIBUF(pdbcontext, paictl->aiqcurb)->aibk);
    pbktbl->bt_dbkey = 0L;
    bkRead(pcontext, pbktbl);
    paiblk = XAIBLK(pdbcontext, pbktbl->bt_qbuf);

    /* Make sure we have a compatible version                */
    if (rlaiVersion(pcontext, paiblk))
    {
	/* AI file cannot be used with this database */
	MSGN_CALLBACK(pcontext, rlMSG094);
	return -1;
    }

    /* make sure blocksize matches database */
    if (rlaiblksize(pcontext, paiblk, paictl))
    {
	/* AI file cannot be used with this database */
	MSGN_CALLBACK(pcontext, rlMSG094);
	return -1;
    }

    /* Make sure the file is complete, BUG# 20000510-002 */
    if ( rlaiCompare(pcontext, paiblk, paictl) )
    {
        /* File lengths don't compare for whatever reason.
           Prohibit the ai seq num from being incremented so if the user 
           happens to find the correct, full ai file they can retry. */

        returnCode = 1;
    }

    /* setup for reading (rollforward) or writing (logging) to file */
    if (aimode == AIINPUT)
    {
	if ( execmode )
	{
         if ( retry )
            {
                /* Retry is activate - check extent status */
                if( paiblk->aifirst.aiextstate == AIEXTEMPTY )
                {
                    /* That's because this is an empty ai extent */
                    MSGN_CALLBACK(pcontext, rlMSG058);
                    return -1;
                }
                /* Ensure ai in proper sequence. */
                pmstr->mb_aiseq = pmstr->mb_aiseq ? pmstr->mb_aiseq : 1;
                if (paiblk->aifirst.aidates.aigennbr != pmstr->mb_aiseq)
                {
                    /* This ai file is not in the proper sequence for rretry. */
     /* Expected ai file number %l but file sepecified is %l in sequence. */
                    MSGN_CALLBACK(pcontext, rlMSG140, pmstr->mb_aiseq,
                                  paiblk->aifirst.aidates.aigennbr);
                    return -1;
                }
            }
            else if  (paiblk->aifirst.lstmod != pmstr->mb_lstmod )
	    {
		/* the time stamps dont match */
		if( paiblk->aifirst.aiextstate == AIEXTEMPTY )
		{
		    /* That's because this is an empty ai extent */
		    MSGN_CALLBACK(pcontext, rlMSG058);
		}
		else
		{
                    /* Ensure ai in proper sequence. */
                    pmstr->mb_aiseq = pmstr->mb_aiseq ? pmstr->mb_aiseq : 1;
                    if (paiblk->aifirst.aidates.aigennbr != pmstr->mb_aiseq)
                    {
                        /* ai file is not in the proper sequence for rollf. */
    /* "Expected ai file number %l but file sepecified is %l in sequence." */
                        MSGN_CALLBACK(pcontext, rlMSG140, pmstr->mb_aiseq,
                                      paiblk->aifirst.aidates.aigennbr);
                    }
		    MSGN_CALLBACK(pcontext, rlMSG001,
                                uttime((time_t *)&pmstr->mb_lstmod, timeString,
                                       sizeof(timeString)));
		    MSGN_CALLBACK(pcontext, rlMSG002,
		                  uttime((time_t *)&paiblk->aifirst.lstmod,
                                         timeString, sizeof(timeString)));
		    MSGN_CALLBACK(pcontext, rlMSG003);
		}
		return -1;
	    }
	}

	/* Init for reading from beginning of file */
	paictl->aiofst = paiblk->aihdr.aihdrlen;
	paictl->ailoc = pbktbl->bt_dbkey;
	paictl->aimode = AIINPUT;
    }
    else
    {
	/* file is being opened for output (logging) check the dates */
	if (paiblk->aifirst.aidates.aiopen != pmstr->mb_ai.aiopen)
        {
	    /* time stamps dont match */
            if( (pname == NULL) && 
                (pdbcontext->pmstrblk->mb_aibusy_extent > (TEXT)0) )
            {
		/* Means its an ai extent file */
		ret = bkGetAreaFtbl(pcontext, paictl->aiArea,&pbkftbl);
		pbkftbl += pdbcontext->pmstrblk->mb_aibusy_extent - 1;
                pname = XTEXT(pdbcontext, pbkftbl->ft_qname);
	    }
	    MSGN_CALLBACK(pcontext, rlMSG045, pname);
	    return -1;
	}

	/* get the current date/time and put into ai block */
	time(&paiblk->aifirst.aidates.aiopen);

	/* put time into masterblock */
	pmstr->mb_ai.aiopen = paiblk->aifirst.aidates.aiopen;

	/* write out both blocks */
	bkWrite(pcontext, pbktbl, UNBUFFERED);
	bmFlushMasterblock(pcontext);

	/* initialize ai control structure for logging */
        paictl->aiupdctr = paiblk->aifirst.aifirstctr;
        paictl->ailoc = pbktbl->bt_dbkey;
        paictl->aiofst = paiblk->aihdr.aihdrlen;
	paictl->aimode = AIOUTPUT;
    }
    /* done. ready to go */

    if ( returnCode )
    {
        /* detected partial ai file */
        return (1);
    }
    else
    {
        /* success */
        return (returnCode);
    }
}
Пример #6
0
/* PROGRAM: dsmDatabaseProcessEvents - perform xxx processing
 *
 * NOTE: Quiet points and tmdelayed commit are supported here
 * 
 * RETURNS: DSM_S_SUCCESS
 *          DSM_S_INVALID_USER
 *          DSM_S_SHUT_DOWN on EXBAD or EXGOOD
 */
dsmStatus_t
dsmDatabaseProcessEvents(
        dsmContext_t *pcontext)
{
    dbcontext_t *pdbcontext = pcontext->pdbcontext;
    dbshm_t     *pdbshm     = pdbcontext->pdbpub;
    usrctl_t    *pusr       = pcontext->pusrctl;
    mstrblk_t   *pmstr;
    dsmStatus_t  returnCode;

#if OPSYS==WIN32API
    if (fWin95)
        return -1;
#endif

    pdbcontext->inservice++;  /* "post-pone" signal handling while in DSM API */
 
    SETJMP_ERROREXIT(pcontext, returnCode) /* Ensure error exit address set */

    if ((returnCode = dsmThreadSafeEntry(pcontext)) != DSM_S_SUCCESS)
    {
        returnCode = dsmEntryProcessError(pcontext, returnCode,
                      (TEXT *)"dsmDatabaseProcessEvents");
        goto done;
    }

    /* Check for quiet point command requests */
    if (pdbshm->quietpoint == QUIET_POINT_REQUEST)
    {
        /* Shut off update activity for the quiet point */
        rlTXElock(pcontext,RL_TXE_EXCL,RL_MISC_OP);
        MT_LOCK_MTX();
        pmstr = pdbcontext->pmstrblk;

        /* Switch after imaging extent if there are ai extents */
        if( rlaiqon(pcontext) && pmstr->mb_aibusy_extent > 0 )
        {
            MT_LOCK_AIB();
            if (rlaiswitch(pcontext, (int)RLAI_NEW, 1) )
            {
                MT_UNLK_AIB();
                /* Unable to switch to new ai extent */
                MSGN_CALLBACK(pcontext, drMSG205);
                if ( MTHOLDING(MTL_MTX) )
                     MT_UNLK_MTX();

                if ( pusr->uc_txelk )
                    rlTXEunlock(pcontext);
                goto done;
            }
            MT_UNLK_AIB();
        }

        /* Flush the buffer pool and bi buffers */
        rlbiflsh(pcontext,RL_FLUSH_ALL_BI_BUFFERS);
 
        /* At this point, the quiet point is in place */
        MSGN_CALLBACK(pcontext, drMSG402);
        pdbshm->quietpoint = QUIET_POINT_ENABLED;
        while(pdbshm->quietpoint == QUIET_POINT_ENABLED &&
              !pdbshm->shutdn)
        {
            utsleep(1);
        }
        MT_UNLK_MTX();
        rlTXEunlock(pcontext);        /* Release transaction end lock */

        /* At this point, normal operations can return */
        MSGN_CALLBACK(pcontext, drMSG403);
        pdbshm->quietpoint = QUIET_POINT_NORMAL;       
    }
 
    /* Process delayed commit (-Mf) */
    tmchkdelay(pcontext, 0);
    /* Check if table locking can be shut off    */
    lkTableLockCheck(pcontext);

    returnCode = DSM_S_SUCCESS;

done:
    dsmThreadSafeExit(pcontext);
    pdbcontext->inservice--;  /* re-allow signal handling */

    return returnCode;

}  /* end dsmDatabaseProcessEvents */
Пример #7
0
/* PROGRAM: bkioCreateLkFile -- lock the database in desired mode.
 *
 *    Create a .lk file holding the following information:
 *      a.) The mode the db is in BKIO_LKSNGL | BKIO_LKMULT
 *      b.) The process ID of the starter of the db
 *      c.) The hostname of the machine where the db was started
 *
 *
 * RETURNS:
 *	0		database locked in requested mode.
 *	BKIO_LKSNGL	database currently locked in single-user mode,
 *			request denied.
 *	BKIO_LKMULT	database currently locked in multi-user mode,
 *			request denied.
 *      BKIO_LKSTARTUP  database is in the process of starting up
 *                      request denied.
 *
 */
int
bkioCreateLkFile (
        dsmContext_t    *pcontext,
        int		 mode,		/* desired usage mode, either
		            		   BKIO_LKSNGL or BKIO_LKMULT */
        TEXT		*dbname,	/* name of database */
        int             dispmsg)	/* if true, then display a message */

{

    TEXT	 namebuf[MAXPATHN+1];
    TEXT	 dbnamebuf[MAXPATHN+1];
    TEXT	 nodebuf[BKIO_NODESZ];
    int		 ret = 0;
    ULONG	 spid = 0;
    int          errorStatus = 0;
    int          bytesWritten;
    LONG         retWrite;
    LONG         retMakePath = 0;
    int		 lockret = 1; 
    int		 wmode = mode;
    fileHandle_t lkhandle;
    int          i;
    int          local = 0;
    dbcontext_t *pdbcontext = pcontext->pdbcontext;

    /* see if the *.lk file already exists and is valid */
    if(pdbcontext->pdatadir)
       utmypath(namebuf,pdbcontext->pdatadir,dbname,
                (TEXT *)".lk");
    else
        retMakePath = utMakePathname(namebuf, sizeof(namebuf), dbname, 
                                     (TEXT *)".lk");
    if (retMakePath != DBUT_S_SUCCESS)
    {
        /* Report error */
        dbUserError(pcontext, retMakePath, errno, 0,
                    (DSMVOID *)NULL, (DSMVOID *)NULL);
    }
    if(pdbcontext->pdatadir)
        utmypath(dbnamebuf,pdbcontext->pdatadir,dbname,
                (TEXT *)".db");
    else
        retMakePath = utMakePathname(dbnamebuf, sizeof(dbnamebuf), dbname, 
                                     (TEXT *)".db");
    if (retMakePath != DBUT_S_SUCCESS)
    {
        /* Report error */
        dbUserError(pcontext, retMakePath, errno, 0,
                    (DSMVOID *)NULL, (DSMVOID *)NULL);
    }

    ret = bkioTestLkFile(pcontext, dbname);

    if (ret)
    {   
        switch(ret) 
        {
	    case BKIO_LKSNGL:
	        if(dispmsg)
	             MSGN_CALLBACK(pcontext, bkMSG005, dbname);
	        break; /* db in use single-user */
	    case BKIO_LKMULT:
	    case BKIO_LKSTARTUP:
	        if(dispmsg)
	 	     MSGN_CALLBACK(pcontext, bkMSG006, dbname);
	        break; /* db in use multi-user */
	    case BKIO_LKNOHOST:
	         MSGN_CALLBACK(pcontext, bkMSG007, namebuf);
	         MSGN_CALLBACK(pcontext, bkMSG008);
                 MSGN_CALLBACK(pcontext, bkMSG009);
                 MSGN_CALLBACK(pcontext, bkMSG010);
	         MSGN_CALLBACK(pcontext, bkMSG011, namebuf); break;
            case BKIO_LKTRUNC:
                break;  /* message was put out by bkioTestLkFile */
	    default:	 FATAL_MSGN_CALLBACK(pcontext, bkFTL009, dbname); break;
	  }
    }
    else
    {	
        /* open failed, try to creat it */
        /* 19990525-028 - small window of opportunity for two brokers    */
        /* to start on same database. Replace utOsCreat call with        */
        /* utOsOpen.                                                     */
        /* lkhandle = utOsCreat((TEXT *)namebuf, 0444, 0, &errorStatus); */
      
        /* 19990525-028 second try. Can only call utOsOpen if not on NFS */
        /*              See bug for details.                             */

        local = bkioIsLocalFile(pcontext,dbnamebuf);

        /* if .lk file is on NFS drive */
        if (local == 0)
        {
            lkhandle = utOsCreat((TEXT *)namebuf, 0444, 0, &errorStatus); 
        }
        else
        {
#if OPSYS == WIN32API
            lkhandle = utOsOpen((TEXT *)namebuf,
                                (O_CREAT | O_EXCL | O_WRONLY), 
                                CREATE_DATA_FILE, 0, &errorStatus);

#else
            lkhandle = utOsOpen((TEXT *)namebuf,
                                (O_CREAT | O_EXCL | O_WRONLY), 
                                0444, 0, &errorStatus);
#endif
        }

        if (lkhandle == INVALID_FILE_HANDLE) 
        {
            /* cant open */
            MSGN_CALLBACK(pcontext, bkMSG002, namebuf, errorStatus);
            return -1;
        }

        /* Remove this conditional once file locking is implemented for UNIX */
#if OPSYS == WIN32API
        /* attempt to get a lock in the .lk file itself */
        lockret = utLockLkFile(lkhandle);
#endif

        /* if we got the lock, write out the mode, pid and nodename */
        if (lockret)
        {
            if (mode == BKIO_LKMULT)
            {
                wmode = BKIO_LKSTARTUP;
            }
        
            /* write out the mode the database is in */
            retWrite = utWriteToFile(lkhandle, 0, (TEXT *)&wmode,
                                 sizeof(int), &bytesWritten, &errorStatus);

            /* get the process id and put that into the file */
            spid = utgetpid ();
            retWrite = utWriteToFile(lkhandle, sizeof(int), (TEXT *)&spid,
                                 sizeof(int), &bytesWritten, &errorStatus);

            stnclr(nodebuf,BKIO_NODESZ); /*fill with nulls*/
    
            /* get the hostname and put it into the file */
            ret = utgethostname((TEXT *)nodebuf,BKIO_NODESZ - 1);
            if (ret < 0)
            {
                /* if the utgethostname call failed, write out an ampty
                   hostname, that will cause the .lk file checking to be 
                   more strict
                */
                stnclr(nodebuf,BKIO_NODESZ); /*fill with nulls*/
            }
            retWrite = utWriteToFile(lkhandle,2*(sizeof(int)),nodebuf, 
                              BKIO_NODESZ, &bytesWritten, &errorStatus);

            /* Save the handle in the lkstr structure */
            for (i = 0; i < 240; i++)
            {
                if (lkstr[i].lkHandle == (fileHandle_t)0)
                {
                    /* we found an empty slot, populate it */
                    lkstr[i].lkHandle = lkhandle;
                    lkstr[i].nameCrc = 
                          calc_crc((UCOUNT)0, namebuf, (COUNT)stlen(namebuf));
                    break;
                }
            }

        }
        else
        {
            /* we did no succeed in locking the .lk file */
	    utOsClose(lkhandle,0);
            MSGN_CALLBACK(pcontext, bkMSG131, namebuf, errorStatus);
            return -1;
        }
    }
    return(ret);
}
Пример #8
0
/* PROGRAM: bkioVerifyLkFile - verify that the .lk file is valid with the
 *                           passed in pid.
 *
 *
 * RETURNS: 0 - lk is valid
 *         -1 - lk is invalid
 */
int
bkioVerifyLkFile(
        dsmContext_t *pcontext,
        int           pid,		/* .lk creators pid */
        TEXT         *dbname)		/* basename for the .lk file */
{
    LONG	  ret;	                /* return for utReadFromFile() */
    int		  status =0;		/* value returned */
    int		  errorStatus = 0;
    TEXT          namebuf[MAXPATHN+1];
    TEXT          nodebuf[BKIO_NODESZ];
    TEXT          snodebuf[BKIO_NODESZ];
    int           spid = 0;
    LONG          retMakePath = 0;
    int           bytesRead;
    int           lockret = 0;
    int           needopen = 0;
    UCOUNT        nameCrc;
    fileHandle_t  lkhandle = (fileHandle_t) -1;
    int           i;
    dbcontext_t   *pdbcontext = pcontext->pdbcontext;

    if(pdbcontext->pdatadir)
        utmypath(namebuf,pdbcontext->pdatadir,dbname,
                (TEXT *)".lk");
    else
        retMakePath = utMakePathname(namebuf, sizeof(namebuf), dbname, 
                                     (TEXT *)".lk");
    if (retMakePath != DBUT_S_SUCCESS)
    {
        /* Report Error */
        dbUserError(pcontext, retMakePath, errno, 0,
                    (DSMVOID *)NULL, (DSMVOID *)NULL);
    }

    nameCrc = calc_crc((UCOUNT)0, namebuf, (COUNT)stlen(namebuf));

    /* find the handle for the lkfile */
    for (i = 0; i < 240; i++)
    {
        if ((lkstr[i].nameCrc == nameCrc) && 
            (lkstr[i].lkHandle != (fileHandle_t)0))
        {
            lkhandle = lkstr[i].lkHandle;
            break;
        }
    }

    /* if we don't have a valid file handle, open the lock file and get one */
    if (lkhandle == (fileHandle_t) -1)
    {
        /* note that we needed to open the lock file */
        needopen = 1;
    
        /* get the absolute path of the .lk file */

        lkhandle = utOsOpen((TEXT *)namebuf, OPEN_R, DEFLT_PERM, OPEN_SEQL,
                                                            &errorStatus);
    
        if (lkhandle == INVALID_FILE_HANDLE)
        {
            /* failed to open the .lk file, return the failure */
            MSGN_CALLBACK(pcontext, bkMSG100,namebuf,errorStatus);
            return -1;
        }
    }

    /* Try to lock the lock file - if we get a lock, then the .lk file
     * is not valid.
    */
    

/* Remove this conditional once file locking is implemented for UNIX */
#if OPSYS == WIN32API
    lockret = utLockLkFile(lkhandle);
#endif

    if (lockret)
    {
        /* we got the lock so the old .lk file must have been invalid */
        MSGN_CALLBACK(pcontext, bkMSG132, namebuf, errorStatus);
        return -1;
    }
    
    /* now lets read the .lk file */
    /* read the past the mode from the .lk file */
    ret = utReadFromFile(lkhandle, 0, (TEXT *)&spid, sizeof(int),
                         &bytesRead, &errorStatus);
    if (bytesRead != sizeof(int))
    {
        /* read failed.  Either the file is too short, or read gave an
           error.  Regardless, we need to shutdown */
        MSGN_CALLBACK(pcontext, bkMSG101,"MODE",namebuf,errorStatus);
        utOsClose(lkhandle,OPEN_SEQL);
        return -1;
    }

    /* read the pid from the .lk file */
    ret = utReadFromFile(lkhandle, sizeof(int), (TEXT *)&spid,sizeof(int),
                         &bytesRead, &errorStatus);
    if (bytesRead != sizeof(int))
    {
        /* read failed.  Either the file is too short, or read gave an
           error.  Regardless, we need to shutdown */
        MSGN_CALLBACK(pcontext, bkMSG101,"PID",namebuf,errorStatus);
        utOsClose(lkhandle,OPEN_SEQL);
        return -1;
    }

    /* read the hostname from the .lk file */
    ret = utReadFromFile(lkhandle, 2 * sizeof(int), snodebuf,BKIO_NODESZ,
                         &bytesRead, &errorStatus);
    if (bytesRead != BKIO_NODESZ)
    {
        /* read failed.  Either the file is too short, or read gave an
           error.  Regardless, we need to shutdown */
        MSGN_CALLBACK(pcontext, bkMSG101,"HOSTNAME",namebuf,errorStatus);
        utOsClose(lkhandle,OPEN_SEQL);
        return -1;
    }

    /* get the systems hostname don't worry about failures, the 
       stpcmp will verify the host for us later */
    ret = utgethostname((TEXT *)nodebuf,BKIO_NODESZ - 1);

    /* now that we have read the .lk file, verify it's a valid one */
    if (pid == spid)
    {
        /* pids match, now check the hostname */
        if (stpcmp(nodebuf,snodebuf) != 0)
        {
            /* hostnames don't match.  .lk file is invalid for this server */
            MSGN_CALLBACK(pcontext, bkMSG102,namebuf,snodebuf,nodebuf);
            status = -1;
        }
    }
    else
    {
        /* pids don't match.  .lk file is invalid for this server */
        MSGN_CALLBACK(pcontext, bkMSG103,namebuf,spid,pid);
        status = -1;
    }

    if (needopen)
    {
        utOsClose (lkhandle, OPEN_SEQL);
        lkhandle = (fileHandle_t) -1;
    }
    return(status);
}
Пример #9
0
/* PROGRAM: bkioUpdateLkFile - update the .lk file
 *
 * Update the .lk file with the NON-NULL parameters passed to the 
 * routine.  This is used to revalidate the .lk file incase it's 
 * creator has disappeared.  An example of this is during Emergency
 * Shutdown, the first thing that happens is that the broker dies
 * hence the .lk is now "stale".
 *
 * RETURNS: 0 - success
 *         -1 - failure
 */
int
bkioUpdateLkFile(
        dsmContext_t *pcontext,
        int           mode,		/* mode database is opened in */
        int           pid,		/* pid of the owner */
        TEXT         *phost,		/* hostname */
        TEXT         *dbname)         /* name of database */
{
    LONG	    ret;
    LONG            retMakePath = 0;
    int		    errorStatus = 0;
    int		    bytesWritten;
    TEXT            namebuf[MAXPATHN+1];
    int             lockret;
    UCOUNT          nameCrc;
    fileHandle_t    lkhandle = (fileHandle_t) -1;
    int i;

    /* get the absolute path of the .lk file */
    if(pcontext->pdbcontext->pdatadir)
        utmypath(namebuf,pcontext->pdbcontext->pdatadir,
                 pcontext->pdbcontext->pdbname,
                 (TEXT *)".lk");
    else
        retMakePath = utMakePathname(namebuf, sizeof(namebuf), dbname,
                                                 (TEXT *)".lk");
    if (retMakePath != DBUT_S_SUCCESS)
    {
        /* Report error */
        dbUserError(pcontext, retMakePath, errno, 0,
                    (DSMVOID *)NULL, (DSMVOID *)NULL);
    }

    nameCrc = calc_crc((UCOUNT)0, namebuf, (COUNT)stlen(namebuf));

    /* find the handle for the lkfile */
    for (i = 0; i < 240; i++)
    {
        if ((lkstr[i].nameCrc == nameCrc) && 
            (lkstr[i].lkHandle != (fileHandle_t)0))
        {
            lkhandle = lkstr[i].lkHandle;
            break;
        }
    }

    /* If we were not called from a process that knew the lock file 
     * handle, go get it.
    */
    if (lkhandle == (fileHandle_t) -1)
    {
        lkhandle = utOsOpen((TEXT *)namebuf, OPEN_RW, DEFLT_PERM,
                           OPEN_SEQL, &errorStatus);
    
        if (lkhandle == INVALID_FILE_HANDLE)
        {
            /* failed to open the .lk file, return the failure */
            MSGN_CALLBACK(pcontext, bkMSG100, namebuf, errorStatus);
            return -1;
        }

        /* we are going to end up owning this lk file, save the handle
           for future use. */
        for (i = 0; i < 240; i++)
        {
            if (lkstr[i].lkHandle == (fileHandle_t)0)
            {
                /* we found an empty slot, populate it */
                lkstr[i].lkHandle = lkhandle;
                lkstr[i].nameCrc = calc_crc((UCOUNT)0, namebuf, 
                                            (COUNT)stlen(namebuf));
                break;
            }
        }
    }
#if OPSYS==UNIX
    else
    {
        /* we are going to close this file at the end so we 
           need to make sure every knows that */
        lkstr[i].lkHandle = (fileHandle_t) -1;
    }
#endif

    /* If we get the lock, then we were called by brkillall, watchdog,
     * or wdogLkFileCheck (after it was determined that the broker was gone).
     * If we don't get a lock, then we were called by nsaloop during startup
     * and we need to change the mode from DBLKSTARTUP to DBLKMULT.
    */
    lockret = utLockLkFile(lkhandle);

    if (mode)
    {
        /* update the mode with the passed one */

        ret = utWriteToFile(lkhandle, 0, (TEXT *)&mode,sizeof(int),
                            &bytesWritten, &errorStatus);
        if (ret < 0)
        {
            /* failed to write mode to the .lk file, return the failure */
            MSGN_CALLBACK(pcontext, bkMSG099,namebuf,errorStatus);
            return -1;
        }
 
    }
    
    if (pid)
    {
        /* update the pid with the passed one */
        ret = utWriteToFile(lkhandle, sizeof(int), (TEXT *)&pid,sizeof(int),
                            &bytesWritten, &errorStatus);
        if (ret < 0)
        {
            /* failed to seek to pid in the .lk file, return the failure */
            MSGN_CALLBACK(pcontext, bkMSG099,namebuf,errorStatus);
            return -1;
        }
    }
    
    if (phost)
    {
        /* update the hostname with the passed one */
        ret = utWriteToFile(lkhandle,2 * sizeof(int), phost,stlen(phost),
                            &bytesWritten, &errorStatus);
        if (ret < 0)
        {
            /* failed to write hostname to the .lk file, return the failure */
            MSGN_CALLBACK(pcontext, bkMSG099, namebuf, errorStatus);
            return -1;
        }
    }

    /* if we got here, time to close up shop and return success */
#if OPSYS == UNIX
    utOsClose (lkhandle, OPEN_SEQL);
#endif

    return 0;
    
}
Пример #10
0
/* PROGRAM: bkioTestLkFile -- examine the database to see if it is locked, and
 *		if so return the mode, i.e. single-user or multi-user.
 *		This version uses a special file, ".lk", instead of the
 *		UNIX locking call.
 *
 * RETURNS:	Returns 0 if the database is not locked, else returns
 *		BKIO_LKSNGL or BKIO_LKMULT.
 */
int
bkioTestLkFile (
        dsmContext_t    *pcontext,
	TEXT		*dbname)	/* path name for ".db" file */
                                          

{
     TEXT		namebuf[MAXPATHN+1];
#if OPSYS == UNIX
     TEXT		nodebuf[BKIO_NODESZ];
     TEXT		mynode[BKIO_NODESZ];
#endif
     LONG		retRead;
     ULONG		spid = 0;
     int		lkmode = 0;
     int		errorStatus = 0;
     int                bytesRead;
     LONG               retMakePath = 0;
     fileHandle_t       lkhandle;
     int                lockret = 0;

    /* form path name for *.lk file, see if it's there and current */
    if(pcontext->pdbcontext->pdatadir)
        utmypath(namebuf,pcontext->pdbcontext->pdatadir,
                         pcontext->pdbcontext->pdbname,
                         (TEXT *)".lk");
    else 
        retMakePath = utMakePathname(namebuf, sizeof(namebuf), dbname, 
                                    (TEXT *)".lk");
    if (retMakePath != DBUT_S_SUCCESS)
    {
        /* Report Error */
        dbUserError(pcontext, retMakePath, errno, 0,
                    (DSMVOID *)NULL, (DSMVOID *)NULL);
    }

#if OPSYS == WIN32API
    lkhandle = utOsOpen(namebuf, OPEN_RW, DEFLT_PERM, OPEN_SEQL, &errorStatus);
#else
    lkhandle = utOsOpen(namebuf, OPEN_R, DEFLT_PERM, OPEN_SEQL, &errorStatus);
#endif

    if (lkhandle == INVALID_FILE_HANDLE)
    {	
        /* open failed, either db not in use, or permission screwed up */
	if (errorStatus != ENOENT)
            FATAL_MSGN_CALLBACK(pcontext, svFTL013, namebuf, errorStatus);
    }
    else 
    {
        /* read lock mode and server pid out of lock file */
	/* the following loop takes care of a timing window that exists
	*  when the server creates the .lk file, and the client attempts
	*  to read the file before the server has written the lock mode
	*  and its pid into the file. This loop should also handle interrupted
	*  system call under Unix, and hence no special case for EINTR
	*/

        /* Remove this conditional once file locking is implemented for UNIX */
#if OPSYS == WIN32API
        /* Try to lock the .lk file */
        lockret = utLockLkFile(lkhandle);
#endif
   
        /* We got a lock, so the .lk file is invalid. Now unlock so it 
         * can be overwritten.
        */ 
        if (lockret)
        {
            lockret = utUnlockLkFile(&lkhandle);
            /* 19990525-028 - If we are going to change behavior such   */
            /* that the .lk file is only created if it does not already */
            /* exist, then if the .lk file is invalid we must delete it */
            bkioRemoveLkFile(pcontext, dbname);
            return (0);
        } 
        else
        {
            /* The .lk file exists, we can't lock it, so it is valid */
	    retRead = utReadFromFile(lkhandle, 0, (TEXT *)&lkmode,
                                 sizeof (int), &bytesRead, &errorStatus);

	    if ( bytesRead != sizeof(int))
            {
	        MSGN_CALLBACK(pcontext, svMSG005);
                return BKIO_LKTRUNC;
            }

#if OPSYS == UNIX
	    /* get PID and HOST name from file-- if its the same HOST as we
               are on, it is then safe to test the PID and erase .lk if its
	       not a live process on this same machine and allow login.

	       if the HOSTS are different, or gethostname() is not supported 
               on this machine, the PID cannot be guaranteed to be valid 
               because of NFS so return BKIO_LKNOHOST */

	    retRead = utReadFromFile(lkhandle, sizeof(int), (TEXT *)&spid,
                                 sizeof(int), &bytesRead, &errorStatus);
	    if ( spid )
	    {
	        stnclr(mynode,BKIO_NODESZ);

	        utgethostname((TEXT *)mynode,BKIO_NODESZ -1);
    
	        retRead = utReadFromFile(lkhandle, 2 * sizeof(int), 
                            (TEXT *)nodebuf, BKIO_NODESZ, &bytesRead, 
                            &errorStatus);
	        if ( bytesRead == BKIO_NODESZ)
                {
		    if (nodebuf[0] == '\0') /* No hostname in the .lk file */
                    {
                        return BKIO_LKNOHOST;
                    }
		    if (stpcmp(nodebuf,mynode) == 0) /*see if nodes match*/
		    {   
                        if ( (kill ( spid, 0 ) == -1) && (errno == ESRCH) )
                        {
			    lkmode= 0;
                        }
		    }
                }
	    }

#endif /* UNIX */
        }
    }

    if (lkhandle != INVALID_FILE_HANDLE)
    {
        utOsClose(lkhandle, OPEN_SEQL);
        if (lkmode == 0)
        {
            bkioRemoveLkFile(pcontext, dbname);
        }
    }
    return(lkmode);
}
Пример #11
0
/* PROGRAM: dbQuietPoint - evaluate the quiet request and
 *                         enable or disable the quiet point.
 *
 * RETURNS: 0 - success
 *          non-zero - failure
 */
int
dbQuietPoint(dsmContext_t *pcontext,
             UCOUNT        quietRequest,
             ULONG         quietArg)
{
    int returnCode = 0;       /* status of the quiet request */
    dbcontext_t  *pdbcontext = pcontext->pdbcontext;
    dbshm_t      *pdbshm = pdbcontext->pdbpub;
    usrctl_t     *pusrctl = pcontext->pusrctl;
    RLCTL        *prl = pdbcontext->prlctl;
    LONG64        bithreshold = 0;
    DOUBLE        bitholdBytes = 0;
    DOUBLE        bitholdSize = 0;
    TEXT          sizeId;
    DOUBLE        fromBitholdBytes = 0;
    DOUBLE        fromBitholdSize = 0;
    TEXT          fromSizeId;
    DOUBLE        toBitholdBytes = 0;
    DOUBLE        toBitholdSize = 0;
    TEXT          toSizeId;
    TEXT          printBuffer[13];
    TEXT          fromPrintBuffer[13];
    TEXT          toPrintBuffer[13];


    /* Before we attempt to enable or disable the quiescent point */
    /* we need to check for the existence of the broker.          */

        if (!deadpid(pcontext, pdbshm->brokerpid))
        {
            if (quietRequest == QUIET_POINT_REQUEST)
            {
                if (!pdbshm->quietpoint == QUIET_POINT_NORMAL)
                {
                    if ((pdbshm->quietpoint == QUIET_POINT_REQUEST) ||
                       (pdbshm->quietpoint == QUIET_POINT_ENABLED)) 
                    {
                        /* Quiet point has already been requested. */
                        MSGN_CALLBACK(pcontext, drMSG392);
                        returnCode = 4;
                    }
                     else
                    {
                        /* Protect against a second user trying to quiet */
                        /* Enabling the quiet point is in effect. */
                        MSGN_CALLBACK(pcontext, drMSG393);
                        returnCode = 6;
                    }
                }
                else
                /* Database is in the Normal Processing State */
                {
                    
                    /* Check if after imaging is enabled without */
                    /* the use of after image extents.           */
                    if ( rlaiqon(pcontext) == 1 && 
                         pdbcontext->pmstrblk->mb_aibusy_extent == 0 )
                    {
                        /* Cannot enable with single ai file */
                        MSGN_CALLBACK(pcontext, drMSG394);
                        returnCode = 2;
                    }
                    else  
                    {

                    /* Reset the shared memory variable to request    */
                    /* the enabling of the quiet point by the broker. */
                    pdbshm->quietpoint = QUIET_POINT_REQUEST;

                    /* Loop until the quietpoint state changes to */
                    /* QUIET_POINT_ENABLED */
                    for (;;)
                    {
                        /* Test for brokers existence and whether */
                        /* shutdown has already occurred. */
                        if (deadpid(pcontext, pdbshm->brokerpid)) 
                        {
                            MSGN_CALLBACK(pcontext, drMSG395);
                            returnCode = 16;
                            break;
                        }

                        /* Check to see if a shutdown was received. */
                        if (pusrctl->usrtodie)
                        {
                                MSGN_CALLBACK(pcontext, drMSG396);
                                returnCode = 16;
                                break;
                        }

                        if (pdbshm->quietpoint == QUIET_POINT_ENABLED)
                        {
                            pdbcontext->usertype |= DBSHUT;
                            returnCode = 0;
                            break;
                        }
                        utsleep(1);
                    }

                    } 
                }
            }
            /* Disable the Ouiet Point */
            else if (quietRequest == QUIET_POINT_DISABLE)
            {
                /* Database is in the Normal Processing State */
                if (pdbshm->quietpoint == QUIET_POINT_ENABLED)
                {
                    /* Reset the shared memory variable to request    */
                    /* the enabling of the quiet point by the broker. */
                    pdbshm->quietpoint = QUIET_POINT_DISABLE;

                    /* Loop until the quietpoint state changes to */
                    /* QUIET_POINT_ENABLED */
                    for (;;)
                    {
                        /* Test for brokers existence */
                        if (deadpid(pcontext, pdbshm->brokerpid))
                        {
                            MSGN_CALLBACK(pcontext, drMSG397);
                            pdbcontext->usertype |= DBSHUT;
                            returnCode = 16;
                            break;
                        }

                        /* Check to see if a shutdown was received. */
                        if (pusrctl->usrtodie)
                        {
                            MSGN_CALLBACK(pcontext, drMSG398);
                            pdbcontext->usertype |= DBSHUT;
                            returnCode = 16;
                            break;
                        }
                            
                        if (pdbshm->quietpoint == QUIET_POINT_NORMAL)
                        {
                            pdbcontext->usertype |= DBSHUT;
                            returnCode = 0;
                            break;
                        }
                        utsleep(1);
                    }
                }
                else if (pdbshm->quietpoint != QUIET_POINT_ENABLED)
                {
                    /* Quiet point does not need to be disabled. */
                    MSGN_CALLBACK(pcontext, drMSG399);
                    pdbcontext->usertype |= DBSHUT;
                    returnCode = 3;
                }
            }
            else if (quietRequest == QUIET_POINT_BITHRESHOLD)
            {
                 /* Round down bi threshold by a cluster if it is set */
                 bithreshold =
                     ( (((LONG64)quietArg * 1048576) / prl->rlbiblksize)
                          - (prl->rlclbytes / prl->rlbiblksize) );

                 if (bithreshold > 0 && bithreshold > prl->rlsize)
                     
                 {
                     /* Validate the bi threshold value */
                     if (pdbshm->bithold == bithreshold)
                     {
                         /* bithold size same, request to change rejected */
                         bitholdBytes =
                                    (DOUBLE)bithreshold * prl->rlbiblksize;
                         utConvertBytes(bitholdBytes,
                                        &bitholdSize, &sizeId);
                         sprintf((char *)printBuffer, "%-5.1f %cBytes",
                                               bitholdSize, sizeId);
                         MSGN_CALLBACK(pcontext, drMSG687, printBuffer);
                         MSGN_CALLBACK(pcontext, drMSG451);
                         returnCode = 3;
                     }
                     else if (pdbshm->bithold == 0 
                              || pdbshm->bithold > (ULONG)prl->rlsize)
                     {
                         if (pdbshm->quietpoint != QUIET_POINT_ENABLED)
                         {
                             /* Quiet point not enabled and stall did not occur.
                                Request to change bi threshold rejected */
                             MSGN_CALLBACK(pcontext, drMSG452);
                             MSGN_CALLBACK(pcontext, drMSG451);
                             returnCode = 3;
                         }
                         else
                         {
                             /* Make sure new bi threshold is larger than
                                bi file size */
                             if (bithreshold >= prl->rlsize)
                             {
                                 /* bi threshold changed from value to value */
                                 fromBitholdBytes =
                                    (DOUBLE)pdbshm->bithold * prl->rlbiblksize;
                                 utConvertBytes(fromBitholdBytes,
                                                &fromBitholdSize, &fromSizeId);
                                 sprintf((char *)fromPrintBuffer, "%-5.1f %cBytes",
                                               fromBitholdSize, fromSizeId);
                                 toBitholdBytes =
                                    (DOUBLE)bithreshold * prl->rlbiblksize;
                                 utConvertBytes(toBitholdBytes,
                                                &toBitholdSize, &toSizeId);
                                 sprintf((char *)toPrintBuffer, "%-5.1f %cBytes",
                                               toBitholdSize, toSizeId);
                                 MSGN_CALLBACK(pcontext, drMSG686,
                                               fromPrintBuffer, toPrintBuffer);
                                 pdbshm->bithold = bithreshold;
                                 returnCode = 0;
                             }
                             else
                             {
                                 /* Invalid value provided, request to change
                                    bi threshold rejected */
                                 MSGN_CALLBACK(pcontext, drMSG454);
                                 MSGN_CALLBACK(pcontext, drMSG451);
                                 returnCode = 3;
                             }
                         }
                     }
                     else if ((pdbshm->bithold) <= (ULONG)prl->rlsize) 
                     {
                         /* bi threshold reached */
                         /* bi threshold changed from value to value */
                         fromBitholdBytes =
                                    (DOUBLE)pdbshm->bithold * prl->rlbiblksize;
                         utConvertBytes(fromBitholdBytes,
                                        &fromBitholdSize, &fromSizeId);
                         sprintf((char *)fromPrintBuffer, "%-5.1f %cBytes",
                                                  fromBitholdSize, fromSizeId);
                         toBitholdBytes =
                                    (DOUBLE)bithreshold * prl->rlbiblksize;
                         utConvertBytes(toBitholdBytes,
                                        &toBitholdSize, &toSizeId);
                         sprintf((char *)toPrintBuffer, "%-5.1f %cBytes",
                                                toBitholdSize, toSizeId);
                         MSGN_CALLBACK(pcontext, drMSG686,
                                            fromPrintBuffer, toPrintBuffer);
                         
                         pdbshm->bithold = bithreshold;
                         pdbshm->quietpoint = QUIET_POINT_NORMAL;
                         returnCode = 0;
                     }
                     else
                     {
                         /* Invalid value provided, request to change
                            bi threshold rejected */
                         MSGN_CALLBACK(pcontext, drMSG454);
                         MSGN_CALLBACK(pcontext, drMSG451);
                         returnCode = 3;
                     }
                 }
                 else
                 {
                     /* Invalid value provided, request to change
                        bi threshold rejected */
                     MSGN_CALLBACK(pcontext, drMSG454);
                     MSGN_CALLBACK(pcontext, drMSG451);
                     returnCode = 3;
                 }
           }
        }
        else 
        /* The broker does not exist and shutdown may be in progress */
        {
            /* Broker is dead - abnormal shutdown of the database */
            MSGN_CALLBACK(pcontext, drMSG400);
            returnCode = 16;
        }

    return(returnCode);
}
Пример #12
0
/* PROGRAM: dbLogOpen -- open the database log file (".lg").
 *
 * RETURNS:	0 - OK
 *	    non-0 - Unable to open the .lg file
 */
int
dbLogOpen(
        dsmContext_t *pcontext,
        TEXT         *pname)	/* name of the database */
{
    dbcontext_t *pdbcontext = pcontext->pdbcontext;
	TEXT	 namebuf[MAXPATHN+1];
	fileHandle_t	 tmpfd;
        int              errorStatus;
        LONG             retMakePath;

    if (pdbcontext->logopen)
        return 0;

    /* setup the fd cache */
    utInitFdCache(128);

    /* get name of log file, open it */
    retMakePath = utMakePathname( namebuf, sizeof(namebuf), pname, (TEXT *) ".lg");
    if (retMakePath != DBUT_S_SUCCESS)
    {
        /* Report error */
        dbUserError(pcontext, retMakePath, errno, 0,
                    (DSMVOID *)NULL, (DSMVOID *)NULL);
    }

    if ((tmpfd = utOsOpen (namebuf, OPEN_W_APPEND_TEXT,
	    DEFLT_PERM, OPEN_SEQL,&errorStatus)) == INVALID_FILE_HANDLE)
	if ( (tmpfd = utOsCreat (namebuf, CREATMODE,
		    CHG_OWNER|AUTOERR,&errorStatus)) != INVALID_FILE_HANDLE)
	{
	    utOsClose(tmpfd,OPEN_SEQL);
	    tmpfd = utOsOpen (namebuf, OPEN_W_APPEND_TEXT,
			DEFLT_PERM, OPEN_SEQL,&errorStatus);
	}
    if (tmpfd == INVALID_FILE_HANDLE)
    {
        MSGN_CALLBACK(pcontext, utMSG092, namebuf, errorStatus);
        return -1;
    }

#if OPSYS == UNIX
    /* writing to the .lg file is *VERY* important, so it
       doesn't participate in the fd cache.  To make this true
       we need to close the handle and do a regular open on it */
    utOsClose(tmpfd, 0);
    pdbcontext->lgfd = open(namebuf, OPEN_W_APPEND_TEXT);
    if (pdbcontext->lgfd < 0)
    {
        MSGN_CALLBACK(pcontext, utMSG092, namebuf, errorStatus);
        return -1;
    }
#else
    pdbcontext->lgfd = _open_osfhandle((LONG)tmpfd, O_APPEND | O_TEXT);
#endif

    /* prevent child processes from inheriting this file */
    utclex (tmpfd);

    pdbcontext->logopen = 1;
    return 0;

} /* end dbLogOpen */
Пример #13
0
/* RETURNS: -1 = error; >=0 = the shmid of the segment	*/
int
shmCreateSegment(
        dsmContext_t *pcontext,
        SHMDSC       *pshmdsc, /*control blk for a series of shm segs */
        int           idchar _UNUSED_) /* Key value for multiple segments within db */ 
{
    int	 shmid;
    TEXT	*pname = pshmdsc->pname;/*database name or other file name*/

    pshmdsc->segsize = MIN(pshmdsc->segsize, mssize);

#if ALPHAOSF
    /* -Mpte keeps VLM64 allocations in multiples of 8Mb for good performance */
    if (pcontext->pdbcontext->argMpte) while (pshmdsc->segsize >= 0x00800000)
    {
	shmid = shmget(IPC_PRIVATE,                 /* ensure unique id   */
                       (int)pshmdsc->segsize,       /* segment size       */
                       0666+IPC_EXCL+IPC_CREAT);    /* segment attributes */

	if (shmid >= 0) return shmid;   /* successful		*/

	/* "vm: gh-fail-if-no-mem=1" in /etc/sysconfigtab can raise ENOMEM */
	if (errno == EINVAL || errno == ENOMEM)
	{
	    /* the size is invalid, decrease it by 8MB and try again */
	    pshmdsc->segsize -= 0x00800000;
	    mssize = pshmdsc->segsize;
	    continue;
	}
	else break;
    }
    /* if this didn't work, go on and try it the old fashioned way. */
    mssize = pshmdsc->segsize = 0x00800000;
#endif
    do  
    {
        pshmdsc->segsize = (pshmdsc->segsize + 0xfff) & ~0xfff;

	shmid = shmget(IPC_PRIVATE,                 /* ensure unique id   */
                       (int)pshmdsc->segsize,       /* segment size       */
                       0666+IPC_EXCL+IPC_CREAT);    /* segment attributes */

	if (shmid >= 0) return shmid;   /* successful		*/
        if (errno == EINVAL)
	{
	    /* the size is invalid, decrease it  and try again */
	    pshmdsc->segsize = pshmdsc->segsize - 8192;
	    if (pshmdsc->segsize < 8 * 1024)
	    {
		/* The allowed shm segment size too small */
		MSGN_CALLBACK(pcontext, utMSG024);
		return -1;
	    }
	    mssize = pshmdsc->segsize;
	}
    }
    while (errno == EINVAL);

    if (errno == ENOMEM || errno == EAGAIN)
    {
        MSGN_CALLBACK(pcontext, utMSG026);
    }
    else
    {
        /* print an error message	*/
        shmmsg(pcontext, errno, (TEXT *)"create", pname, (key_t)shmid);
    }

    return -1;
}
Пример #14
0
/* RETURNS: -1 = error; >=0 = the shmid of the segment	*/
int
shmCreateSegment(
        dsmContext_t *pcontext,
        SHMDSC       *pshmdsc,/* control blk for a series of shm segs */
        int           idchar)  /*id for multiple segments for same db  */
{

    LPVOID  lpmem;
    HANDLE  hmap;
    TEXT    *pname = pshmdsc->pname;
    char    szShareMem[MAXUTFLEN];
    char    szFile[MAXUTFLEN];

    pshmdsc->segsize = MIN(pshmdsc->segsize, MAXSEGSIZE);
    utapath(szFile, MAXUTFLEN, pname, "");
    utmkosnm("sharemem.", szFile, szShareMem, MAXUTFLEN, idchar);

    hmap = CreateFileMapping((HANDLE)0xFFFFFFFF,  /* Use the swap file    */
			     (SECURITY_ATTRIBUTES*)SecurityAttributes(0), 
                                                  /* Not inherited        */
			     PAGE_READWRITE,      /* Memory is Read/Write */
			     0L,                  /* Size Upper 32 Bits   */
			     (DWORD)pshmdsc->segsize,/* Size Lower 32 bits*/
			     szShareMem);

    if (!hmap)
    {
    	DWORD dwRet = GetLastError();
    
        switch (dwRet) 
	{
	  case ERROR_ALREADY_EXISTS:      /* Right now this case will never */
	    /* be TRUE. hmap is not NULL   */
	    /* if the mapping already existed */
	  default:
	    /* Unable to create shared memory %s, error %d */
	    MSGN_CALLBACK(pcontext, utMSG062, szShareMem, dwRet);
	    return -1;
	}
    }

    lpmem = MapViewOfFile(hmap,
			  FILE_MAP_WRITE | FILE_MAP_READ,
			  0, 0, (DWORD)pshmdsc->segsize);

#if 0 /* Your supposed to be able to do this */
	CloseHandle(hmap);
#endif
    if (lpmem == 0)
    {
    	/* Unable to create shared memory %s, error %d */
    	MSGN_CALLBACK(pcontext, utMSG062, szShareMem, 0);
    	return -1;
    }

    if (utshmAddNamedSegment(szShareMem, (int)lpmem, (ULONG)hmap))
    {
    	/* Failed, out of memory */
    	UnmapViewOfFile(lpmem);
    	return -1;
    }
    
    return (int)lpmem;
}