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

📄 logaccessfile.java

📁 derby database source code.good for you.
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*   Derby - Class org.apache.derby.impl.store.raw.log.LogAccessFile   Copyright 1999, 2004 The Apache Software Foundation or its licensors, as applicable.   Licensed under the Apache License, Version 2.0 (the "License");   you may not use this file except in compliance with the License.   You may obtain a copy of the License at      http://www.apache.org/licenses/LICENSE-2.0   Unless required by applicable law or agreed to in writing, software   distributed under the License is distributed on an "AS IS" BASIS,   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   See the License for the specific language governing permissions and   limitations under the License. */package org.apache.derby.impl.store.raw.log;import org.apache.derby.iapi.reference.SQLState;import org.apache.derby.iapi.services.sanity.SanityManager;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.io.StorageRandomAccessFile;import java.io.IOException;import java.io.OutputStream;import java.io.SyncFailedException;import java.io.InterruptedIOException;import java.util.LinkedList;import org.apache.derby.iapi.services.io.FormatIdOutputStream;import org.apache.derby.iapi.services.io.ArrayOutputStream;import org.apache.derby.iapi.store.raw.RawStoreFactory;/**	Wraps a RandomAccessFile file to provide buffering	on log writes. Only supports the write calls	required for the log!	MT - unsafe.  Caller of this class must provide synchronization.  The one	exception is with the log file access, LogAccessFile will touch the log	only inside synchronized block protected by the semaphore, which is	defined by the creator of this object.	    Write to the log buffers are allowed when there are free buffers even    when dirty buffers are being written(flushed) to the disk by a different	thread. Only one flush writes to log file at a time, other wait for it to finish.	Except for flushLogAccessFile , SyncAccessLogFile other function callers	must provide syncronization that will allow only one of them to write to     the buffers.     Log Buffers are used in circular fashion, each buffer moves through following stages: 	freeBuffers --> dirtyBuffers --> freeBuffers. Movement of buffers from one    stage to 	another stage is synchronized using	the object(this) of this class. 	A Checksum log record that has the checksum value for the data that is    being written to the disk is generated and written 	before the actual data. 	Except for the large log records that does not fit into a single buffer,     checksum is calcualted for a group of log records that are in the buffer 	when buffers is switched. Checksum log record is written into the reserved	space in the beginning buffer.     In case of a large log record that does not fit into a bufffer, it needs to     be written directly to the disk instead of going through the log buffers.     In this case the log record write gets broken into three parts:        1) Write checksum log record and LOG RECORD HEADER (length + instant)         2) Write the log record.         3) Write the trailing length of the log record. 	Checksum log records helps in identifying the incomplete log disk writes during     recovery. This is done by recalculating the checksum value for the data on    the disk and comparing it to the the value stored in the checksum log    record. */public class LogAccessFile {    /**     * The fixed size of a log record is 16 bytes:     *     int   length             : 4 bytes     *     long  instant            : 8 bytes     *     int   trailing length    : 4 bytes     **/    private static final int            LOG_RECORD_FIXED_OVERHEAD_SIZE = 16;	private static final int            LOG_RECORD_HEADER_SIZE = 12; //(length + instant)	private static final int            LOG_RECORD_TRAILER_SIZE = 4; //trailing length     private static final int            LOG_NUMBER_LOG_BUFFERS = 3;	private LinkedList    freeBuffers;  //list of free buffers	private LinkedList    dirtyBuffers; //list of dirty buffers to flush	private  LogAccessFileBuffer currentBuffer; //current active buffer	private boolean flushInProgress = false;		private final StorageRandomAccessFile  log;	// log can be touched only inside synchronized block protected by	// logFileSemaphore.	private final Object            logFileSemaphore;	static int                      mon_numWritesToLog;	static int                      mon_numBytesToLog;	//streams used to generated check sume log record ; see if there is any simpler way	private ArrayOutputStream logOutputBuffer;	private FormatIdOutputStream logicalOut;	private boolean directWrite = false; //true when log is written directly to file.	private long checksumInstant = -1;	private int checksumLength;	private int checksumLogRecordSize;      //checksumLength + LOG_RECORD_FIXED_OVERHEAD_SIZE	private boolean writeChecksum; 	private ChecksumOperation checksumLogOperation;	private LogRecord checksumLogRecord;	private LogToFile logFactory;	private boolean databaseEncrypted=false;			public LogAccessFile(LogToFile logFactory,						 StorageRandomAccessFile    log, 						 int                 bufferSize)     {		if (SanityManager.DEBUG)		{			if(SanityManager.DEBUG_ON("LogBufferOff"))				bufferSize = 10;	// make it very tiny		}				this.log            = log;		logFileSemaphore    = log;		this.logFactory     = logFactory;		if (SanityManager.DEBUG)            SanityManager.ASSERT(LOG_NUMBER_LOG_BUFFERS >= 1);						//initialize buffers lists		freeBuffers = new LinkedList();		dirtyBuffers = new LinkedList();		//add all buffers to free list        for (int i = 0; i < LOG_NUMBER_LOG_BUFFERS; i++)        {            LogAccessFileBuffer b = new LogAccessFileBuffer(bufferSize);            freeBuffers.addLast(b);        }		currentBuffer = (LogAccessFileBuffer) freeBuffers.removeFirst();				// Support for Transaction Log Checksum in Derby was added in 10.1		// Check to see if the Store have been upgraded to 10.1 or later before		// writing the checksum log records.  Otherwise recovery will fail		// incase user tries to revert back to versions before 10.1 in 		// soft upgrade mode. 		writeChecksum = logFactory.checkVersion(RawStoreFactory.DERBY_STORE_MAJOR_VERSION_10, 												RawStoreFactory.DERBY_STORE_MINOR_VERSION_1);		if(writeChecksum)		{			/**			 * setup structures that are required to write the checksum log records			 * for a group of log records are being written to the disk. 			 */			checksumLogOperation = new ChecksumOperation();			checksumLogOperation.init();			checksumLogRecord = new LogRecord();			// Note: Checksum log records are not related any particular transaction, 			// they are written to store a checksum information identify			// incomplete log record writes. No transacton id is set for this			// log record. That is why a null argument is passed below 			// setValue(..) call. 			checksumLogRecord.setValue(null, checksumLogOperation);			checksumLength = 				checksumLogRecord.getStoredSize(checksumLogOperation.group(), null) + 				checksumLogOperation.getStoredSize();			// calculate checksum log operation length when the database is encrypted			if (logFactory.databaseEncrypted())			{				checksumLength =  logFactory.getEncryptedDataLength(checksumLength);				databaseEncrypted = true;			}			checksumLogRecordSize = checksumLength  + LOG_RECORD_FIXED_OVERHEAD_SIZE;			//streams required to convert a log record to raw byte array. 			logOutputBuffer = new ArrayOutputStream(); 			logicalOut = new FormatIdOutputStream(logOutputBuffer);			/** initialize the buffer with space reserved for checksum log record in			 * the beginning of the log buffer; checksum record is written into			 * this space when buffer is switched or while doing direct write to the log file.			 */		}else		{			//checksumming of transaction log feature is not in use. 			checksumLogRecordSize = 0;		}				currentBuffer.init(checksumLogRecordSize);	}	private byte[] db = new byte[LOG_RECORD_TRAILER_SIZE];     /**     * Write a single log record to the stream.     * <p>     * For performance pass all parameters rather into a specialized routine     * rather than maintaining the writeInt, writeLong, and write interfaces     * that this class provides as a standard OutputStream.  It will make it     * harder to use other OutputStream implementations, but makes for less     * function calls and allows optimizations knowing when to switch buffers.     * <p>     * This routine handles all log records which are smaller than one log     * buffer.  If a log record is bigger than a log buffer it calls     * writeUnbufferedLogRecord().     * <p>     * The log record written will always look the same as if the following     * code had been executed:     *     writeInt(length)     *     writeLong(instant)     *     write(data, data_offset, (length - optional_data_length) )     *     *     if (optional_data_length != 0)     *         write(optional_data, optional_data_offset, optional_data_length)     *     *     writeInt(length)     *     * @param length                (data + optional_data) length bytes to write     * @param instant               the log address of this log record.     * @param data                  "from" array to copy "data" portion of rec     * @param data_offset           offset in "data" to start copying from.     * @param optional_data         "from" array to copy "optional data" from     * @param optional_data_offset  offset in "optional_data" to start copy from     * @param optional_data_length  length of optional data to copy.     *	 * @exception  StandardException  Standard exception policy.     **/    public void writeLogRecord(    int     length,    long    instant,    byte[]  data,    int     data_offset,    byte[]  optional_data,    int     optional_data_offset,    int     optional_data_length)        throws StandardException, IOException     {        int total_log_record_length = length + LOG_RECORD_FIXED_OVERHEAD_SIZE;		if (total_log_record_length <= currentBuffer.bytes_free)        {            byte[] b    = currentBuffer.buffer;            int    p    = currentBuffer.position;            // writeInt(length)			p = writeInt(length, b, p);                        // writeLong(instant)			p = writeLong(instant, b , p);            // write(data, data_offset, length - optional_data_length)            int transfer_length = (length - optional_data_length);			System.arraycopy(data, data_offset, b, p, transfer_length);            p += transfer_length;            if (optional_data_length != 0)            {                // write(                //   optional_data, optional_data_offset, optional_data_length);                System.arraycopy(                    optional_data, optional_data_offset,                     b,             p,                     optional_data_length);                p += optional_data_length;            }            // writeInt(length)			p = writeInt(length, b, p);            			currentBuffer.position   = p;            currentBuffer.bytes_free -= total_log_record_length;		}        else        {						/** Because current log record will never fit in a single buffer			 * a direct write to the log file is required instead of 			 * writing the log record through  the log bufffers. 			 */			directWrite = true;			byte[] b    = currentBuffer.buffer;            int    p    = currentBuffer.position;            // writeInt(length)			p = writeInt(length , b, p);                        // writeLong(instant)			p = writeLong(instant, b, p);			currentBuffer.position   = p;			currentBuffer.bytes_free -= LOG_RECORD_HEADER_SIZE;			/** using a seperate small buffer to write the traling length			 * instead of the log buffer because data portion will be 			 * written directly to log file after the log buffer is 			 * flushed and the trailing length should be written after that. 			 */			// writeInt(length)			writeInt(length , db, 0);			if(writeChecksum)			{				checksumLogOperation.reset();				checksumLogOperation.update(b, checksumLogRecordSize, p - checksumLogRecordSize);				checksumLogOperation.update(data, data_offset, length - optional_data_length);				if (optional_data_length != 0)				{					checksumLogOperation.update(optional_data, optional_data_offset, optional_data_length);					}				// update the checksum to include the trailing length.				checksumLogOperation.update(db, 0, LOG_RECORD_TRAILER_SIZE);							// write checksum log record to the log buffer 				writeChecksumLogRecord();			}									// now do the  writes directly to the log file. 			// flush all buffers before wrting directly to the log file. 			flushLogAccessFile();			// Note:No Special Synchronization required here , 			// There will be nothing to write by flushDirtyBuffers that can run			// in parallel to the threads that is executing this code. Above			// flush call should have written all the buffers and NO new log will 			// get added until the following direct log to file call finishes. 			// write the rest of the log directltly to the log file.             writeToLog(data, data_offset, length - optional_data_length);            if (optional_data_length != 0)            {                writeToLog(                    optional_data, optional_data_offset, optional_data_length);            }			// write the trailing length 			writeToLog(db,0, 4);			directWrite = false;		}    }	private final int writeInt(int i , byte b[], int p)	{	        b[p++] = (byte) ((i >>> 24) & 0xff);         b[p++] = (byte) ((i >>> 16) & 0xff);         b[p++] = (byte) ((i >>> 8) & 0xff);         b[p++] = (byte) (i & 0xff);			return p;	}	private final int writeLong(long l , byte b[], int p)	{		b[p++] = (byte) (((int)(l >>> 56)) & 0xff);         b[p++] = (byte) (((int)(l >>> 48)) & 0xff);         b[p++] = (byte) (((int)(l >>> 40)) & 0xff);         b[p++] = (byte) (((int)(l >>> 32)) & 0xff);         b[p++] = (byte) (((int)(l >>> 24)) & 0xff);         b[p++] = (byte) (((int)(l >>> 16)) & 0xff);         b[p++] = (byte) (((int)(l >>> 8)) & 0xff);         b[p++] = (byte) (((int)l) & 0xff); 		return p;	}	public void writeInt(int i)     {		if (SanityManager.DEBUG)		{			SanityManager.ASSERT(currentBuffer.bytes_free >= 4);		}				currentBuffer.position = 			writeInt(i , currentBuffer.buffer, currentBuffer.position);		currentBuffer.bytes_free -= 4;	}	public void writeLong(long l)     {				if (SanityManager.DEBUG)		{			SanityManager.ASSERT(currentBuffer.bytes_free >= 8);		}				currentBuffer.position = 			writeLong(l , currentBuffer.buffer, currentBuffer.position);		currentBuffer.bytes_free -= 8;    }	public void write(int b)     {		if (SanityManager.DEBUG)		{			SanityManager.ASSERT(currentBuffer.bytes_free > 0);		}				currentBuffer.buffer[currentBuffer.position++] = (byte) b;		currentBuffer.bytes_free--;	}	public void write(byte b[], int off, int len)     {		if (SanityManager.DEBUG)		{			SanityManager.ASSERT(len <= currentBuffer.bytes_free);		}				System.arraycopy(b, off, currentBuffer.buffer, currentBuffer.position, len);

⌨️ 快捷键说明

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