openModeller
Version 1.4.0
|
00001 00027 #include <openmodeller/env_io/WcsProxyRaster.hh> 00028 #include <openmodeller/Log.hh> 00029 #include <openmodeller/Exceptions.hh> 00030 #include <openmodeller/MapFormat.hh> 00031 #include <openmodeller/CacheManager.hh> 00032 #include <openmodeller/Settings.hh> 00033 #include <openmodeller/env_io/RemoteRaster.hh> 00034 00035 #include <gdal.h> 00036 00037 #include <string.h> 00038 #include <sstream> 00039 00040 using namespace std; 00041 00042 #ifdef MPI_FOUND 00043 #include "mpi.h" 00044 #endif 00045 00046 /****************************************************************/ 00047 /*********************** WCS Proxy Raster ***********************/ 00048 00049 /******************/ 00050 /*** Destructor ***/ 00051 WcsProxyRaster::~WcsProxyRaster() 00052 { 00053 } 00054 00055 /******************************/ 00056 /*** create Raster Callback ***/ 00057 Raster* 00058 WcsProxyRaster::CreateRasterCallback() 00059 { 00060 return new WcsProxyRaster(); 00061 } 00062 00063 /*********************/ 00064 /*** create Raster ***/ 00065 void 00066 WcsProxyRaster::createRaster( const string& str, int categ ) 00067 { 00068 string cache_id = CacheManager::getContentIdMd5( str ); 00069 00071 00072 if ( CacheManager::isCachedMd5( str, OM_WCS_PROXY_SUBDIR ) ) { 00073 00074 Log::instance()->debug( "WCS proxy raster %s already present in local cache (%s)\n", str.c_str(), cache_id.c_str() ); 00075 00076 string cached_ref = CacheManager::getContentLocationMd5( str, OM_WCS_PROXY_SUBDIR ); 00077 00078 GdalRaster::createRaster( cached_ref, categ ); 00079 } 00080 else { 00081 00082 Log::instance()->debug( "Setting up WCS proxy for %s (%s)\n", str.c_str(), cache_id.c_str() ); 00083 00084 // Extract tokens from identifier 00085 vector<string> tokens; 00086 stringstream ss(str); 00087 string token; 00088 while ( getline(ss, token, '>') ) { 00089 00090 tokens.push_back(token); 00091 } 00092 00093 if ( tokens.size() != 3 ) { 00094 00095 std::string msg = "Invalid WCS identifier. Make sure it has 3 parts separated by \">\".\n"; 00096 Log::instance()->error( msg.c_str() ); 00097 throw RasterException( msg.c_str() ); 00098 } 00099 00100 if ( RemoteRaster::isFromRejectedSource( tokens[1] ) ) { 00101 00102 std::string msg = "Untrusted source for WCS raster. Aborting operation.\n"; 00103 Log::instance()->error( msg.c_str() ); 00104 throw RasterException( msg.c_str() ); 00105 } 00106 00107 // Create GDAL WCS XML file 00108 ostringstream oss (ostringstream::out); 00109 oss<<"<WCS_GDAL>"<<std::endl; 00110 oss<<"<ServiceURL>"<<tokens[1]<<"</ServiceURL>"<<std::endl; 00111 oss<<"<CoverageName>"<<tokens[2]<<"</CoverageName>"<<std::endl; 00112 oss<<"</WCS_GDAL>"; 00113 00114 // Then cache it 00115 CacheManager::cacheMd5( str, oss, OM_WCS_PROXY_SUBDIR ); 00116 } 00117 00118 string cached_ref = CacheManager::getContentLocationMd5( str, OM_WCS_PROXY_SUBDIR ); 00119 00121 if ( Settings::count( "FETCH_WCS" ) == 1 && Settings::get( "FETCH_WCS" ) == "true" ) { 00122 00123 Log::instance()->debug( "openModeller configured to work with local copies of WCS rasters\n" ); 00124 00125 std::string clone_id( cache_id ); 00126 clone_id.append(".img"); 00127 00128 std::string clone_ref( cached_ref ); 00129 clone_ref.append(".img"); 00130 00131 // Check if file is being downloaded (presence of lock file) 00132 std::string lock_file = cache_id; 00133 lock_file.append(".lock"); 00134 00135 if ( CacheManager::isCached( lock_file, OM_WCS_PROXY_SUBDIR ) ) { 00136 00137 Log::instance()->debug( "Ongoing concurrent download\n" ); 00138 throw RasterException( "Ongoing concurrent download", 1 ); 00139 } 00140 00141 if ( CacheManager::isCached( clone_id, OM_WCS_PROXY_SUBDIR ) ) { 00142 00143 Log::instance()->debug( "Local WCS copy already present: %s\n", clone_ref.c_str() ); 00144 00145 GdalRaster::createRaster( cached_ref, categ ); 00146 } 00147 else { 00148 00149 Log::instance()->debug( "Local WCS copy does not exist\n" ); 00150 00151 std::string retries_file = cache_id; 00152 retries_file.append(".tries"); 00153 00154 std::string retries_fullpath = CacheManager::getContentLocation( retries_file, OM_WCS_PROXY_SUBDIR ); 00155 int num_retries = 0; 00156 00157 // Check number of previous attempts 00158 if ( CacheManager::isCached( retries_file, OM_WCS_PROXY_SUBDIR ) ) { 00159 00160 fstream fin; 00161 fin.open( retries_fullpath.c_str(), ios::in ); 00162 00163 if ( fin.is_open() ) { 00164 00165 ostringstream oss; 00166 string line; 00167 00168 getline( fin, line ); 00169 oss << line << endl; 00170 00171 // Note: if the content is empty, atoi returns 0 00172 num_retries = atoi( oss.str().c_str() ); 00173 00174 fin.close(); 00175 } 00176 else { 00177 00178 throw RasterException( "Could not determine number of previous download retries." ); 00179 } 00180 00181 if ( num_retries > 3 ) { 00182 00183 // Without removing the file, it will need to be manually removed before trying again! 00184 CacheManager::eraseCache( retries_file, OM_WCS_PROXY_SUBDIR ); 00185 throw RasterException( "Too many attempts to fetch raster. Aborting." ); 00186 } 00187 } 00188 00189 // Fetch file 00190 try { 00191 00192 // Last minute double check 00193 if ( CacheManager::isCached( lock_file, OM_WCS_PROXY_SUBDIR ) ) { 00194 00195 throw RasterException( "Ongoing concurrent download", 1 ); 00196 } 00197 00198 // Create lock file 00199 ostringstream oss (ostringstream::out); 00200 CacheManager::cache( lock_file, oss, OM_WCS_PROXY_SUBDIR ); 00201 00202 // Increase number of retries 00203 FILE *p_file = NULL; 00204 p_file = fopen( retries_fullpath.c_str(), "w" ); 00205 00206 if ( p_file == NULL ) { 00207 00208 // Could not open file 00209 throw RasterException( "Could not store number of download retries." ); 00210 } 00211 else { 00212 00213 ++num_retries; 00214 char buffer[2]; 00215 sprintf( buffer, "%d", num_retries ); 00216 fputs( buffer, p_file ); 00217 fclose( p_file ); 00218 } 00219 00220 // Finally fetch raster 00221 Log::instance()->debug( "Fetching WCS raster...\n" ); 00222 00223 GDALAllRegister(); 00224 00225 // Open source raster 00226 GDALDatasetH hDataset = GDALOpen( cached_ref.c_str(), GA_ReadOnly ); 00227 if ( hDataset == NULL ) { 00228 00229 std::string msg = "Failed to open WCS raster!\n"; 00230 Log::instance()->error( msg.c_str() ); 00231 throw RasterException( msg.c_str() ); 00232 } 00233 00234 GDALDriverH hDriver = GDALGetDriverByName( "HFA" ); // Use Erdas Imagine 00235 if ( hDriver == NULL ) { 00236 00237 GDALClose( hDataset ); 00238 GDALDestroyDriverManager(); 00239 00240 std::string msg = "Could not find GDAL HFA driver!\n"; 00241 Log::instance()->error( msg.c_str() ); 00242 throw RasterException( msg.c_str() ); 00243 } 00244 00245 // Copy WCS proxy to HFA 00246 GDALDatasetH hOutDS = GDALCreateCopy( hDriver, clone_ref.c_str(), hDataset, FALSE, NULL, NULL, NULL ); 00247 00248 if ( hOutDS == NULL ) { 00249 00250 GDALClose( hDataset ); 00251 GDALDestroyDriverManager(); 00252 00253 std::string msg = "Could not clone WCS raster!\n"; 00254 Log::instance()->error( msg.c_str() ); 00255 throw RasterException( msg.c_str() ); 00256 } 00257 00258 GDALClose( hOutDS ); 00259 GDALClose( hDataset ); 00260 00261 Log::instance()->debug( "Done!\n" ); 00262 00263 GdalRaster::createRaster( clone_ref, categ ); 00264 00265 // Erase lock and retries 00266 CacheManager::eraseCache( lock_file, OM_WCS_PROXY_SUBDIR ); 00267 CacheManager::eraseCache( retries_file, OM_WCS_PROXY_SUBDIR ); 00268 } 00269 catch ( RasterException& e ) { 00270 00271 if ( e.getCode() != 1 ) { 00272 00273 // Erase lock 00274 CacheManager::eraseCache( lock_file, OM_WCS_PROXY_SUBDIR ); 00275 } 00276 00277 throw; 00278 } 00279 catch (...) { 00280 00281 // Erase lock 00282 CacheManager::eraseCache( lock_file, OM_WCS_PROXY_SUBDIR ); 00283 throw; 00284 } 00285 } 00286 } 00287 else { 00288 00289 Log::instance()->debug( "openModeller configured to work with remote WCS rasters\n" ); 00290 00291 GdalRaster::createRaster( cached_ref, categ ); 00292 } 00293 } 00294 00295 #ifdef MPI_FOUND 00296 void 00297 WcsProxyRaster::createRaster( const string& output_file, const string& file, const MapFormat& format) { 00298 00299 std::string msg = "Method createRaster() not available to create writable WCS rasters.\n"; 00300 Log::instance()->error( msg.c_str() ); 00301 throw RasterException( msg.c_str() ); 00302 } 00303 00304 #else 00305 void 00306 WcsProxyRaster::createRaster( const string& file, const MapFormat& format) { 00307 00308 std::string msg = "Method createRaster() not available to create writable WCS rasters.\n"; 00309 Log::instance()->warn( msg.c_str() ); 00310 throw RasterException( msg.c_str() ); 00311 } 00312 #endif 00313 00314 /***********/ 00315 /*** put ***/ 00316 int 00317 WcsProxyRaster::put( Coord px, Coord py, Scalar val ) 00318 { 00319 std::string msg = "Method put() not available for WCS rasters.\n"; 00320 Log::instance()->warn( msg.c_str() ); 00321 throw RasterException( msg.c_str() ); 00322 } 00323 00324 /***********/ 00325 /*** put ***/ 00326 int 00327 WcsProxyRaster::put( Coord px, Coord py ) 00328 { 00329 std::string msg = "Method put() not available for WCS rasters.\n"; 00330 Log::instance()->warn( msg.c_str() ); 00331 throw RasterException( msg.c_str() ); 00332 } 00333 00334 /**************/ 00335 /*** finish ***/ 00336 void 00337 WcsProxyRaster::finish() 00338 { 00339 std::string msg = "Method finish() not available for WCS rasters.\n"; 00340 Log::instance()->warn( msg.c_str() ); 00341 throw RasterException( msg.c_str() ); 00342 } 00343 00344 /*********************/ 00345 /*** delete Raster ***/ 00346 int 00347 WcsProxyRaster::deleteRaster() 00348 { 00349 std::string msg = "Method deleteRaster() not available for WCS rasters.\n"; 00350 Log::instance()->warn( msg.c_str() ); 00351 throw RasterException( msg.c_str() ); 00352 }