File: Base\MS\Internal\IO\Zip\IZipIOBlock.cs
Project: wpf\src\WindowsBase.csproj (WindowsBase)
//-----------------------------------------------------------------------------
//-------------   *** WARNING ***
//-------------    This file is part of a legally monitored development project.  
//-------------    Do not check in changes to this project.  Do not raid bugs on this
//-------------    code in the main PS database.  Do not contact the owner of this
//-------------    code directly.  Contact the legal team at ‘ZSLegal’ for assistance.
//-------------   *** WARNING ***
//-----------------------------------------------------------------------------
 
//-----------------------------------------------------------------------------
//
// <copyright file="IZipIOBlock.cs" company="Microsoft">
//    Copyright (C) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// Description:
//  This is an internal class that enables interactions with Zip archives
//  for OPC scenarios 
//
// History:
//  11/19/2004: IgorBel: Initial creation.
//
//-----------------------------------------------------------------------------
 
using System;
using System.IO;
 
namespace MS.Internal.IO.Zip
{   
    internal enum PreSaveNotificationScanControlInstruction : int 
    {
        Continue = 0,   // instruction to continue Pre Save Notification on the following block 
        Stop = 1,          // instruction to stop Pre Save Notification loop
    }
 
    /// <summary>
    /// IZipIOBlock - this interface is used to enable polymorphism across all 
    /// supported Zip IO records. This enables ZipIOBlockManager to manipulate all blocks in a uniform way
    /// </summary>
    internal interface IZipIOBlock
    {
        /// <summary>
        /// This is the current offset of the block relative to the start of the archive stream.
        /// It might not necessarily correspond to the current location
        /// of the block on disk. It is rather the Offset that will be used by the Save function to write data out. 
        /// If Block Manager needs to insert a new block it should call Move which in Turn will mark those blocks 
        /// dirty and will change the offset. 
        /// </summary>
        long Offset{get;}
 
        /// <summary>
        /// This is the current size of the block,  it might not neccessarily correspond to the current size of the 
        /// block on disk. It is rather the Size that will be used up if Save function is called. Block Manager 
        /// doesn't have any direct control over this size. It is changeble only by Block Specific operations 
        /// (stream operations with ZipIOLocalFileBlock, add/remove files with the CentralDirectoryBlock and so on)
        /// </summary>
        long Size{get;}
 
        /// <summary>
        /// This is the current state of block, if block is marked dirty it means that it was either moved from the 
        /// original location of load, or it was changed by the external APIs. Block Manager 
        /// doesn't have any direct control over this flag. It can be affected by calls to Move,
        /// Save,  UpdateReferences and Block Specific operations (like stream operations with ZipIOLocalFileBlock, 
        /// add/remove files with the CentralDirectoryBlock and so on) 
        /// closingFlag parameter indicates whether we querying the Dirty state for purposes of flushing or closing.
        /// The only case where it makes a difference is the compressed stream. Which in the Write Through mode 
        /// will be Dirty for close but not Dirty for flush.
        /// </summary>
        bool GetDirtyFlag(bool closingFlag);
 
        /// <summary>
        /// This function is used by the ZipIOBlockManager to adjust positions of the block in the archive, it's mostly 
        /// used for adding/deleting new file item blocks. Call to this function with a parameter not equal to 0 must 
        /// mark the block as dirty. 
        /// </summary>
        void Move(long shiftSize);
 
        /// <summary>
        /// This function is used by the ZipIOBlockManager to Save given block into it's current Offset position.
        /// Call to this function will result in making DirtyFlag = false; 
        /// </summary>
        void Save(); 
 
        /// <summary>
        /// This function is used by the ZipIOBlockManager to prepare block for Saving. If called on a block this function 
        ///  is ultimately responsible for marking this block dirty for any reason including changes in other blocks. For example 
        /// during normal operation of the ZipIoBlock Manager EndOfCentralDirectoryBlock isn't updated with the location 
        /// and size of the Central Directory on every single operation that might affect it. Only just before saving 
        /// EndOfCentralDirectoryBlock is notified using update references call that it needs to check its' local record against 
        /// the position and size of the CentralDirectory. If there is a mismatch EndOfCentralDirectory will update it's local informtion
        /// and mark itself dirty. 
        /// Similar things happen when CentralDirectoryBlock is called to UpdateReferences; it walks through all RawDataBlocks 
        /// and FileItemBlocks, and updates Central Directory records accordingly. 
        /// closingFlag parameter indicates that we should be closing streams not just flushing them. It makes a huge 
        /// difference for deflate scenarios where Flush is NOP and Close is actually always writing out extra data.
        /// </summary>
        void UpdateReferences(bool closingFlag);
 
        /// <summary>
        /// This function is used by the ZipIOBlockManager to notify blocks that some area of the file is about to to be overwritten.
        /// Depending on the caching policy of each block type (or particular block instance), it might choose to ignore this notification. 
        /// For Example EndOfCentralDirectoryBlock and CentralDirectoryBlocks are always fully cached (have complete snapshot of 
        /// the latest data in memory). Which means, that they do not care whether the area of the file where this data has originated 
        /// is overwritten or not. 
        /// In contrast RawDataBlock and LocalFileBlock by default do not cache everything in memory, so they need to implement  
        /// PreSaveNotification call. These types of blocks need to at least load data that they might need from disk, and make sure that the
        /// area described by the parameters doesn't have any data that needs to be preserved. 
        ///         
        /// Block can also return a value indicating whether PreSaveNotification should be extended to the blocks that are positioned after 
        /// it in the Block List. For example, if block has completely handled PreSaveNotification in a way that it cached the whole area that 
        /// was in danger (of being overwritten) it means that no blocks need to worry about this anymore. After all, no 2 blocks should have 
        /// overlapping disk buffers. Another scenario is when a block can determine that the area in danger is positioned before the block's on-disk 
        /// buffers; this means that all blocks that are positioned later in the block list do not need to worry about this PreSaveNotification 
        /// as their buffers should be positioned even further along in the file. 
        /// </summary>
        PreSaveNotificationScanControlInstruction PreSaveNotification(long offset, long size);
    }
}