00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef _UT_BUFFERED_FILE_H_
00026 #define _UT_BUFFERED_FILE_H_
00027
00028
00029
00030
00031
00032 #include "UTFile.h"
00033 #include "UTLists.h"
00034
00035
00036
00037
00038
00039
00040
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
00055
00056
00057
00058
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
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
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
00379
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
00409
00410 #endif // _UT_BUFFERED_FILE_H_