FileDocCategorySizeDatePackage
LogControl.javaAPI DocGlassfish v2 API34205Fri May 04 22:36:38 BST 2007com.sun.jts.CosTransactions

LogControl

public class LogControl extends Object
This class holds the top level information for an instance of the log,
version
0.01
author
Simon Holdsworth, IBM Corporation
see

Fields Summary
private static final String
CUSHION_NAME
Constants for file name extensions.
private static final String
EXTENT_NAME
private static final String
CONTROL_NAME
public static final String
RECOVERY_STRING_FILE_NAME
private static final String
LOG_EXTENSION
private static final char[]
EXTENT_CHARS
boolean
logInitialised
Internal instance members
boolean
logReadOnly
Vector
logHandles
String
directoryPath
File
controlFile
File
cushionFile
Constructors Summary
Methods Summary
static booleancheckFileExists(java.lang.String logId, java.lang.String logDirectory)
Determines whether the given named log exists in the given directory.

param
logId The log identifier.
param
logDirectory The log directory.
return
Indicates whether the file exists.
see


		//START IASRI 4730519
		if(logDirectory==null)
		    return false;
		//END IASRI 4730519
        boolean exists = controlFile(logId,logDirectory).exists();

        return exists;
    
synchronized voidcleanUp(LogHandle logHandle)
Cleans up the given log file.

param
logHandle The log to clean up.
return
exception
LogException The operation failed.
see


        // IF not LogInitialised Return LOG_NOT_INITIALISED

        if( !logInitialised )
            throw new LogException(null,LogException.LOG_NOT_INITIALISED,1);

        // Check BlockValid field in Log_FileDescriptor block and
        // ensure it is valid
        // IF not valid Log_FileDescriptor
        //   Return LOG_INVALID_FILE_DESCRIPTOR

        if( logHandle == null || logHandle.blockValid != logHandle )
            throw new LogException(null,LogException.LOG_INVALID_FILE_DESCRIPTOR,2);

        // Set the block valid to NULL

        logHandle.blockValid = null;

        // Remove all extent entries from the log file's extent hash table

        logHandle.cleanUpExtents();

        // Unchain the Log_FileDescriptor block from the RCA chain.  The
        // mutices contained in the FD latch structure will already have been
        // freed up when the AS process which owned them died.  We indicate this
        // by setting the ProcessOwnsLatch parameter to FALSE.

        removeFile(logHandle);

    
static voidclearDirectory(java.lang.String logDir)
Clears out all log files from the given directory.

param
logDir
return
see

        // Find each control file in turn and then delete all files that
        // begin with the same name. This will delete all files associated
        // with that log (including the control file so that it is not found
        // again next time through the loop)

        File directory = new File(logDir);
        String[] allFiles = directory.list();

        for( int i = 0; i < allFiles.length; i++ ) {

            // Determine if the file is actually a log subdirectory.  If so, use it's name
            // to delete all associated log files.
            if( allFiles[i].endsWith(LOG_EXTENSION) ) {
                //Start IASRI 4720539
                final File logFileDir = new File(directory,allFiles[i]);
                if( logFileDir.isDirectory() ) {
                    final String[] logFiles = logFileDir.list();
                    /*
                    for( int j = 0; j < logFiles.length; j++ )
                        new File(logFileDir,logFiles[j]).delete();
                    logFileDir.delete();
                    */                                        
                    java.security.AccessController.doPrivileged(
                        new java.security.PrivilegedAction() {
                            public Object run(){
                                for( int j = 0; j < logFiles.length; j++ ){
                                    new File(logFileDir,logFiles[j]).delete();                                    
                                }
                                return null;
                            }
                        }
                    );                    
                    java.security.AccessController.doPrivileged(
                        new java.security.PrivilegedAction() {
                            public Object run(){
                                logFileDir.delete();
                                return null;
                            }
                        }
                    );                    
                }
                //End IASRI 4720539
            }            
        }

    
static final java.io.FilecontrolFile(java.lang.String logId, java.lang.String logDir)
Builds a log control file.

param
logId Log identifier.
param
logDir Log directory.
return
A File object representing the control file.
see

        File result = new File(directory(logId,logDir),CONTROL_NAME);
        return result;
    
final java.io.FilecushionFile(java.lang.String logId)
Builds a log cushion file.

param
logId Log identifier.
return
A File object representing the cushion file.
see


        File result = new File(directory(logId,directoryPath),CUSHION_NAME);

        return result;
    
static final java.io.Filedirectory(java.lang.String logId, java.lang.String logDir)
Builds a log directory file.

param
logId Log identifier.
param
logDir Base log directory.
return
A File object representing the directory.
see


	//START IASRI 4721336
	//START IASRI 4730519
	if(logDir==null) //It should not be null
       	return new File( "." + File.separator + logId + LOG_EXTENSION);
	//END IASRI 4730519
    return new File(logDir);
	//END IASRI 4721336
    
voiddump()
Dumps the state of the object.

param
return
see

        // If the log has been initialised the pointer to the global
        // data will have been initialised. So, if the pointer to the
        // global data is not NULL, dump out the its contents.
    
java.io.FileextentFile(java.lang.String logId, int extent)
Builds a log extent file.

param
logId Log identifier.
param
extent Extent number.
return
A File object representing the extent file.
see


        char[] buff = (char[])EXTENT_CHARS.clone();

        int tmpExtent   = extent / LogExtent.EXTENT_RADIX;
        int extentLow  = extent % LogExtent.EXTENT_RADIX;
        int extentMid  = tmpExtent % LogExtent.EXTENT_RADIX;
        int extentHigh = tmpExtent / LogExtent.EXTENT_RADIX;

        buff[7]  = (char)(extentHigh + (extentHigh > 9 ? 'A"-10 : '0"));
        buff[8]  = (char)(extentMid  + (extentMid  > 9 ? 'A"-10 : '0"));
        buff[9] = (char)(extentLow  + (extentLow  > 9 ? 'A"-10 : '0"));

        String fileName = new String(buff);
        File result = new File(directory(logId,directoryPath),fileName);

        return result;
    
synchronized voidinitLog(boolean coldStart, boolean readOnly, java.lang.String logDirectory)
Initialises the log in the given directory.

param
coldStart Cold start indicator.
param
readOnly Read only log indicator.
param
logDirectory Directory for log files.
return
see


    //static processSharedLog = GlobLock();

                                            
        
                                
                                   

        // Trace the global state of the log.

        // IF logInitialised
        //    Unlock the LogGlobalMutex
        //    Return LOG_SUCCESS

        if( logInitialised ) {
            return;
        }

        logReadOnly = readOnly;

        // Store the log directory name for use by subsequent log functions.

        directoryPath = new String(logDirectory);

        // If this is a cold start, then remove all files in the log directory

        if( coldStart && !readOnly )
            clearDirectory(logDirectory);

        // Create the Vector which will hold the LogHandles.

        logHandles = new Vector();

        // Set the logInitialised flag to TRUE
        // Unlock the logGlobalMutex
        // Return LOG_SUCCESS

        logInitialised = true;

    
synchronized LogHandleopenFile(java.lang.String logFileName, LogUpcallTarget upcallTarget, java.lang.String baseNewName, boolean[] newlyCreated)
Opens a log file with the given name and upcall.

param
logName Name of log.
param
upcallTarget Upcall for log file.
param
baseNewName Base of new name for log file.
param
newlyCreated A one-element array to hold the newly created indicator.
return
Handle for the log file.
exception
LogException The open failed.
see


        // IF not LogInitialised
        //   Return LOG_NOT_INITIALISED

        if( !logInitialised )
            throw new LogException(null,LogException.LOG_NOT_INITIALISED,1);

        // If the logid provided is an Alias name, it could be more than 8
        // characters. If so, to support the FAT file system, a unique
        // 8 character must be generated
        // If the name is an Alias name, then the base new name to use will have
        // been passed in as a parameter.

        String logName = null;

        /*  if( baseNewName != null )
            {
            int i = 0;

            // Determine the index to start allocating from based on the base

            if( baseNewName.length() != 0 )
            {
            try
            { i = Integer.parseInt(baseNewName.substring(LogHandle.FILENAME_PREFIX_LEN+1,LogHandle.FILENAME_PREFIX_LEN+3),16); }
            catch( Throwable e ) {}
            i++;
            }

            // Generate a new name from the base.

            boolean logExists;
            for( logExists = true;
            i <= LogHandle.MAX_NAMES && logExists;
            i++)
            {
            logName = new String(FILENAME_PREFIX);
            if( i < 100 ) logName += "0";
            if( i < 10  ) logName += "0";
            logName += Integer.toString(i);
            logExists = checkFileExists(logName,directoryPath);
            }
            }
            else
        */    {

            // If the log Id is provided is not an Alias make make sure it
            // meets the FAT file system requirements

            /*    if( logFileName.length() != LogHandle.NAME_LENGTH )
                  throw new LogException(null,LogException.LOG_INVALID_FILE_DESCRIPTOR,19);
            */
            logName = logFileName;
            File logDir = directory(logName,directoryPath);
            if( !logDir.exists() )
                logDir.mkdir();
        }

        // Build name of log's control file, e.g. (<logname>.control)
        // Issue OPEN request for control file, specifying Read/Write, Create,
        // No-share and 'guaranteed write to disk' options
        // IF OPEN is not successful
        //   Return LOG_OPEN_FAILURE

        controlFile = controlFile(logName,directoryPath);
        cushionFile = cushionFile(logName);

        int openOptions = LogFileHandle.OPEN_RDWR  |
            LogFileHandle.OPEN_CREAT |
            LogFileHandle.OPEN_SYNC; // Default open options
        if( logReadOnly )
            openOptions = LogFileHandle.OPEN_RDONLY;

        LogFileHandle controlFH;
        try {
            controlFH = new LogFileHandle(controlFile,openOptions);
        } catch( LogException le ) {
            throw new LogException(null,LogException.LOG_OPEN_FAILURE,3);
        }

        // Allocate a Log_FileDescriptor block and initialise it
        // IF allocate fails
        //   Close the control file
        //   Return LOG_INSUFFICIENT_MEMORY

        LogHandle logHandle = null;
        try {
            logHandle = new LogHandle(this,logName,controlFH,upcallTarget); }
        catch( LogException le ) {
            controlFH.finalize();
            throw new LogException(null,LogException.LOG_INSUFFICIENT_MEMORY,4);
        }


        // Call Log_RestoreCushion to create/check the cushion file exists
        // for this logfile. If this fails the log cannot be opened.

        try {
            logHandle.restoreCushion(false); 
        } catch( LogException le ) {
            controlFH.finalize();
            throw new LogException(null,LogException.LOG_INSUFFICIENT_MEMORY,9);
        }

        // Issue a READ request for the control file, specifying the
        // Log_ControlDescriptor structure within the Log_FileDescriptor
        // block as the input buffer
        // IF not successful (rc == -1)
        //   Close the control file
        //   Deallocate the Log_FileDescriptor block
        //   Return LOG_READ_FAILURE

        byte[] controlBytes = new byte[LogControlDescriptor.SIZEOF];
        int bytesRead = 0;
        try {
            bytesRead = controlFH.fileRead(controlBytes); 
        } catch( LogException le ) {
            controlFH.finalize();
            throw new LogException(null,LogException.LOG_READ_FAILURE,5);
        }

        if( bytesRead == 0 ) {

            // IF the READ returned EOF (rc == 0), continue with initialisation of
            // the Log_ControlDescriptor structure within the
            // Log_FileDescriptor block
            // - Initialise the log head LSN to LOG_NULL_LSN
            // - Initialise the log tail LSN to LOG_FIRST_LSN
            // - Initialise the next free LSN to LOG_FIRST_LSN
            // - Initialise the RestartDataLength in the Log_FileDescriptor
            //   block to 0
            //
            // Set NewlyCreated parameter to TRUE
            //
            // Pre-allocate all the file storage for the control file
            //
            // Set RecordsWritten to LOG_CONTROL_FORCE_INTERVAL so on
            // the first write to the log the newly created control data
            // is written to disk. If this is not done then data could be lost.
            //
            // Write the control data to file
            //
            // Open the first extent file and allocate the storage it requires.
            // If either step fails close and erase the control file and
            // return LOG_INSUFFICIENT_STORAGE.

            logHandle.logControlDescriptor.headLSN.copy(LogLSN.NULL_LSN);
            logHandle.logControlDescriptor.tailLSN.copy(LogLSN.FIRST_LSN);
            logHandle.logControlDescriptor.nextLSN.copy(LogLSN.FIRST_LSN);
            logHandle.restartDataLength = 0;
            logHandle.recordsWritten = LogHandle.CONTROL_FORCE_INTERVAL;
            newlyCreated[0] = true;

            if( !logReadOnly ) {
                int bytesWritten;

                try {
                    controlFH.allocFileStorage(LogHandle.CONTROL_FILE_SIZE); 
                } catch( LogException le ) {
                    controlFH.finalize();
                    throw new LogException(null,LogException.LOG_WRITE_FAILURE,6);
                }

                logHandle.logControlDescriptor.toBytes(controlBytes,0);
                try {
                    bytesWritten = controlFH.fileWrite(controlBytes);
                } catch( LogException le ) {
                    controlFH.finalize();
                    throw new LogException(null,LogException.LOG_WRITE_FAILURE,7);
                }

                LogExtent logEDP = null;
                try {
                    logEDP = logHandle.openExtent(logHandle.logControlDescriptor.nextLSN.extent);
                } catch( LogException le ) {
                    controlFH.finalize();
                    throw new LogException(null,LogException.LOG_NO_SPACE,10);
                }

                try {
                    logEDP.fileHandle.allocFileStorage(LogHandle.ALLOCATE_SIZE); 
                } catch( LogException le ) {
                    controlFH.finalize();
                    throw new LogException(null,LogException.LOG_NO_SPACE,11);
                }

                logHandle.chunkRemaining = LogHandle.ALLOCATE_SIZE;
            }
        }

        // Otherwise the log already exists.

        else {
            int timeStampRec1;                    // The time stamp in restart rec 1
            int timeStampRec2;                    // The time stamp in restart rec 2
            int lengthRec1;                       // The length of restart record 1
            int lengthRec2;                       // The length of restart record 1

            // Set NewlyCreated parameter to FALSE

            newlyCreated[0] = false;

            // Open all of the active extents and
            // rebuild the extent table, starting form the extent
            // containing the Tail LSN and finishing with the extent
            // containing the Head LSN

            logHandle.logControlDescriptor = new LogControlDescriptor(controlBytes,0);

            LogExtent logEDP = null;
            for( int currentExtent = logHandle.logControlDescriptor.tailLSN.extent;
                 currentExtent <= logHandle.logControlDescriptor.headLSN.extent ||
                     currentExtent <= logHandle.logControlDescriptor.nextLSN.extent;
                 currentExtent++)
                try {
                    logEDP = logHandle.openExtent(currentExtent); 
                } catch( LogException le ) {
                    controlFH.finalize();
                    throw new LogException(null,LogException.LOG_OPEN_EXTENT_FAILURE,19);
                }

            // Read the restart data for restart record one
            // If the read failed then
            //   Close the control file
            //   Deallocate the Log_FileDescriptor block
            //   Return LOG_READ_FAILURE

            int[] restartValues1 = new int[2];
            int[] restartValues2 = new int[2];

            try {
                logHandle.checkRestart(controlFH,1,restartValues1); 
            } catch( LogException le ) {
                controlFH.finalize();
                throw new LogException(null,LogException.LOG_READ_FAILURE,8);
            }

            // Check that the record length was not equal to zero
            // IF the record length was not equal to zero
            //   READ the next restart record
            //   IF ( (Length2 !=0) && (Time2 > Time1)
            //   THEN CurrentValid is 2
            //   ELSE CurrentValid is 1

            // BUGFIX(Ram Jeyaraman) Always check both the restart records,
            // even though the first record might have zero data length.
            // It is possible, that the second record might 
            // have non-zero data length with a later
            // timestamp, even though the first record has zero data length.
            // Fix is to comment out the check below.
            //if (restartValues1[0] != 0)
            {

                // If the read failed then
                //   Close the control file
                //   Deallocate the Log_FileDescriptor block
                //   Return LOG_READ_FAILURE

                try {
                    logHandle.checkRestart(controlFH,2,restartValues2);
                } catch( LogException le ) {
                    controlFH.finalize();
                    throw new LogException(null,LogException.LOG_READ_FAILURE,9);
                }

                if( restartValues2[0] != 0 &&
                    restartValues2[1] > restartValues1[1] ) {
                    logHandle.activeRestartVersion = 2;
                    logHandle.restartDataLength    = restartValues2[0];
                } else {
                    logHandle.activeRestartVersion = 1;
                    logHandle.restartDataLength    = restartValues1[0];
                }
            }

            if( logHandle.logControlDescriptor.headLSN.isNULL() )
                logHandle.recordsWritten = LogHandle.CONTROL_FORCE_INTERVAL;
        }

        // Add the Log_FileDescriptor block to the head of the
        // (LogFileDescriptorHead) chain hung off the RCA and update the backward
        // chain pointer of the block which was previously at the head of the chain.

        logHandles.addElement(logHandle);

        // IF the head LSN in Log_ControlDescriptor != LOG_NULL_LSN
        // Build the extent file name from the head LSN
        // Issue an OPEN request for the file

        if( !logHandle.logControlDescriptor.headLSN.isNULL() ) {
            int offset;                           // Present offset in the open extent
            LogRecordHeader extentRec,            // An extent record header
                headRec,              // An extent record header
                linkRec;              // An extent record header
            boolean lastValidRead = false;        // Has the last valid record be read
            LogExtent logEDP = null;

            // IF not successful (rc == -1)
            //   Close the control file
            //   Unchain the LogFDP and free up the storage
            //   Return LOG_OPEN_FAILURE

            // Allocate a Log_ExtentDescriptor block and initialise it
            // Hash the extent number to find the anchor for this extent in the
            // hash table and add it to the head of the chain
            // Move the file pointer to the head LSN record (using LSEEK)

            try {
                logEDP = logHandle.positionFilePointer(logHandle.logControlDescriptor.headLSN,
                                                       0,LogExtent.ACCESSTYPE_READ); }
            catch( LogException le ) {
                controlFH.finalize();
                removeFile(logHandle);
                throw new LogException(null,LogException.LOG_OPEN_FAILURE,10);
            }

            // Issue a READ for the record header
            // IF the read is not successful (rc <= 0)
            //   Close the control file
            //   Deallocate newly acquired control blocks
            //   Return LOG_READ_FAILURE
            //
            // Check that the LSN in the record header matches the head LSN
            // IF there is a mismatch
            //   Deallocate newly acquired control blocks
            //   Return LOG_CORRUPTED

            byte[] headerBytes = new byte[LogRecordHeader.SIZEOF];

            try {
                bytesRead = logEDP.fileHandle.fileRead(headerBytes);
            } catch( LogException le ) {
                controlFH.finalize();
                removeFile(logHandle);
                throw new LogException(null,le.errorCode,11);
            }
            extentRec = new LogRecordHeader(headerBytes,0);

            if( !extentRec.currentLSN.equals(logHandle.logControlDescriptor.headLSN) ) {
                controlFH.finalize();
                removeFile(logHandle);
                throw new LogException(null,LogException.LOG_CORRUPTED,12);
            }

            // Copy the record header to HEADERCOPY
            // Move the file pointer to the 'next LSN' in record header

            logEDP.cursorPosition += bytesRead;
            headRec = new LogRecordHeader();
            headRec.copy(extentRec);
            offset = headRec.nextLSN.offset;

            try {
                logEDP = logHandle.positionFilePointer(extentRec.nextLSN,0,LogExtent.ACCESSTYPE_READ);
            } catch( LogException le ) {
                controlFH.finalize();
                removeFile(logHandle);
                throw new LogException(null,LogException.LOG_OPEN_FAILURE,13);
            }

            linkRec = new LogRecordHeader();

            // LOOP until last valid log record has been read

            lastValidRead = false;
            do {
                // Issue a read for the record header

                offset = extentRec.nextLSN.offset;

                try {
                    bytesRead = logEDP.fileHandle.fileRead(headerBytes);
                } catch( LogException le ) {
                    controlFH.finalize();
                    removeFile(logHandle);
                    throw new LogException(null,LogException.LOG_READ_FAILURE,14);
                }
                if( bytesRead == -1 ) {
                    controlFH.finalize();
                    removeFile(logHandle);
                    throw new LogException(null,LogException.LOG_READ_FAILURE,14);
                }

                extentRec = new LogRecordHeader(headerBytes,0);
                logEDP.cursorPosition += bytesRead;

                // IF the LSN in the record header matches the LSN of the
                // current position in the extent file

                if( extentRec.currentLSN.offset == offset ) {
                    // IF its a link record

                    if( extentRec.recordType == LogHandle.LINK ) {
                        // Copy it to LINKCOPY
                        // 'Move' the file pointer to the NextRecord value (in the next extent file)
                        // Iterate.

                        linkRec.copy(extentRec);
                        try {
                            logEDP = logHandle.positionFilePointer(extentRec.nextLSN,0,LogExtent.ACCESSTYPE_READ);
                        } catch( LogException le ) {
                            controlFH.finalize();
                            removeFile(logHandle);
                            throw new LogException(null,le.errorCode,15);
                        }
                        continue;
                    } else

                        // IF LINKCOPY is not null AND LINKCOPY.NextRecord LSN &lnot.= ThisRecord LSN
                        //   Set LINKCOPY to null

                        if( !linkRec.currentLSN.isNULL() &&
                            !linkRec.nextLSN.equals(extentRec.currentLSN) )
                            linkRec = new LogRecordHeader();

                    // Copy the record header to HEADERCOPY
                    // Use the NextRecord value to move the file pointer to the next record header

                    headRec.copy(extentRec);
                    try {
                        logEDP = logHandle.positionFilePointer(extentRec.nextLSN,0,LogExtent.ACCESSTYPE_READ);
                    } catch( Throwable e ) {}
                } else {
                    LogRecordEnding endRec;           // An ending record type

                    lastValidRead = true;

                    // Use the ThisRecord value from HEADERCOPY together with the
                    // RecordLength value to calculate the position of the previous
                    // Log_RecordEnding structure
                    //
                    // LSEEK to this position and read it

                    try {
                        logEDP = logHandle.positionFilePointer(headRec.currentLSN,
                                                               LogRecordHeader.SIZEOF+headRec.recordLength,
                                                               LogExtent.ACCESSTYPE_READ); 
                    } catch( LogException le ) {
                        controlFH.finalize();
                        removeFile(logHandle);
                        throw new LogException(null,le.errorCode,16);
                    }

                    byte[] endingBytes = new byte[LogRecordEnding.SIZEOF];

                    try {
                        bytesRead = logEDP.fileHandle.fileRead(endingBytes);
                    } catch( LogException le ) {
                        controlFH.finalize();
                        removeFile(logHandle);
                        throw new LogException(null,le.errorCode,17);
                    }

                    endRec = new LogRecordEnding(endingBytes,0);

                    logEDP.cursorPosition += bytesRead;

                    // IF its value is the same as ThisRecord LSN This is the last valid record
                    // Update head LSN in control data with ThisRecord LSN
                    // Update next LSN in control data with the NextRecord LSN

                    if( endRec.currentLSN.equals(headRec.currentLSN) ) {
                        logHandle.logControlDescriptor.headLSN.copy(headRec.currentLSN);
                        logHandle.logControlDescriptor.nextLSN.copy(headRec.nextLSN);
                    }

                    // This is an invalid record, so record details of previous valid record
                    // IF LINKCOPY is null
                    // Update head LSN in control data with the PreviousRecord LSN
                    // Update next LSN in control data with ThisRecord LSN

                    else {
                        if( linkRec.currentLSN.isNULL() ) {
                            logHandle.logControlDescriptor.headLSN.copy(headRec.previousLSN);
                            logHandle.logControlDescriptor.nextLSN.copy(headRec.currentLSN);
                        }

                        // Otherwise update head LSN in control data with value from LINKCOPY

                        else { 
                            logHandle.logControlDescriptor.headLSN.copy(linkRec.previousLSN);
                            logHandle.logControlDescriptor.nextLSN.copy(linkRec.currentLSN);
                        }
                    }
                }

                // Increase the number of records written since the last force

                logHandle.recordsWritten++;
            }
            while( !lastValidRead );
        }

        // Store the address of the Log_FileDescriptor block into its BlockValid field

        logHandle.blockValid = logHandle;

        return logHandle;
    
static final java.io.FilerecoveryIdentifierFile(java.lang.String logId, java.lang.String logDir)

        File result = new File(directory(logId,logDir),RECOVERY_STRING_FILE_NAME);
        return result;
    
synchronized voidremoveFile(LogHandle logHandle)
Removes the log file from the chain.

param
logHandle
return
see


        // Unchain the Log_FileDescriptor block from the RCA chain

        logHandles.removeElement(logHandle);

        // Clear the BlockValid field in the Log_FileDescriptor block

        logHandle.blockValid = null;