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-2009 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 "BESUncompressZ.h"
00041 #include "BESCache.h"
00042 #include "BESInternalError.h"
00043 #include "BESDebug.h"
00044 #include "TheBESKeys.h"
00045 
00046 BESUncompressManager *BESUncompressManager::_instance = 0 ;
00047 
00057 BESUncompressManager::BESUncompressManager()
00058 {
00059     add_method( "gz", BESUncompressGZ::uncompress ) ;
00060     add_method( "bz2", BESUncompressBZ2::uncompress ) ;
00061     add_method( "z", BESUncompressZ::uncompress ) ;
00062 
00063     bool found = false ;
00064     string key = "BES.Uncompress.Retry" ;
00065     string val = TheBESKeys::TheKeys()->get_key( key, found ) ;
00066     if( !found || val.empty() )
00067     {
00068         _retry = 2000 ;
00069     }
00070     else
00071     {
00072         istringstream is( val ) ;
00073         is >> _retry ;
00074     }
00075 
00076     key = "BES.Uncompress.NumTries" ;
00077     val = TheBESKeys::TheKeys()->get_key( key, found ) ;
00078     if( !found || val.empty() )
00079     {
00080         _num_tries = 10 ;
00081     }
00082     else
00083     {
00084         istringstream is( val ) ;
00085         is >> _num_tries ;
00086     }
00087 }
00088 
00098 bool
00099 BESUncompressManager::add_method( const string &name,
00100                                   p_bes_uncompress method )
00101 {
00102     BESUncompressManager::UCIter i ;
00103     i = _uncompress_list.find( name ) ;
00104     if( i == _uncompress_list.end() )
00105     {
00106         _uncompress_list[name] = method ;
00107         return true ;
00108     }
00109     return false ;
00110 }
00111 
00120 bool
00121 BESUncompressManager::remove_method( const string &name )
00122 {
00123     BESUncompressManager::UIter i ;
00124     i = _uncompress_list.find( name ) ;
00125     if( i != _uncompress_list.end() )
00126     {
00127         _uncompress_list.erase( i ) ;
00128         return true ;
00129     }
00130     return false ;
00131 }
00132 
00141 p_bes_uncompress
00142 BESUncompressManager::find_method( const string &name )
00143 {
00144     BESUncompressManager::UCIter i ;
00145     i = _uncompress_list.find( name ) ;
00146     if( i != _uncompress_list.end() )
00147     {
00148         return (*i).second ;
00149     }
00150     return 0 ;
00151 }
00152 
00158 string
00159 BESUncompressManager::get_method_names()
00160 {
00161     string ret ;
00162     bool first_name = true ;
00163     BESUncompressManager::UCIter i = _uncompress_list.begin() ;
00164     for( ; i != _uncompress_list.end(); i++ )
00165     {
00166         if( !first_name )
00167             ret += ", " ;
00168         ret += (*i).first ;
00169         first_name = false ;
00170     }
00171     return ret ;
00172 }
00173 
00203 bool
00204 BESUncompressManager::uncompress( const string &src, string &target,
00205                                   BESCache &cache )
00206 {
00207     BESDEBUG( "bes", "BESUncompressManager::uncompress - src = " << src << endl )
00208     string::size_type dot = src.rfind( "." ) ;
00209     if( dot != string::npos )
00210     {
00211         string ext = src.substr( dot+1, src.length() - dot ) ;
00212         // Why fold the extension to lowercase? jhrg 5/9/07
00213         // The extension (Z, gz, bz2, GZ, BZ2, z) is used to determine which
00214         // uncompression engine to use. It is compared to the list, which is
00215         // all lower case. pcw 2/22/08
00216         for( int i = 0; i < ext.length(); i++ )
00217         {
00218             ext[i] = tolower( ext[i] ) ;
00219         }
00220 
00221         // if we find the method for this file then use it. If we don't find
00222         // it then assume that the file is not compressed and simply return
00223         // the src file at the end of the method.
00224         p_bes_uncompress p = find_method( ext ) ;
00225         if( p )
00226         {
00227             // the file is compressed so we either need to uncompress it or
00228             // we need to tell if it is already cached. To do this, lock the
00229             // cache so no one else can do anything
00230             if( cache.lock( _retry, _num_tries ) )
00231             {
00232                 try
00233                 {
00234                     // before calling uncompress on the file, see if the file
00235                     // has already been cached. If it has, then simply return
00236                     // the target, no need to cache.
00237                     BESDEBUG( "bes", "BESUncompressManager::uncompress - is cached? " << src << endl )
00238                     if( cache.is_cached( src, target ) )
00239                     {
00240                         BESDEBUG( "bes", "BESUncompressManager::uncompress - "  << "is cached " << target << endl )
00241                         cache.unlock() ;
00242                         return true ;
00243                     }
00244 
00245                     // the file is not cached, so we need to uncompress the
00246                     // file.  First determine if there is enough space in
00247                     // the cache to uncompress the file
00248                     BESDEBUG( "bes", "BESUncompressManager::uncompress - " << "purging cache" << endl )
00249                     cache.purge() ;
00250 
00251                     // Now that we have some room ... uncompress the file
00252                     BESDEBUG( "bes", "BESUncompressManager::uncompress - " << "uncompress to " << target \
00253                               << " using " << ext << " uncompression" \
00254                               << endl )
00255 
00256                     // we are now done in the cahce, unlock it
00257                     cache.unlock() ;
00258 
00259                     p( src, target ) ;
00260                     return true ;
00261                 }
00262                 catch( BESError & )
00263                 {
00264                     // a problem in the cache, unlock it and re-throw the
00265                     // exception
00266                     cache.unlock() ;
00267                     throw ;
00268                 }
00269                 catch( ... )
00270                 {
00271                     // an unknown problem in the cache, unlock it and throw a
00272                     // BES exception
00273                     cache.unlock() ;
00274                     string err = (string)"Problem working with the cache, "
00275                                  + "unknow error" ;
00276                     throw BESInternalError( err, __FILE__,__LINE__);
00277                 }
00278             }
00279             else
00280             {
00281                 string err = "Unable to lock the cache " 
00282                              + cache.cache_dir() ;
00283                 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00284             }
00285         }
00286         else
00287         {
00288             BESDEBUG( "bes", "BESUncompressManager::uncompress - not compressed " << endl )
00289         }
00290     }
00291     else
00292     {
00293         BESDEBUG( "bes", "BESUncompressmanager::uncompress - not file extension" << endl )
00294 #if 0
00295         // This could just mean that there is a README file here, so just
00296         // return the src file name and let the system run its course.
00297         string err = "Unable to determine type of file from "
00298                      + src ;
00299         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00300 #endif
00301     }
00302 
00303     return false ;
00304 }
00305 
00313 void
00314 BESUncompressManager::dump( ostream &strm ) const
00315 {
00316     strm << BESIndent::LMarg << "BESUncompressManager::dump - ("
00317                              << (void *)this << ")" << endl ;
00318     BESIndent::Indent() ;
00319     if( _uncompress_list.size() )
00320     {
00321         strm << BESIndent::LMarg << "registered uncompression methods:" << endl;
00322         BESIndent::Indent() ;
00323         BESUncompressManager::UCIter i = _uncompress_list.begin() ;
00324         BESUncompressManager::UCIter ie = _uncompress_list.end() ;
00325         for( ; i != ie; i++ )
00326         {
00327             strm << BESIndent::LMarg << (*i).first << endl ;
00328         }
00329         BESIndent::UnIndent() ;
00330     }
00331     else
00332     {
00333         strm << BESIndent::LMarg << "registered uncompress methods: none" << endl ;
00334     }
00335     BESIndent::UnIndent() ;
00336 }
00337 
00338 BESUncompressManager *
00339 BESUncompressManager::TheManager()
00340 {
00341     if( _instance == 0 )
00342     {
00343         _instance = new BESUncompressManager ;
00344     }
00345     return _instance ;
00346 }

Generated on 18 Feb 2010 for OPeNDAP Hyrax Back End Server (BES) by  doxygen 1.6.1