BESUncompressManager.cc

Go to the documentation of this file.
00001 // BESUncompressManager.cc
00002 
00003 // This file is part of bes, A C++ back-end server implementation framework
00004 // for the OPeNDAP Data Access Protocol.
00005 
00006 // Copyright (c) 2004,2005 University Corporation for Atmospheric Research
00007 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 // 
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Lesser General Public License for more details.
00018 // 
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 // You can contact University Corporation for Atmospheric Research at
00024 // 3080 Center Green Drive, Boulder, CO 80301
00025  
00026 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
00027 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
00028 //
00029 // Authors:
00030 //      pwest       Patrick West <pwest@ucar.edu>
00031 //      jgarcia     Jose Garcia <jgarcia@ucar.edu>
00032 
00033 #include <sstream>
00034 
00035 using std::istringstream ;
00036 
00037 #include "BESUncompressManager.h"
00038 #include "BESUncompressGZ.h"
00039 #include "BESUncompressBZ2.h"
00040 #include "BESCache.h"
00041 #include "BESContainerStorageException.h"
00042 #include "BESDebug.h"
00043 #include "TheBESKeys.h"
00044 #include "config.h"
00045 
00046 BESUncompressManager *BESUncompressManager::_instance = 0 ;
00047 
00051 BESUncompressManager::BESUncompressManager()
00052 {
00053     add_method( "gz", BESUncompressGZ::uncompress ) ;
00054 #ifdef HAVE_BZLIB_H
00055     add_method( "bz2", BESUncompressBZ2::uncompress ) ;
00056 #endif
00057 
00058     bool found = false ;
00059     string key = "BES.Uncompress.Retry" ;
00060     string val = TheBESKeys::TheKeys()->get_key( key, found ) ;
00061     if( !found || val.empty() )
00062     {
00063         _retry = 2 ;
00064     }
00065     else
00066     {
00067         istringstream is( val ) ;
00068         is >> _retry ;
00069     }
00070 
00071     key = "BES.Uncompress.NumTries" ;
00072     val = TheBESKeys::TheKeys()->get_key( key, found ) ;
00073     if( !found || val.empty() )
00074     {
00075         _num_tries = 10 ;
00076     }
00077     else
00078     {
00079         istringstream is( val ) ;
00080         is >> _num_tries ;
00081     }
00082 }
00083 
00093 bool
00094 BESUncompressManager::add_method( const string &name,
00095                                   p_bes_uncompress method )
00096 {
00097     BESUncompressManager::UCIter i ;
00098     i = _uncompress_list.find( name ) ;
00099     if( i == _uncompress_list.end() )
00100     {
00101         _uncompress_list[name] = method ;
00102         return true ;
00103     }
00104     return false ;
00105 }
00106 
00115 bool
00116 BESUncompressManager::remove_method( const string &name )
00117 {
00118     BESUncompressManager::UIter i ;
00119     i = _uncompress_list.find( name ) ;
00120     if( i != _uncompress_list.end() )
00121     {
00122         _uncompress_list.erase( i ) ;
00123         return true ;
00124     }
00125     return false ;
00126 }
00127 
00136 p_bes_uncompress
00137 BESUncompressManager::find_method( const string &name )
00138 {
00139     BESUncompressManager::UCIter i ;
00140     i = _uncompress_list.find( name ) ;
00141     if( i != _uncompress_list.end() )
00142     {
00143         return (*i).second ;
00144     }
00145     return 0 ;
00146 }
00147 
00153 string
00154 BESUncompressManager::get_method_names()
00155 {
00156     string ret ;
00157     bool first_name = true ;
00158     BESUncompressManager::UCIter i = _uncompress_list.begin() ;
00159     for( ; i != _uncompress_list.end(); i++ )
00160     {
00161         if( !first_name )
00162             ret += ", " ;
00163         ret += (*i).first ;
00164         first_name = false ;
00165     }
00166     return ret ;
00167 }
00168 
00176 string
00177 BESUncompressManager::uncompress( const string &src, BESCache &cache )
00178 {
00179     BESDEBUG( "BESUncompressManager::uncompress - src = " << src << endl )
00180     string::size_type dot = src.rfind( "." ) ;
00181     if( dot != string::npos )
00182     {
00183         string ext = src.substr( dot+1, src.length() - dot ) ;
00184         // Why fold the extension to lowercase? jhrg 5/9/07
00185         for( int i = 0; i < ext.length(); i++ )
00186         {
00187             ext[i] = tolower( ext[i] ) ;
00188         }
00189 
00190         // if we find the method for this file then use it. If we don't find
00191         // it then assume that the file is not compressed and simply return
00192         // the src file at the end of the method.
00193         p_bes_uncompress p = find_method( ext ) ;
00194         if( p )
00195         {
00196             // the file is compressed so we either need to uncompress it or
00197             // we need to tell if it is already cached. To do this, lock the
00198             // cache so no one else can do anything
00199             if( cache.lock( _retry, _num_tries ) )
00200             {
00201                 try
00202                 {
00203                     // before calling uncompress on the file, see if the file
00204                     // has already been cached. If it has, then simply return
00205                     // the target, no need to cache.
00206                     BESDEBUG( "BESUncompressManager::uncompress - is cached? " \
00207                               << src << endl )
00208                     string target ;
00209                     if( cache.is_cached( src, target ) )
00210                     {
00211                         BESDEBUG( "BESUncompressManager::uncompress - " \
00212                                   << "is cached " << target << endl )
00213                         cache.unlock() ;
00214                         return target ;
00215                     }
00216 
00217                     // the file is not cached, so we need to uncompress the
00218                     // file.  First determine if there is enough space in
00219                     // the cache to uncompress the file
00220                     BESDEBUG( "BESUncompressManager::uncompress - " \
00221                               << "purging cache" << endl )
00222                     cache.purge() ;
00223 
00224                     // Now that we have some room ... uncompress the file
00225                     BESDEBUG( "BESUncompressManager::uncompress - " \
00226                               << "uncompress to " << target \
00227                               << " using " << ext << " uncompression" \
00228                               << endl )
00229 
00230                     // we are now done in the cahce, unlock it
00231                     cache.unlock() ;
00232 
00233                     // How about having the p_bes_uncompress() return bool
00234                     // since we already know the name of the target? Or
00235                     // return void since it throws on error? jhrg 5/9/07
00236                     return p( src, target ) ;
00237                 }
00238                 catch( BESException &e )
00239                 {
00240                     // a problem in the cache, unlock it and re-throw the
00241                     // exception
00242                     cache.unlock() ;
00243                     throw e ;
00244                 }
00245                 catch( ... )
00246                 {
00247                     // an unknown problem in the cache, unlock it and throw a
00248                     // BES exception
00249                     cache.unlock() ;
00250                     string err = (string)"Problem working with the cache, "
00251                                  + "unknow error" ;
00252                     throw BESContainerStorageException( err, __FILE__,__LINE__);
00253                 }
00254             }
00255             else
00256             {
00257                 string err = "Unable to lock the cache " 
00258                              + cache.cache_dir() ;
00259                 throw BESContainerStorageException( err, __FILE__, __LINE__ ) ;
00260             }
00261         }
00262         else
00263         {
00264             BESDEBUG( "BESUncompressManager::uncompress - not compressed " \
00265                       << endl )
00266         }
00267     }
00268     else
00269     {
00270         string err = "Unable to determine type of file from "
00271                      + src ;
00272         throw BESContainerStorageException( err, __FILE__, __LINE__ ) ;
00273     }
00274 
00275     return src ;
00276 }
00277 
00285 void
00286 BESUncompressManager::dump( ostream &strm ) const
00287 {
00288     strm << BESIndent::LMarg << "BESUncompressManager::dump - ("
00289                              << (void *)this << ")" << endl ;
00290     BESIndent::Indent() ;
00291     if( _uncompress_list.size() )
00292     {
00293         strm << BESIndent::LMarg << "registered uncompression methods:" << endl;
00294         BESIndent::Indent() ;
00295         BESUncompressManager::UCIter i = _uncompress_list.begin() ;
00296         BESUncompressManager::UCIter ie = _uncompress_list.end() ;
00297         for( ; i != ie; i++ )
00298         {
00299             strm << BESIndent::LMarg << (*i).first << endl ;
00300         }
00301         BESIndent::UnIndent() ;
00302     }
00303     else
00304     {
00305         strm << BESIndent::LMarg << "registered uncompress methods: none" << endl ;
00306     }
00307     BESIndent::UnIndent() ;
00308 }
00309 
00310 BESUncompressManager *
00311 BESUncompressManager::TheManager()
00312 {
00313     if( _instance == 0 )
00314     {
00315         _instance = new BESUncompressManager ;
00316     }
00317     return _instance ;
00318 }

Generated on Wed Aug 29 03:20:59 2007 for OPeNDAP Back End Server (BES) by  doxygen 1.5.2