00001 #ifndef Impala_Application_TagsLife_RemoteRetriever_h
00002 #define Impala_Application_TagsLife_RemoteRetriever_h
00003
00004 #ifdef USE_CURL
00005
00006 #include "curl/curl.h"
00007 #endif
00008
00009 #include <sys/stat.h>
00010 #include <iostream>
00011 #include <fstream>
00012
00013 #ifdef USE_BOOST_THREAD
00014 #ifndef USE_BOOST_THREADPOOL
00015 #include <boost/thread/thread.hpp>
00016 #endif
00017 #endif
00018
00019 #ifdef USE_BOOST_THREADPOOL
00020 #define USE_BOOST_THREAD
00021
00022
00023
00024 #include "threadpool25/threadpool.hpp"
00025 using namespace boost::threadpool;
00026 #endif
00027
00028 #include "Visualization/RgbOglImage.h"
00029 #include "Core/Array/ReadImage.h"
00030
00031 namespace Impala {
00032 namespace Application {
00033 namespace TagsLife {
00034
00035 class RemoteRetriever {
00036 public:
00037 static RemoteRetriever* GetInstance() {
00038 if (!sInstance)
00039 {
00040 ILOG_INFO("Instantiating RemoteRetriever.");
00041 sInstance = new RemoteRetriever();
00042 }
00043 return sInstance;
00044 }
00045
00046
00047
00048
00049
00050
00051
00052 OGLIMAGE* requestImage(std::string url, bool fromCache=true, bool toCache=true) {
00053 Core::Array::Array2dVec3UInt8* empty = Core::Array::ArrayCreate<Core::Array::Array2dVec3UInt8>(0, 0, 0, 0);
00054 OGLIMAGE* oglIm = Visualization::RgbOglImage::OglImage(empty);
00055 if(!mUseCache) fromCache = toCache = false;
00056 RemoteImageRetriever retriever = RemoteImageRetriever(url, oglIm, fromCache, toCache, mCachePrefix);
00057 #ifdef USE_BOOST_THREAD
00058 #ifdef USE_BOOST_THREADPOOL
00059 threadpool.schedule(retriever);
00060 #else
00061 boost::thread work(retriever);
00062 #endif
00063 #else
00064 retriever();
00065 #endif
00066 ILOG_DEBUG("Returning image of " << oglIm->w << "x" << oglIm->h <<" pixels at " << oglIm);
00067 return oglIm;
00068 }
00069
00070 std::string requestFile(std::string url, bool fromCache=true, bool toCache=true, std::string filename = "") {
00071
00072 RemoteFileRetriever retriever = RemoteFileRetriever(url, fromCache, toCache, filename);
00073 #ifdef USE_BOOST_THREAD
00074 #ifdef USE_BOOST_THREADPOOL
00075 threadpool.schedule(retriever);
00076 #else
00077 boost::thread work(retriever);
00078 #endif
00079 #else
00080 retriever();
00081 #endif
00082 return filename;
00083 }
00084
00085 class RemoteFileRetriever {
00086 public:
00087 RemoteFileRetriever(std::string url, bool fromCache, bool toCache, std::string filename = "") :
00088 url(url), fromCache(fromCache), toCache(toCache), filename(filename) {
00089 target = std::string();
00090 }
00091 RemoteFileRetriever(std::string url, std::string &target, bool fromCache, bool toCache, std::string filename = "") :
00092 url(url), fromCache(fromCache), toCache(toCache), filename(filename), target(target) {
00093 }
00094
00095 int operator()() {
00096 ILOG_DEBUG("Getting file from: " << url << " to store in " << target);
00097
00098 Core::Array::Array2dVec3UInt8* im = 0;
00099 if(fromCache && FileExists(filename)) {
00100 ILOG_DEBUG("Retrieving file from " << filename);
00101 std::ifstream cachedFile(filename.c_str(), std::ios::binary | std::ios::in);
00102 while (cachedFile.good())
00103 target += (char) cachedFile.get();
00104 cachedFile.close();
00105 return 1;
00106 }
00107
00108 #ifdef USE_CURL
00109 CURL *h = curl_easy_init();
00110 CURLcode result;
00111
00112 target = std::string();
00113
00114 curl_easy_setopt(h, CURLOPT_URL, url.c_str());
00115 curl_easy_setopt(h, CURLOPT_WRITEFUNCTION, CurlCallback);
00116 curl_easy_setopt(h, CURLOPT_WRITEDATA, &target);
00117
00118 ILOG_DEBUG("Retrieving remote: " << url);
00119 result = curl_easy_perform(h);
00120
00121 if (result == CURLE_OK) {
00122 ILOG_DEBUG("retrieved " << target.size() << ", trying decode...");
00123
00124 if(toCache) {
00125 std::ofstream cachedFile(filename.c_str(), std::ios::binary | std::ios::out);
00126 cachedFile << target;
00127 cachedFile.close();
00128 } else {
00129 }
00130 curl_easy_cleanup(h);
00131 return 1;
00132 }
00133 curl_easy_cleanup(h);
00134 ILOG_ERROR("Could not retrieve URI: " << url);
00135 return 0;
00136 #else
00137 ILOG_ERROR("Network retrieval of files not compiled in this version.");
00138 return 0;
00139 #endif
00140 }
00141
00142 bool FileExists(std::string strFilename) {
00143 struct stat stFileInfo;
00144 int intStat = stat(strFilename.c_str(),&stFileInfo);
00145 if(intStat == 0) return true;
00146 return false;
00147 }
00148
00149 #ifdef USE_CURL
00150 static size_t CurlCallback(char *data, size_t size, size_t nmemb, std::string *buffer) {
00151 if (buffer != 0) {
00152 buffer->append(data, size * nmemb);
00153 } else return 0;
00154 return size * nmemb;
00155 }
00156 #endif
00157
00158 std::string url, filename, target;
00159 bool toCache, fromCache;
00160 };
00161
00162 class RemoteImageRetriever : RemoteFileRetriever {
00163 public:
00164 RemoteImageRetriever(std::string &url, OGLIMAGE* &oglIm, bool fromCache, bool toCache, std::string cachePrefix) :
00165 oglIm(oglIm), RemoteFileRetriever(url, fromCache, toCache) {
00166 filename = cachePrefix + url.substr(url.find_last_of('/')+1);
00167 }
00168
00169 int operator()() {
00170 ILOG_DEBUG("Getting Image from: " << url << " to store in " << target);
00171
00172 if((toCache || fromCache) && !FileExists("Cache")) {
00173 ILOG_WARN("Cache folder does not exists, continuing without cache");
00174 toCache = fromCache = false;
00175 }
00176
00177 Core::Array::Array2dVec3UInt8* im = 0;
00178
00179 RemoteFileRetriever::operator()();
00180
00181 Core::Array::ReadJpgFromMemory(im, (char*) target.c_str(), target.size());
00182 if(im != 0) {
00183 oglIm->imageHandle = im;
00184 oglIm->h = im->CH();
00185 oglIm->w = im->CW();
00186 oglIm->changed = 1;
00187 ILOG_DEBUG("Loaded an image of " << oglIm->w << "x" << oglIm->h <<" pixels to " << oglIm << " from " << url);
00188 return 1;
00189 }
00190
00191 ILOG_ERROR("Failed to load image from " << url << "! (buffer.size = " << target.size() << ")");
00192
00193 oglIm->h = -1;
00194 oglIm->w = -1;
00195 oglIm->changed = 1;
00196 return 0;
00197 }
00198
00199 OGLIMAGE* oglIm;
00200 };
00201
00202 private:
00203 RemoteRetriever(std::string cachePrefix = "Cache/")
00204 {
00205
00206 #ifdef USE_CURL
00207 if (!sCurlInit) {
00208 ILOG_DEBUG("Initializing CURL...");
00209
00210 curl_global_init(CURL_GLOBAL_WIN32);
00211 sCurlInit = true;
00212 }
00213 #endif
00214
00215 #ifdef USE_BOOST_THREADPOOL
00216 threadpool = pool(8);
00217 #endif
00218 mCachePrefix = cachePrefix;
00219
00220 mUseCache = true;
00221
00222
00223 }
00224
00225 RemoteRetriever(RemoteRetriever const&){};
00226 RemoteRetriever& operator=(RemoteRetriever const&){};
00227
00228 bool mUseCache;
00229 std::string mCachePrefix;
00230
00231 static RemoteRetriever* sInstance;
00232
00233 #ifdef USE_CURL
00234 static bool sCurlInit;
00235 #endif
00236
00237 #ifdef USE_BOOST_THREADPOOL
00238 pool threadpool;
00239 #endif
00240
00241 ILOG_VAR_DEC;
00242 };
00243
00244 RemoteRetriever* RemoteRetriever::sInstance = 0;
00245
00246 #ifdef USE_CURL
00247 bool RemoteRetriever::sCurlInit = false;
00248 #endif
00249
00250 ILOG_VAR_INIT(RemoteRetriever, Application.TagsLife);
00251
00252 }
00253 }
00254 }
00255
00256 #endif // Impala_Application_TagsLife_RemoteRetriever_h