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

Generated on Wed Jan 2 06:00:40 2008 for OPeNDAP Back End Server (BES) by  doxygen 1.5.4