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