⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 logaccessfile.java

📁 derby database source code.good for you.
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
		currentBuffer.bytes_free -= len;		currentBuffer.position += len;	}    /**     * Write data from all dirty buffers into the log file.     * <p>     * A call for clients of LogAccessFile to insure that all privately buffered     * data has been writen to the file - so that reads on the file using one     * of the various scan classes will see     * all the data which has been writen to this point.     * <p>     * Note that this routine only "writes" the data to the file, this does not     * mean that the data has been synced to disk unless file was opened in	 * WRITE SYNC mode(rws/rwd).  The only way to insure that is by calling     * is to call syncLogAccessFile() after this call in Non-WRITE sync mode(rw)	 * 	 * <p>	 * MT-Safe : parallel thereads can call this function, only one threads does	 * the flush and the other threads waits for the one that is doing the flush to finish.	 * Currently there are two possible threads that can call this function in parallel 	 * 1) A Thread that is doing the commit	 * 2) A Thread that is writing to the log and log buffers are full or	 * a log records does not fit in a buffer. (Log Buffers	 * full(switchLogBuffer() or a log record size that is greater than	 * logbuffer size has to be writtern through writeToLog call directlty)	 * Note: writeToLog() is not synchronized on the semaphore	 * that is used to do  buffer management to allow writes 	 * to the free buffers when flush is in progress.       **/	protected void flushDirtyBuffers() throws IOException     {        LogAccessFileBuffer buf = null;		int noOfBuffers;		int nFlushed= 0;		try{			synchronized(this)			{				/**if some one else flushing wait, otherwise it is possible 				 * different threads will get different buffers and order can 				 * not be determined.				 * 				 **/				while(flushInProgress)				{					try{						wait();					}catch (InterruptedException ie) 					{						//do nothing, let the flush request to complete.						//because it possible that other thread which is						//currently might have completed this request also ,						//if exited  on interrupt and throw exception, can not						//be sure whether this transaction is COMMITTED ot not.					}				}						noOfBuffers = dirtyBuffers.size();				if(noOfBuffers > 0)					buf = (LogAccessFileBuffer) dirtyBuffers.removeFirst();								flushInProgress = true;			}						while(nFlushed < noOfBuffers)			{				if (buf.position != 0)					writeToLog(buf.buffer, 0, buf.position);				nFlushed++;				synchronized(this)				{					//add the buffer that was written previosly to the free list					freeBuffers.addLast(buf);					if(nFlushed < noOfBuffers)						buf = (LogAccessFileBuffer) dirtyBuffers.removeFirst();					else					{						//see if we can flush more, that came when we are at it.						//don't flush more than the total number of buffers,						//that might lead to starvation of the current thread.						int size = dirtyBuffers.size();						if(size > 0 && nFlushed <= LOG_NUMBER_LOG_BUFFERS)						{							noOfBuffers += size;							buf = (LogAccessFileBuffer) dirtyBuffers.removeFirst();						}					}				}			}						}finally{			synchronized(this)			{				flushInProgress = false;				notifyAll();			}		}	}	//flush all the the dirty buffers to disk	public void flushLogAccessFile() throws IOException,  StandardException 	{		switchLogBuffer();		flushDirtyBuffers();	}			/**	 * Appends the current Buffer to the dirty Buffer list and assigns a free	 * buffer to be the currrent active buffer . Flushing of the buffer	 * to disk is delayed if there is a free buffer available. 	 * dirty buffers will be  flushed to the disk   	 * when  flushDirtyBuffers() is invoked by  a commit call 	 * or when no more free buffers are available. 	 */	public void switchLogBuffer() throws IOException, StandardException      {		synchronized(this)		{			// ignore empty buffer switch requests			if(currentBuffer.position == checksumLogRecordSize)				return;			// calculate the checksum for the current log buffer 			// and write the record to the space reserverd in 			// the beginning of the buffer. 			if(writeChecksum && !directWrite)			{				checksumLogOperation.reset();				checksumLogOperation.update(currentBuffer.buffer, checksumLogRecordSize, currentBuffer.position - checksumLogRecordSize);				writeChecksumLogRecord();			}			//add the current buffer to the flush buffer list			dirtyBuffers.addLast(currentBuffer);			//if there is No free buffer, flush the buffers to get a free one 			if(freeBuffers.size() == 0) 			{				flushDirtyBuffers();				//after the flush call there should be a free buffer				//because this is only methods removes items from 				//free buffers and removal is in synchronized block. 			}			// there should be free buffer available at this point.			if (SanityManager.DEBUG)				SanityManager.ASSERT(freeBuffers.size() > 0);			//switch over to the next log buffer, let someone else write it.			currentBuffer = (LogAccessFileBuffer) freeBuffers.removeFirst();			currentBuffer.init(checksumLogRecordSize);			if (SanityManager.DEBUG)			{				SanityManager.ASSERT(currentBuffer.position == checksumLogRecordSize);				SanityManager.ASSERT(									 currentBuffer.bytes_free == currentBuffer.length);                SanityManager.ASSERT(currentBuffer.bytes_free > 0);			}		}	}    /**     * Guarantee all writes up to the last call to flushLogAccessFile on disk.     * <p>     * A call for clients of LogAccessFile to insure that all data written     * up to the last call to flushLogAccessFile() are written to disk.     * This call will not return until those writes have hit disk.     * <p>     * Note that this routine may block waiting for I/O to complete so      * callers should limit the number of resource held locked while this     * operation is called.  It is expected that the caller     * Note that this routine only "writes" the data to the file, this does not     * mean that the data has been synced to disk.  The only way to insure that     * is to first call switchLogBuffer() and then follow by a call of sync().     *     **/    public void syncLogAccessFile()         throws IOException, StandardException    {        for( int i=0; ; )        {            // 3311: JVM sync call sometimes fails under high load against NFS             // mounted disk.  We re-try to do this 20 times.            try            {                synchronized( this)                {                    log.sync( false);                }                // the sync succeed, so return                break;            }            catch( SyncFailedException sfe )            {                i++;                try                {                    // wait for .2 of a second, hopefully I/O is done by now                    // we wait a max of 4 seconds before we give up                    Thread.sleep( 200 );                 }                catch( InterruptedException ie )                {   //does not matter weather I get interrupted or not                }                if( i > 20 )                    throw StandardException.newException(                        SQLState.LOG_FULL, sfe, null);            }        }    }	/**		The database is being marked corrupted, get rid of file pointer without		writing out anything more.	 */	public void corrupt() throws IOException	{		synchronized(logFileSemaphore)		{			if (log != null)				log.close();		}	}	public void close() throws IOException, StandardException    {		if (SanityManager.DEBUG)         {			if (currentBuffer.position !=  checksumLogRecordSize)				SanityManager.THROWASSERT(				"Log file being closed with data still buffered " +                 currentBuffer.position +  " " + currentBuffer.bytes_free);		}		flushLogAccessFile();		synchronized(logFileSemaphore)		{			if (log != null)				log.close();		}	}	/* write to the log file */	private void writeToLog(byte b[], int off, int len) throws IOException	{		synchronized(logFileSemaphore)		{            if (log != null)            {                // Try to handle case where user application is throwing                // random interrupts at cloudscape threads, retry in the case                // of IO exceptions 5 times.  After that hope that it is                 // a real disk problem - an IO error in a write to the log file                // is going to take down the whole system, so seems worthwhile                // to retry.                for (int i = 0; ;i++)                {                    try                     {                        log.write(b, off, len);                        break;                    }                    catch (IOException ioe)                    {                        // just fall through and rety the log write 1st 5 times.                        if (i >= 5)                            throw ioe;                    }                }            }		}		if (SanityManager.DEBUG)         {			mon_numWritesToLog++;			mon_numBytesToLog += len;		}	}	/**	 * reserve the space for the checksum log record in the log file.      *	 * @param  length           the length of the log record to be written	 * @param  logFileNumber    current log file number 	 * @param  currentPosition  current position in the log file.      *	 * @return the space that is needed to write a checksum log record.	 */	protected long reserveSpaceForChecksum(int length, long logFileNumber, long currentPosition )		throws StandardException, IOException 	{		int total_log_record_length = length + LOG_RECORD_FIXED_OVERHEAD_SIZE;		boolean reserveChecksumSpace = false;				/* checksum log record is calculated for a group of log 		 * records that can fit in to a single buffer or for 		 * a single record when it does not fit into 		 * a fit into a buffer at all. When a new buffer 		 * is required to write a log record, log space 		 * has to be reserved before writing the log record		 * becuase checksum is written in the before the 		 * log records that are being checksummed. 		 * What it also means is a real log instant has to be 		 * reserved for writing the checksum log record in addition 		 * to the log buffer space.		 */				/* reserve checkum space for new log records if a log buffer switch had		 * happened before because of a explicit log flush requests(like commit)		 * or a long record write 		 */		if(currentBuffer.position == checksumLogRecordSize)		{			// reserver space if log checksum feature is enabled.			reserveChecksumSpace = writeChecksum;		}		else{			if (total_log_record_length > currentBuffer.bytes_free)			{				// the log record that is going to be written is not 				// going to fit in the current buffer, switch the 				// log buffer to create buffer space for it. 				switchLogBuffer();				// reserve space if log checksum feature is enabled. 				reserveChecksumSpace = writeChecksum;			}		}				if(reserveChecksumSpace)		{			if (SanityManager.DEBUG)			{				// Prevoiusly reserved real checksum instant should have been				// used, before an another one is generated. 				SanityManager.ASSERT(checksumInstant == -1,  "CHECKSUM INSTANT IS GETTING OVER WRITTEN");			}						checksumInstant = LogCounter.makeLogInstantAsLong(logFileNumber, currentPosition);			return  checksumLogRecordSize;		}else		{			return 0 ;		}	}	/*	 * generate the checkum log record and write it into the log buffer.	 */	private void writeChecksumLogRecord() throws IOException, StandardException	{				byte[] b    = currentBuffer.buffer;		int    p    = 0; //checksum is written in the beginning of the buffer		// writeInt(length)		p = writeInt(checksumLength, b , p);            		// writeLong(instant)		p = writeLong(checksumInstant, b , p);		//write the checksum log operation  		logOutputBuffer.setData(b);		logOutputBuffer.setPosition(p);		logicalOut.writeObject(checksumLogRecord);		if(databaseEncrypted)		{			//encrypt the checksum log operation part.			int len = 				logFactory.encrypt(b, LOG_RECORD_HEADER_SIZE, checksumLength, 								   b, LOG_RECORD_HEADER_SIZE);					   			if (SanityManager.DEBUG)				SanityManager.ASSERT(len == checksumLength, 									 "encrypted log buffer length != log buffer len");		}		p = LOG_RECORD_HEADER_SIZE + checksumLength ;		// writeInt(length) trailing		p = writeInt(checksumLength, b, p );				if (SanityManager.DEBUG)		{			SanityManager.ASSERT(p == checksumLogRecordSize, "position=" + p  + "ckrecordsize=" + checksumLogRecordSize);			if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG))			{				SanityManager.DEBUG(									LogToFile.DBG_FLAG, 									"Write log record: tranId=Null"  +									" instant: " + LogCounter.toDebugString(checksumInstant) + " length: " +									checksumLength + "\n" + checksumLogOperation + "\n");			}			checksumInstant = -1; 		}	}	protected void writeEndMarker(int marker) throws IOException, StandardException 	{		//flush all the buffers and then write the end marker.		flushLogAccessFile();				byte[] b    = currentBuffer.buffer;		int    p    = 0; //end is written in the beginning of the buffer, no						 //need to checksum a int write.		p = writeInt(marker , b , p);		writeToLog(b, 0, p);	}	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -