sample/file_archive_2/main.cpp

00001 /*
00002 
00003 Copyright (c) 2002-2005, Yauheni Akhotnikau
00004 All rights reserved.
00005 
00006 Redistribution and use in source and binary forms, with or without
00007 modification, are permitted provided that the following conditions are met:
00008 
00009 - Redistributions of source code must retain the above copyright notice, this
00010 list of conditions and the following disclaimer.
00011 
00012 - Redistributions in binary form must reproduce the above copyright notice, this
00013 list of conditions and the following disclaimer in the documentation and/or
00014 other materials provided with the distribution.
00015 
00016 - The name of the author may not be used to endorse or promote products derived
00017 from this software without specific prior written permission.
00018 
00019 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00020 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00021 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
00022 EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00023 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00024 OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00027 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00028 OF SUCH DAMAGE.
00029 
00030 */
00031 
00032 /*
00033   Пример использования БД в качестве архива файлов.
00034 */
00035 
00036 #include <iostream>
00037 #include <fstream>
00038 #include <cerrno>
00039 #include <cstring>
00040 #include <cstdlib>
00041 
00042 #include <time.h>
00043 
00044 #include <map>
00045 #include <string>
00046 
00047 #include <auto_ptr_3/h/obj_ptr.hpp>
00048 
00049 #include <oess_1/defs/h/ex.hpp>
00050 
00051 #include <oess_1/stdsn/h/inout_templ.hpp>
00052 
00053 #include <oess_1/db/cln/h/local_db.hpp>
00054 #include <oess_1/db/cln/h/slice_image.hpp>
00055 #include <oess_1/db/cln/h/slice_index.hpp>
00056 
00057 using namespace std;
00058 
00059 //
00060 // dir_item_t
00061 //
00062 
00063 // Элемент каталога файла в хранилище.
00064 class dir_item_t :
00065   public oess_1::stdsn::serializable_t
00066 {
00067   OESS_SERIALIZER( dir_item_t )
00068 private :
00069   // Имя файла.
00070   std::string m_file_name;
00071   // Размер файла.
00072   unsigned int  m_file_size;
00073   // Идентификатор файла в хранилище.
00074   oess_1::ent_id_t  m_id;
00075 
00076 public :
00077   dir_item_t()
00078   :
00079     m_file_size( 0 )
00080   {}
00081   dir_item_t(
00082     const std::string & file_name,
00083     unsigned int file_size,
00084     const oess_1::ent_id_t & id )
00085   :
00086     m_file_name( file_name )
00087   , m_file_size( file_size )
00088   , m_id( id )
00089   {}
00090   dir_item_t(
00091     const dir_item_t & o )
00092   {
00093     (*this) = o;
00094   }
00095   virtual ~dir_item_t()
00096   {}
00097 
00098   const dir_item_t &
00099   operator=( const dir_item_t & o )
00100   {
00101     if( &o == this )
00102     {
00103       m_file_name = o.m_file_name;
00104       m_file_size = o.m_file_size;
00105       m_id = o.m_id;
00106     }
00107     return *this;
00108   }
00109 
00110   const std::string &
00111   file_name() const
00112   {
00113     return m_file_name;
00114   }
00115 
00116   // Получение имени файла как ключа.
00117   static const std::string &
00118   file_name_key( const dir_item_t & o )
00119   {
00120     return o.file_name();
00121   }
00122 
00123   unsigned int
00124   file_size() const
00125   {
00126     return m_file_size;
00127   }
00128 
00129   // Получение размера файла как ключа.
00130   static unsigned int
00131   file_size_key( const dir_item_t & o )
00132   {
00133     return o.file_size();
00134   }
00135 
00136   const oess_1::ent_id_t &
00137   id() const
00138   {
00139     return m_id;
00140   }
00141 };
00142 
00143 //
00144 // file_content_t
00145 //
00146 
00147 // Содержимое файла.
00148 class file_content_t :
00149   public  oess_1::stdsn::serializable_t
00150 {
00151   OESS_SERIALIZER( file_content_t )
00152   public :
00153     file_content_t();
00154     virtual ~file_content_t();
00155 
00156     std::string &
00157     content();
00158 
00159     const std::string &
00160     content() const;
00161 
00162     unsigned int
00163     size() const;
00164 
00165   private :
00166     std::string m_content;
00167 };
00168 
00169 file_content_t::file_content_t()
00170 {
00171 }
00172 
00173 file_content_t::~file_content_t()
00174 {
00175 }
00176 
00177 std::string &
00178 file_content_t::content()
00179 {
00180   return m_content;
00181 }
00182 
00183 const std::string &
00184 file_content_t::content() const
00185 {
00186   return m_content;
00187 }
00188 
00189 unsigned int
00190 file_content_t::size() const
00191 {
00192   return m_content.size();
00193 }
00194 
00195 //
00196 // dir_t
00197 //
00198 class dir_t
00199 {
00200 private :
00201   // Тип индекса по оглавлению через имя файла.
00202   typedef oess_1::db::cln::slice_index_t<
00203       dir_item_t,
00204       std::string,
00205       const std::string & (*)( const dir_item_t & ) >
00206     dir_item_name_index_t;
00207 
00208   // Тип индекса по оглавлению через размер файла.
00209   typedef oess_1::db::cln::slice_index_t<
00210       dir_item_t,
00211       unsigned int,
00212       unsigned int (*)( const dir_item_t & ) >
00213     dir_item_size_index_t;
00214 
00215   // Тип образа раздела с оглавлением.
00216   typedef oess_1::db::cln::slice_image_t<
00217       dir_item_t >
00218     dir_item_image_t;
00219 
00220   // Образ раздела с оглавлением.
00221   dir_item_image_t  m_image;
00222   // Индекс по именам файлов.
00223   dir_item_name_index_t m_name_index;
00224   // Индекс по размерам файлов.
00225   dir_item_size_index_t m_size_index;
00226 
00227 public :
00228   dir_t(
00229     oess_1::db::cln::db_t & db );
00230   virtual ~dir_t();
00231 
00232   // Найти файл в архиве.
00233   // Возвращает эквивалент NULL, если файл не найден.
00234   oess_1::ent_id_t
00235   find(
00236     const std::string & file_name ) const;
00237 
00238   // Поместить описание файла в архив.
00239   void
00240   insert(
00241     const std::string & file_name,
00242     unsigned int size,
00243     const oess_1::ent_id_t & id );
00244 
00245   void
00246   list(
00247     std::ostream & s ) const;
00248 
00249   void
00250   erase(
00251     const std::string & file_name );
00252 };
00253 
00254 dir_t::dir_t(
00255   oess_1::db::cln::db_t & db )
00256 :
00257   m_image( db, "dir" )
00258 , m_name_index( m_image, &dir_item_t::file_name_key )
00259 , m_size_index( m_image, &dir_item_t::file_size_key )
00260 {
00261   // В базе должен быть этот раздел.
00262   db.slice_create( "dir" );
00263 
00264   m_image.reload();
00265 }
00266 
00267 dir_t::~dir_t()
00268 {
00269 }
00270 
00271 oess_1::ent_id_t
00272 dir_t::find(
00273   const std::string & file_name ) const
00274 {
00275   dir_item_name_index_t::const_iterator it(
00276     m_name_index.find( file_name ) );
00277   if( it != m_name_index.end() )
00278   {
00279     return it->id();
00280   }
00281 
00282   return oess_1::ent_id_t();
00283 }
00284 
00285 void
00286 dir_t::insert(
00287   const std::string & file_name,
00288   unsigned int size,
00289   const oess_1::ent_id_t & id )
00290 {
00291   m_image.insert( dir_item_t( file_name, size, id ) );
00292 }
00293 
00294 void
00295 dir_t::list(
00296   std::ostream & s ) const
00297 {
00298   for( dir_item_name_index_t::const_iterator
00299     it = m_name_index.begin(), it_end = m_name_index.end();
00300     it != it_end; ++it )
00301   {
00302     s << it->file_name() << ", "
00303       << it->file_size() << ", "
00304       << it->id() << std::endl;
00305   }
00306 }
00307 
00308 void
00309 dir_t::erase(
00310   const std::string & file_name )
00311 {
00312   m_name_index.erase( file_name );
00313 }
00314 
00315 #include "main.ddl.cpp"
00316 
00317 //
00318 // app_t
00319 //
00320 class app_t {
00321   public :
00322     app_t( oess_1::db::cln::db_t & db );
00323     ~app_t();
00324 
00325     void
00326     attach();
00327 
00328     void
00329     pack(
00330       char ** files,
00331       int file_count );
00332 
00333     void
00334     list() const;
00335 
00336     void
00337     erase(
00338       char ** files,
00339       int file_count );
00340 
00341   private :
00342     oess_1::db::cln::db_t & m_db;
00343 
00344     auto_ptr_3::obj_ptr_t< dir_t >  m_dir;
00345 
00346     void
00347     load_dir();
00348 
00349     void
00350     pack_file(
00351       const std::string & file_name );
00352 
00353     bool
00354     load_file_from_filesys(
00355       const std::string & file_name,
00356       file_content_t & ent );
00357 
00358     void
00359     erase_file(
00360       const std::string & file_name );
00361 
00362 };
00363 
00364 app_t::app_t(
00365   oess_1::db::cln::db_t & db )
00366 :
00367   m_db( db )
00368 {
00369 }
00370 
00371 app_t::~app_t()
00372 {
00373 }
00374 
00375 void
00376 app_t::attach()
00377 {
00378   // В базе должен быть этот раздел.
00379   m_db.slice_create( "archive" );
00380 
00381   load_dir();
00382 }
00383 
00384 void
00385 app_t::pack(
00386   char ** files,
00387   int file_count )
00388 {
00389   // Выполняем операцию в транзакции.
00390   oess_1::db::cln::transaction_t trx( m_db );
00391 
00392   for( int i = 0; i != file_count; ++i )
00393   {
00394     pack_file( files[ i ] );
00395   }
00396 
00397   trx.commit();
00398 }
00399 
00400 void
00401 app_t::list() const
00402 {
00403   m_dir->list( std::cout );
00404 }
00405 
00406 void
00407 app_t::erase(
00408   char ** files,
00409   int file_count )
00410 {
00411   // Выполняем операцию в транзакции.
00412   oess_1::db::cln::transaction_t trx( m_db );
00413 
00414   for( int i = 0; i != file_count; ++i )
00415   {
00416     erase_file( files[ i ] );
00417   }
00418 
00419   trx.commit();
00420 }
00421 
00422 void
00423 app_t::load_dir()
00424 {
00425   m_dir.reset( new dir_t( m_db ) );
00426 }
00427 
00428 void
00429 app_t::pack_file(
00430   const std::string & file_name )
00431 {
00432   std::cout << "packing: " << file_name;
00433   file_content_t ent;
00434   if( load_file_from_filesys( file_name, ent ) )
00435   {
00436     oess_1::ent_id_t id( m_dir->find( file_name ) );
00437     if( !id )
00438     {
00439       id = m_db.ent_create( "archive", ent );
00440       m_dir->insert( file_name, ent.size(), id );
00441 
00442       std::cout << " new entity created: " << id << std::endl;
00443     }
00444     else
00445     {
00446       m_db.ent_update( id, ent );
00447       std::cout << " existed entity updated: " << id << std::endl;
00448     }
00449   }
00450 }
00451 
00452 void
00453 app_t::erase_file(
00454   const std::string & file_name )
00455 {
00456   std::cout << "erasing from archive: " << file_name;
00457   oess_1::ent_id_t id( m_dir->find( file_name ) );
00458   if( !id )
00459   {
00460     std::cout << " not found in archive" << std::endl;
00461   }
00462   else
00463   {
00464     m_db.ent_destroy( id );
00465 
00466     m_dir->erase( file_name );
00467     std::cout << std::endl;
00468   }
00469 }
00470 
00471 bool
00472 app_t::load_file_from_filesys(
00473   const std::string & file_name,
00474   file_content_t & ent )
00475 {
00476   std::ifstream f( file_name.c_str(), std::ios::in | std::ios::binary );
00477   if( f )
00478   {
00479     char buf[ 256 ];
00480     while( f )
00481     {
00482       f.read( buf, sizeof( buf ) );
00483       size_t s = f.gcount();
00484       if( s )
00485         ent.content().append( buf, s );
00486     }
00487 
00488     return true;
00489   }
00490   else
00491   {
00492     std::cerr << file_name << ": " << errno
00493       << ", " << strerror( errno ) << std::endl;
00494   }
00495 
00496   return false;
00497 }
00498 
00499 int
00500 main(
00501   int argc,
00502   char ** argv )
00503 {
00504   if( 1 == argc ) {
00505     std::cout << "sample_file_archive_2 <cmd> [file [file [...]]]\n\n"
00506       "cmd:\n"
00507       "\tpack\n"
00508       "\tlist\n"
00509       "\terase\n"
00510       << std::endl;
00511     return 0;
00512   }
00513 
00514   try {
00515     const std::string physic_name( "./sample/file_archive_2/db" );
00516 
00517     oess_1::db::cln::local_db_t db( physic_name );
00518 
00519     app_t app( *db.query_db() );
00520     app.attach();
00521 
00522 //FIX ME: реализовать:
00523 //  - команды: find, unpack;
00524 //  - чтение resp-файлов.
00525 
00526     if( 0 == strcmp( "pack", argv[ 1 ] ) )
00527       app.pack( &argv[ 2 ], argc - 2 );
00528     else if( 0 == strcmp( "list", argv[ 1 ] ) )
00529       app.list();
00530     else if( 0 == strcmp( "erase", argv[ 1 ] ) )
00531       app.erase( &argv[ 2 ], argc - 2 );
00532 
00533     return 0;
00534   }
00535   catch( oess_1::ex_t & x ) {
00536     std::cerr << "*** " << x.query_err_code() << " ***"
00537       << std::endl;
00538   }
00539   catch( ... ) {
00540     std::cerr << "Oops! Unknown exception!" << std::endl;
00541   }
00542 
00543   return 1;
00544 }

Документация по ObjESSty. Последние изменения: Fri Oct 13 18:35:35 2006. Создано системой  doxygen 1.4.7
Hosted by uCoz