UTBufferedFile.h

Go to the documentation of this file.
00001 //==================================================================================================
00002 // Copyright (C) 2010  Brian Tietz    sdbtietz at yahoo dot com
00003 //
00004 // This program is free software; you can redistribute it and/or modify it under the terms of the
00005 // GNU General Public License as published by the Free Software Foundation, version 2.0 of the
00006 // License.
00007 //
00008 // This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
00009 // even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00010 // General Public License for more details.
00011 //
00012 // You should have received a copy of the GNU General Public License along with this program; if
00013 // not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00014 // 02110-1301, USA.
00015 //
00016 // For commercial software, the copyright holder (Brian Tietz, email sdbtietz at yahoo dot com)
00017 // reserves the right and is willing to waive the proprietary source code disclosure aspects of that
00018 // license as applied to the UT library in exchange for either substantial contributions to the
00019 // development of the UT library or other forms of compensation.  Any such waiver must be
00020 // established in writing between the copyright holder and the commercial entity obtaining such a
00021 // waiver.
00022 //==================================================================================================
00023 
00024 
00025 #ifndef _UT_BUFFERED_FILE_H_
00026 #define _UT_BUFFERED_FILE_H_
00027 
00028 
00029 //==================================================================================================
00030 //=== Project headers
00031 //==================================================================================================
00032 #include "UTFile.h"
00033 #include "UTLists.h"
00034 
00035 
00036 //==================================================================================================
00037 //=== Constants
00038 //==================================================================================================
00039 
00040 // \cond DOXYGEN_DOCUMENT_NEVER
00041 
00042 enum buffered_file_state_t
00043 {
00044     eBFS_closed,
00045     eBFS_opening,
00046     eBFS_idle,
00047     eBFS_write_work_buf,
00048     eBFS_read_work_buf,
00049     eBFS_write_block,
00050     eBFS_read_block,
00051     eBFS_preload_block
00052 };
00053 
00054 // \endcond
00055 
00056 
00057 //==================================================================================================
00058 //=== Forward name declarations
00059 //==================================================================================================
00060 class BufferedFileBlock_t;
00061 
00062 
00063 //==================================================================================================
00064 class UT_EXPORT BufferedFile_t
00065 //==================================================================================================
00066 :   public File_t,
00067     public Task_t
00069 {
00070     //----------------------------------------------------------------------------------------------
00071     public:
00072     //----------------------------------------------------------------------------------------------
00073                         BufferedFile_t(int buffer_size = 8192);
00080 
00081     virtual             ~BufferedFile_t();
00084 
00085     virtual Status_t    Open(   const Path_t& path,
00086                                 int flags,
00087                                 mode_t permissions = 0,
00088                                 MessageDestination_t<FileReadCompleteMessage_t>* read_dest = NULL,
00089                                 MessageDestination_t<FileWriteCompleteMessage_t>* write_dest = NULL,
00090                                 MessageDestination_t<FileOpenCompleteMessage_t>* open_dest = NULL );
00102 
00103     inline Status_t     Open(   const utf8* path,
00104                                 int flags,
00105                                 mode_t permissions = 0,
00106                                 MessageDestination_t<FileReadCompleteMessage_t>* read_dest = NULL,
00107                                 MessageDestination_t<FileWriteCompleteMessage_t>* write_dest = NULL,
00108                                 MessageDestination_t<FileOpenCompleteMessage_t>* open_dest = NULL );
00111 
00112     inline Status_t     Open(   stringliteral* path,
00113                                 int flags,
00114                                 mode_t permissions = 0,
00115                                 MessageDestination_t<FileReadCompleteMessage_t>* read_dest = NULL,
00116                                 MessageDestination_t<FileWriteCompleteMessage_t>* write_dest = NULL,
00117                                 MessageDestination_t<FileOpenCompleteMessage_t>* open_dest = NULL );
00120 
00121     virtual Status_t    Read( byte* buffer, int bytes_to_read, bool force_read_all = true );
00144 
00145     virtual Status_t    ReadLine(out String_t* line);
00151 
00152     virtual Status_t    Write(  const byte* buffer,
00153                                 int bytes_to_write,
00154                                 bool force_write_all = true );
00187 
00188     virtual Status_t    WriteLine(  const String_t& line,
00189                                     line_ending_type_t line_ending = eLINEENDING_native );
00194 
00195     virtual Status_t    WriteLine(  const utf8* line,
00196                                     line_ending_type_t line_ending = eLINEENDING_native );
00201 
00202     virtual Status_t    WriteLine(  stringliteral* line,
00203                                     line_ending_type_t line_ending = eLINEENDING_native );
00208 
00209     virtual Status_t    Size(out fileoff_t* size);
00212 
00213     virtual Status_t    Position(out fileoff_t* position);
00217 
00218     virtual Status_t    Seek(fileoff_t position);
00222 
00223     virtual Status_t    Flush();
00228 
00229     virtual Status_t    Close();
00238 
00239     //----------------------------------------------------------------------------------------------
00240     protected:
00241     //----------------------------------------------------------------------------------------------
00242     virtual Status_t    AsyncOpenComplete();
00244 
00245     #if LOG_FILE_OPS
00246     virtual void        AppendStateInfo(String_t* state) const;
00249     #endif
00250 
00251     //----------------------------------------------------------------------------------------------
00252     private:
00253     //----------------------------------------------------------------------------------------------
00254     void                    RunStateMachine(bool force_all);
00255     void                    RunReadStateMachine(bool force_all);
00256     void                    RunWriteStateMachine(bool force_all);
00257     void                    CheckSeekPastEndOfFile( fileoff_t pos, bool force_all );
00258     BufferedFileBlock_t*    FindBlock( fileoff_t pos, bool will_use );
00259     void                    ReadFromBlock( BufferedFileBlock_t* block, bool force_all );
00260     void                    AssessPreloadNext(  BufferedFileBlock_t* current_block,
00261                                                 int offset_into_block );
00262     void                    LoadNewBlock(   fileoff_t pos,
00263                                             bool force_all,
00264                                             bool preload,
00265                                             BufferedFileBlock_t* avoid );
00266     void                    FillBlockGap(   BufferedFileBlock_t* block,
00267                                             int will_read_from,
00268                                             int will_read_to,
00269                                             int will_overwrite_from,
00270                                             int will_overwrite_to,
00271                                             int already_overwrote_from,
00272                                             int already_overwrote_to,
00273                                             bool force_all );
00274     void                    WriteToBlock( BufferedFileBlock_t* block, bool force_all );
00275     void                    AllocateAndWriteToNewBlock(bool force_all);
00276     BufferedFileBlock_t*    RecycleExistingBuffer(  BufferedFileBlock_t* avoid,
00277                                                     bool force_recycling );
00278     BufferedFileBlock_t*    RecycleImmediatelyAvailableBuffer(BufferedFileBlock_t* avoid);
00279     void                    WriteAllDirtyBlocks( fileoff_t before, bool force_all );
00280     void                    CompleteIO(bool force_all);
00281     void                    UpdateBlockExtents( BufferedFileBlock_t* block,
00282                                                 int offset_into_block, 
00283                                                 int length,
00284                                                 bool wrote_to_block,
00285                                                 bool wrote_from_block );
00286     Status_t                PrepReadLineErrorReturn( bool read_any, int partial_utf8_sequence_len );
00287     error_code_t            ReadLineFromBlock(  BufferedFileBlock_t* block,
00288                                                 String_t* line,
00289                                                 bool only_check_for_lf,
00290                                                 utf8* partial_utf8_sequence,
00291                                                 int* partial_utf8_sequence_len,
00292                                                 int* offset_into_block );
00293     bool                    ReadLineWillWriteTempZero(  BufferedFileBlock_t* block,
00294                                                         int offset_into_block );
00295 
00296     //----------------------------------------------------------------------------------------------
00297     private:
00298     //----------------------------------------------------------------------------------------------
00299     int                                                 m_block_size;
00300     int                                                 m_max_blocks;
00301     bool                                                m_async_io_allowed;
00302     fileoff_t                                           m_pos;
00303     fileoff_t                                           m_size;
00304     Status_t                                            m_status;
00305 
00306     buffered_file_state_t                               m_state;
00307 
00308     byte*                                               m_caller_buf;
00309     int                                                 m_caller_bytes;
00310     bool                                                m_caller_write;
00311     byte*                                               m_work_in_caller_buf;
00312     int                                                 m_work_in_caller_buf_bytes;
00313     bool                                                m_notify_caller_when_state_machine_done;
00314 
00315     BufferedFileBlock_t*                                m_work_block;
00316     int                                                 m_work_block_io_offset;
00317     int                                                 m_work_io_bytes;
00318 
00319     LinkedList_t<BufferedFileBlock_t>                   m_blocks;
00320     int                                                 m_contiguous_read_bytes;
00321 
00322     MessageDestination_t<FileReadCompleteMessage_t>     m_owner_read_dest;
00323     MessageDestination_t<FileWriteCompleteMessage_t>    m_owner_write_dest;
00324 
00325     //----------------------------------------------------------------------------------------------
00326     private:
00327     //----------------------------------------------------------------------------------------------
00328     void ReadCompleteReceived(const FileReadCompleteMessage_t* message);
00329     MessageReceiver_t< BufferedFile_t, FileReadCompleteMessage_t >  m_ReadCompleteReceiver;
00330 
00331     void WriteCompleteReceived(const FileWriteCompleteMessage_t* message);
00332     MessageReceiver_t< BufferedFile_t, FileWriteCompleteMessage_t > m_WriteCompleteReceiver;
00333 
00334     void IOCompleteReceived(    const FileReadCompleteMessage_t* read_msg,
00335                                 const FileWriteCompleteMessage_t* write_msg );
00336 
00337     #if LOG_FILE_OPS
00338     void    DebugBufferedFileDumpState(out String_t* string);
00339     void    DebugBufferedFileDumpStateToString(out String_t* string);
00340     #endif
00341 };
00342 
00343 
00344 // \cond DOXYGEN_DOCUMENT_NEVER
00345 
00346 //==================================================================================================
00347 class BufferedFileBlock_t
00348 //==================================================================================================
00349 : public LinkedListNode_t<BufferedFileBlock_t>
00350 {
00351     public:
00352     fileoff_t       pos;
00353     int             valid_from;
00354     int             valid_to;
00355     int             need_write_from;
00356     int             need_write_to;
00357     inline byte*    Data();
00358 };
00359 
00360 
00361 
00362 
00363 //==================================================================================================
00364 //==================================================================================================
00365 //===
00366 //=== Inline function implementations
00367 //===
00368 //==================================================================================================
00369 //==================================================================================================
00370 inline Status_t
00371 BufferedFile_t::Open(   const utf8* path,
00372                         int flags,
00373                         mode_t permissions,
00374                         MessageDestination_t<FileReadCompleteMessage_t>* read_dest,
00375                         MessageDestination_t<FileWriteCompleteMessage_t>* write_dest,
00376                         MessageDestination_t<FileOpenCompleteMessage_t>* open_dest )
00377 {
00378     // Using the stringliteral form allows the temporary Path_t to borrow the caller's utf8* rather
00379     // than copying it
00380     return Open(    Path_t( reinterpret_cast<stringliteral*>(path) ),
00381                     flags,
00382                     permissions,
00383                     read_dest,
00384                     write_dest,
00385                     open_dest );
00386 }
00387 
00388 
00389 inline Status_t
00390 BufferedFile_t::Open(   stringliteral* path,
00391                         int flags,
00392                         mode_t permissions,
00393                         MessageDestination_t<FileReadCompleteMessage_t>* read_dest,
00394                         MessageDestination_t<FileWriteCompleteMessage_t>* write_dest,
00395                         MessageDestination_t<FileOpenCompleteMessage_t>* open_dest )
00396 {
00397     return Open( Path_t(path), flags, permissions, read_dest, write_dest, open_dest );
00398 }
00399 
00400 
00401 inline byte*
00402 BufferedFileBlock_t::Data()
00403 {
00404     return reinterpret_cast<byte*>(this) + sizeof(BufferedFileBlock_t);
00405 }
00406 
00407 
00408 // \endcond
00409 
00410 #endif // _UT_BUFFERED_FILE_H_

Generated on Tue Dec 14 22:35:05 2010 for UT library by  doxygen 1.6.1