![]() |
Disk ARchive
2.5.2
Full featured and portable backup and archiving tool
|
00001 /*********************************************************************/ 00002 // dar - disk archive - a backup/restoration program 00003 // Copyright (C) 2002-2052 Denis Corbin 00004 // 00005 // This program is free software; you can redistribute it and/or 00006 // modify it under the terms of the GNU General Public License 00007 // as published by the Free Software Foundation; either version 2 00008 // of the License, or (at your option) any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with this program; if not, write to the Free Software 00017 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00018 // 00019 // to contact the author : http://dar.linux.free.fr/email.html 00020 /*********************************************************************/ 00021 00025 00026 #ifndef CACHE_HPP 00027 #define CACHE_HPP 00028 00029 #include "../my_config.h" 00030 #include "infinint.hpp" 00031 #include "generic_file.hpp" 00032 00033 namespace libdar 00034 { 00035 00038 00052 class cache : public generic_file 00053 { 00054 public: 00055 cache(generic_file & hidden, //< is the file to cache, it is never deleted by the cache object, 00056 bool shift_mode, //< if true, when all cached data has been read, half of the data is flushed from the cache, the other half is shifted and new data take place to fill the cache. This is necessary for sequential reading, but has some CPU overhead. 00057 U_I size = 102400); //< is the (fixed) size of the cache 00058 cache(const cache & ref) : generic_file(ref.get_mode()) { throw SRC_BUG; }; 00059 const cache & operator = (const cache & ref) { throw SRC_BUG; }; 00060 ~cache(); 00061 void change_to_read_write() { if(get_mode() == gf_read_only) throw SRC_BUG; set_mode(gf_read_write); }; 00062 00063 // inherited from generic_file 00064 00065 bool skippable(skippability direction, const infinint & amount); 00066 bool skip(const infinint & pos); 00067 bool skip_to_eof(); 00068 bool skip_relative(S_I x); 00069 infinint get_position() const { return buffer_offset + next; }; 00070 00071 protected: 00072 // inherited from generic_file 00073 void inherited_read_ahead(const infinint & amount) { ref->read_ahead(amount - available_in_cache(generic_file::skip_forward)); }; 00074 U_I inherited_read(char *a, U_I size); 00075 void inherited_write(const char *a, U_I size); 00076 void inherited_sync_write() { flush_write(); }; 00077 void inherited_flush_read() { flush_write(); clear_buffer(); }; 00078 void inherited_terminate() { flush_write(); }; 00079 00080 private: 00081 generic_file *ref; //< underlying file, (not owned by "this', not to be delete by "this") 00082 char *buffer; //< data in transit 00083 U_I size; //< allocated size 00084 U_I next; //< next to read or next place to write to 00085 U_I last; //< last valid data in the cache. we have: next <= last < size 00086 U_I first_to_write; //< position of the first byte that need to be written. if greater than last, no byte need writing 00087 infinint buffer_offset; //< position of the first byte in buffer 00088 bool shifted_mode; //< whether to half flush and shift or totally flush data 00089 00090 bool need_flush_write() const { return first_to_write < last; }; 00091 void alloc_buffer(size_t x_size); //< allocate x_size byte in buffer field and set size accordingly 00092 void release_buffer(); //< release memory set buffer to nullptr and size to zero 00093 void shift_by_half(); 00094 void clear_buffer(); 00095 void flush_write(); 00096 void fulfill_read(); 00097 U_I available_in_cache(skippability direction) const; 00098 }; 00099 00101 00102 } // end of namespace 00103 00104 #endif 00105