LCOV - code coverage report
Current view: directory - frmts/pcidsk/sdk/core - sysvirtualfile.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 68 43 63.2 %
Date: 2010-01-09 Functions: 5 4 80.0 %

       1                 : /******************************************************************************
       2                 :  *
       3                 :  * Purpose:  Implementation of the SysVirtualFile class.
       4                 :  *
       5                 :  * This class is used to manage access to a single virtual file stored in
       6                 :  * SysBData segments based on a block map stored in the SysBMDir segment 
       7                 :  * (and managed by SysBlockMap class). 
       8                 :  *
       9                 :  * The virtual files are allocated in 8K chunks (block_size) in segments.
      10                 :  * To minimize IO requests, other overhead, we keep one such 8K block in
      11                 :  * our working cache for the virtual file stream.  
      12                 :  *
      13                 :  * This class is primarily used by the CTiledChannel class for access to 
      14                 :  * tiled images.
      15                 :  * 
      16                 :  ******************************************************************************
      17                 :  * Copyright (c) 2009
      18                 :  * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
      19                 :  *
      20                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      21                 :  * copy of this software and associated documentation files (the "Software"),
      22                 :  * to deal in the Software without restriction, including without limitation
      23                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      24                 :  * and/or sell copies of the Software, and to permit persons to whom the
      25                 :  * Software is furnished to do so, subject to the following conditions:
      26                 :  *
      27                 :  * The above copyright notice and this permission notice shall be included
      28                 :  * in all copies or substantial portions of the Software.
      29                 :  *
      30                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      31                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      32                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      33                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      34                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      35                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      36                 :  * DEALINGS IN THE SOFTWARE.
      37                 :  ****************************************************************************/
      38                 : #include "pcidsk_config.h"
      39                 : #include "pcidsk_types.h"
      40                 : #include "pcidsk_buffer.h"
      41                 : #include "pcidsk_exception.h"
      42                 : #include "core/sysvirtualfile.h"
      43                 : #include "core/cpcidskfile.h"
      44                 : #include "segment/sysblockmap.h"
      45                 : #include <cassert>
      46                 : #include <cstring>
      47                 : 
      48                 : using namespace PCIDSK;
      49                 : 
      50                 : 
      51                 : const int SysVirtualFile::block_size = SYSVIRTUALFILE_BLOCKSIZE;
      52                 : 
      53                 : /************************************************************************/
      54                 : /*                           SysVirtualFile()                           */
      55                 : /************************************************************************/
      56                 : 
      57               3 : SysVirtualFile::SysVirtualFile( CPCIDSKFile *file, int start_block, 
      58                 :                                 uint64 image_length, 
      59                 :                                 PCIDSKBuffer &block_map_data,
      60                 :                                 SysBlockMap *sysblockmap,
      61               3 :                                 int image_index )
      62                 : 
      63                 : {
      64               3 :     file_length = image_length;
      65               3 :     this->file = file;
      66               3 :     this->sysblockmap = sysblockmap;
      67               3 :     this->image_index = image_index;
      68                 : 
      69               3 :     loaded_block = -1;
      70               3 :     loaded_block_dirty = false;
      71                 :     
      72               3 :     last_bm_index = -1;
      73                 : 
      74               3 :     int next_block = start_block;
      75                 : 
      76                 :     // perhaps we should defer all this work till the first request is made?
      77               9 :     while( next_block != -1 )
      78                 :     {
      79               3 :         int offset = 512 + next_block * 28;
      80                 : 
      81               3 :         block_segment.push_back( block_map_data.GetInt( offset+0, 4 ) );
      82               3 :         block_index.push_back( block_map_data.GetInt( offset+4, 8 ) );
      83                 : 
      84               3 :         last_bm_index = next_block;
      85               3 :         next_block = block_map_data.GetInt( offset + 20, 8 );
      86                 :     }
      87                 : 
      88               3 :     assert( block_index.size() * block_size >= file_length );
      89               3 : }
      90                 : 
      91                 : /************************************************************************/
      92                 : /*                          ~SysVirtualFile()                           */
      93                 : /************************************************************************/
      94                 : 
      95               3 : SysVirtualFile::~SysVirtualFile()
      96                 : 
      97                 : {
      98               3 :     if( loaded_block_dirty )
      99                 :     {
     100                 :         PCIDSKSegment *data_seg_obj = 
     101               0 :             file->GetSegment( block_segment[loaded_block] );
     102                 : 
     103                 :         data_seg_obj->WriteToFile( block_data, 
     104                 :                                    block_size * (uint64) block_index[loaded_block],
     105               0 :                                    block_size );
     106               0 :         loaded_block_dirty = false;
     107                 :     }
     108               3 : }
     109                 : 
     110                 : 
     111                 : /************************************************************************/
     112                 : /*                            WriteToFile()                             */
     113                 : /************************************************************************/
     114                 : 
     115                 : void 
     116               0 : SysVirtualFile::WriteToFile( const void *buffer, uint64 offset, uint64 size )
     117                 : 
     118                 : {
     119               0 :     uint64 buffer_offset = 0;
     120                 : 
     121               0 :     while( buffer_offset < size )
     122                 :     {
     123               0 :         int request_block = (int) ((offset + buffer_offset) / block_size);
     124               0 :         int offset_in_block = (int) ((offset + buffer_offset) % block_size);
     125                 :         int amount_to_copy;
     126                 : 
     127               0 :         LoadBlock( request_block );
     128                 : 
     129               0 :         amount_to_copy = block_size - offset_in_block;
     130               0 :         if( amount_to_copy > (int) (size - buffer_offset) )
     131               0 :             amount_to_copy = (int) (size - buffer_offset);
     132                 : 
     133                 :         memcpy( block_data + offset_in_block, 
     134                 :                 ((uint8 *) buffer) + buffer_offset, 
     135               0 :                 amount_to_copy );
     136                 : 
     137               0 :         loaded_block_dirty = true;
     138                 : 
     139               0 :         buffer_offset += amount_to_copy;
     140                 :     }
     141                 : 
     142               0 :     if( offset+size > file_length )
     143                 :     {
     144               0 :         file_length = offset+size;
     145               0 :         sysblockmap->SetVirtualFileSize( image_index, file_length );
     146                 :     }
     147               0 : }
     148                 : 
     149                 : /************************************************************************/
     150                 : /*                            ReadFromFile()                            */
     151                 : /************************************************************************/
     152                 : 
     153               7 : void SysVirtualFile::ReadFromFile( void *buffer, uint64 offset, uint64 size )
     154                 : 
     155                 : {
     156               7 :     uint64 buffer_offset = 0;
     157                 : 
     158              21 :     while( buffer_offset < size )
     159                 :     {
     160               7 :         int request_block = (int) ((offset + buffer_offset) / block_size);
     161               7 :         int offset_in_block = (int) ((offset + buffer_offset) % block_size);
     162                 :         int amount_to_copy;
     163                 : 
     164               7 :         LoadBlock( request_block );
     165                 : 
     166               7 :         amount_to_copy = block_size - offset_in_block;
     167               7 :         if( amount_to_copy > (int) (size - buffer_offset) )
     168               7 :             amount_to_copy = (int) (size - buffer_offset);
     169                 : 
     170                 :         memcpy( ((uint8 *) buffer) + buffer_offset, 
     171               7 :                 block_data + offset_in_block, amount_to_copy );
     172                 : 
     173               7 :         buffer_offset += amount_to_copy;
     174                 :     }
     175               7 : }
     176                 : 
     177                 : /************************************************************************/
     178                 : /*                             LoadBlock()                              */
     179                 : /************************************************************************/
     180                 : 
     181               7 : void SysVirtualFile::LoadBlock( int requested_block )
     182                 : 
     183                 : {
     184                 : /* -------------------------------------------------------------------- */
     185                 : /*      Do we already have this block?                                  */
     186                 : /* -------------------------------------------------------------------- */
     187               7 :     if( requested_block == loaded_block )
     188               4 :         return;
     189                 : 
     190                 : /* -------------------------------------------------------------------- */
     191                 : /*      Do we need to grow the virtual file by one block?               */
     192                 : /* -------------------------------------------------------------------- */
     193               3 :     if( requested_block == (int) block_index.size() )
     194                 :     {
     195                 :         int new_seg;
     196                 : 
     197                 :         block_index.push_back( 
     198                 :             sysblockmap->GrowVirtualFile( image_index, 
     199               0 :                                           last_bm_index, new_seg ) );
     200               0 :         block_segment.push_back( new_seg );
     201                 :     }
     202                 : 
     203                 : /* -------------------------------------------------------------------- */
     204                 : /*      Does this block exist in the virtual file?                      */
     205                 : /* -------------------------------------------------------------------- */
     206               3 :     if( requested_block < 0 || requested_block >= (int) block_index.size() )
     207                 :         ThrowPCIDSKException( "SysVirtualFile::LoadBlock(%d) - block out of range.",
     208               0 :                               requested_block );
     209                 : 
     210                 : /* -------------------------------------------------------------------- */
     211                 : /*      Do we have a dirty block loaded that needs to be saved?         */
     212                 : /* -------------------------------------------------------------------- */
     213               3 :     if( loaded_block_dirty )
     214                 :     {
     215                 :         PCIDSKSegment *data_seg_obj = 
     216               0 :             file->GetSegment( block_segment[loaded_block] );
     217                 :         
     218                 :         data_seg_obj->WriteToFile( block_data, 
     219                 :                                    block_size * (uint64) block_index[loaded_block],
     220               0 :                                    block_size );
     221               0 :         loaded_block_dirty = false;
     222                 :     }
     223                 : 
     224                 : /* -------------------------------------------------------------------- */
     225                 : /*      Load the requested block.                                       */
     226                 : /* -------------------------------------------------------------------- */
     227                 :     PCIDSKSegment *data_seg_obj = 
     228               3 :         file->GetSegment( block_segment[requested_block] );
     229                 : 
     230                 :     data_seg_obj->ReadFromFile( block_data, 
     231                 :                                 block_size * (uint64) block_index[requested_block],
     232               3 :                                 block_size );
     233                 : 
     234               3 :     loaded_block = requested_block;
     235               3 :     loaded_block_dirty = false;
     236                 : }
     237                 : 

Generated by: LCOV version 1.7