ocl: binary program cache
This commit is contained in:
@@ -0,0 +1,445 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#include <opencv2/core/utils/configuration.private.hpp>
|
||||
|
||||
#include <opencv2/core/utils/logger.hpp>
|
||||
|
||||
#include "opencv2/core/utils/filesystem.private.hpp"
|
||||
#include "opencv2/core/utils/filesystem.hpp"
|
||||
|
||||
//#define DEBUG_FS_UTILS
|
||||
|
||||
#ifdef DEBUG_FS_UTILS
|
||||
#include <iostream>
|
||||
#define DBG(...) __VA_ARGS__
|
||||
#else
|
||||
#define DBG(...)
|
||||
#endif
|
||||
|
||||
|
||||
#if OPENCV_HAVE_FILESYSTEM_SUPPORT
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
#include <direct.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#elif defined __linux__ || defined __APPLE__
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
namespace cv { namespace utils { namespace fs {
|
||||
|
||||
static inline
|
||||
bool isPathSeparator(char c)
|
||||
{
|
||||
return c == '/' || c == '\\';
|
||||
}
|
||||
|
||||
bool exists(const cv::String& path)
|
||||
{
|
||||
CV_INSTRUMENT_REGION()
|
||||
|
||||
#if defined _WIN32 || defined WINCE
|
||||
BOOL status = TRUE;
|
||||
{
|
||||
WIN32_FILE_ATTRIBUTE_DATA all_attrs;
|
||||
#ifdef WINRT
|
||||
wchar_t wpath[MAX_PATH];
|
||||
size_t copied = mbstowcs(wpath, path.c_str(), MAX_PATH);
|
||||
CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1));
|
||||
status = ::GetFileAttributesExW(wpath, GetFileExInfoStandard, &all_attrs);
|
||||
#else
|
||||
status = ::GetFileAttributesExA(path.c_str(), GetFileExInfoStandard, &all_attrs);
|
||||
#endif
|
||||
}
|
||||
|
||||
return !!status;
|
||||
#else
|
||||
struct stat stat_buf;
|
||||
return (0 == stat(path.c_str(), &stat_buf));
|
||||
#endif
|
||||
}
|
||||
|
||||
cv::String getcwd()
|
||||
{
|
||||
CV_INSTRUMENT_REGION()
|
||||
cv::AutoBuffer<char, 4096> buf;
|
||||
#if defined WIN32 || defined _WIN32 || defined WINCE
|
||||
#ifdef WINRT
|
||||
return cv::String();
|
||||
#else
|
||||
DWORD sz = GetCurrentDirectoryA(0, NULL);
|
||||
buf.allocate((size_t)sz);
|
||||
sz = GetCurrentDirectoryA((DWORD)buf.size(), (char*)buf);
|
||||
return cv::String((char*)buf, (size_t)sz);
|
||||
#endif
|
||||
#elif defined __linux__ || defined __APPLE__
|
||||
for(;;)
|
||||
{
|
||||
char* p = ::getcwd((char*)buf, buf.size());
|
||||
if (p == NULL)
|
||||
{
|
||||
if (errno == ERANGE)
|
||||
{
|
||||
buf.allocate(buf.size() * 2);
|
||||
continue;
|
||||
}
|
||||
return cv::String();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return cv::String((char*)buf, (size_t)strlen((char*)buf));
|
||||
#else
|
||||
return cv::String();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool createDirectory(const cv::String& path)
|
||||
{
|
||||
CV_INSTRUMENT_REGION()
|
||||
#if defined WIN32 || defined _WIN32 || defined WINCE
|
||||
#ifdef WINRT
|
||||
wchar_t wpath[MAX_PATH];
|
||||
size_t copied = mbstowcs(wpath, path.c_str(), MAX_PATH);
|
||||
CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1));
|
||||
int result = CreateDirectoryA(wpath, NULL) ? 0 : -1;
|
||||
#else
|
||||
int result = _mkdir(path.c_str());
|
||||
#endif
|
||||
#elif defined __linux__ || defined __APPLE__
|
||||
int result = mkdir(path.c_str(), 0777);
|
||||
#else
|
||||
int result = -1;
|
||||
#endif
|
||||
|
||||
if (result == -1)
|
||||
{
|
||||
return isDirectory(path);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool createDirectories(const cv::String& path_)
|
||||
{
|
||||
cv::String path = path_;
|
||||
for (;;)
|
||||
{
|
||||
char last_char = path.empty() ? 0 : path[path.length() - 1];
|
||||
if (last_char == '/' || last_char == '\\')
|
||||
{
|
||||
path = path.substr(0, path.length() - 1);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (path.empty() || path == "./" || path == ".\\" || path == ".")
|
||||
return true;
|
||||
if (isDirectory(path))
|
||||
return true;
|
||||
|
||||
size_t pos = path.rfind('/');
|
||||
if (pos == cv::String::npos)
|
||||
pos = path.rfind('\\');
|
||||
if (pos != cv::String::npos)
|
||||
{
|
||||
cv::String parent_directory = path.substr(0, pos);
|
||||
if (!parent_directory.empty())
|
||||
{
|
||||
if (!createDirectories(parent_directory))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return createDirectory(path);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
struct FileLock::Impl
|
||||
{
|
||||
Impl(const char* fname)
|
||||
{
|
||||
// http://support.microsoft.com/kb/316609
|
||||
int numRetries = 5;
|
||||
do
|
||||
{
|
||||
handle = ::CreateFileA(fname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (INVALID_HANDLE_VALUE == handle)
|
||||
{
|
||||
if (ERROR_SHARING_VIOLATION == GetLastError())
|
||||
{
|
||||
numRetries--;
|
||||
Sleep(250);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_ErrorNoReturn_(Error::StsAssert, ("Can't open lock file: %s", fname));
|
||||
}
|
||||
}
|
||||
break;
|
||||
} while (numRetries > 0);
|
||||
}
|
||||
~Impl()
|
||||
{
|
||||
if (INVALID_HANDLE_VALUE != handle)
|
||||
{
|
||||
::CloseHandle(handle);
|
||||
}
|
||||
}
|
||||
|
||||
bool lock()
|
||||
{
|
||||
OVERLAPPED overlapped;
|
||||
std::memset(&overlapped, 0, sizeof(overlapped));
|
||||
return !!::LockFileEx(handle, LOCKFILE_EXCLUSIVE_LOCK, 0, MAXDWORD, MAXDWORD, &overlapped);
|
||||
}
|
||||
bool unlock()
|
||||
{
|
||||
OVERLAPPED overlapped;
|
||||
std::memset(&overlapped, 0, sizeof(overlapped));
|
||||
return !!::UnlockFileEx(handle, 0, MAXDWORD, MAXDWORD, &overlapped);
|
||||
}
|
||||
|
||||
bool lock_shared()
|
||||
{
|
||||
OVERLAPPED overlapped;
|
||||
std::memset(&overlapped, 0, sizeof(overlapped));
|
||||
return !!::LockFileEx(handle, 0, 0, MAXDWORD, MAXDWORD, &overlapped);
|
||||
}
|
||||
bool unlock_shared()
|
||||
{
|
||||
return unlock();
|
||||
}
|
||||
|
||||
HANDLE handle;
|
||||
|
||||
private:
|
||||
Impl(const Impl&); // disabled
|
||||
Impl& operator=(const Impl&); // disabled
|
||||
};
|
||||
|
||||
#elif defined __linux__ || defined __APPLE__
|
||||
|
||||
struct FileLock::Impl
|
||||
{
|
||||
Impl(const char* fname)
|
||||
{
|
||||
handle = ::open(fname, O_RDWR);
|
||||
CV_Assert(handle != -1);
|
||||
}
|
||||
~Impl()
|
||||
{
|
||||
if (handle >= 0)
|
||||
::close(handle);
|
||||
}
|
||||
|
||||
bool lock()
|
||||
{
|
||||
struct ::flock l;
|
||||
std::memset(&l, 0, sizeof(l));
|
||||
l.l_type = F_WRLCK;
|
||||
l.l_whence = SEEK_SET;
|
||||
l.l_start = 0;
|
||||
l.l_len = 0;
|
||||
DBG(std::cout << "Lock..." << std::endl);
|
||||
bool res = -1 != ::fcntl(handle, F_SETLKW, &l);
|
||||
return res;
|
||||
}
|
||||
bool unlock()
|
||||
{
|
||||
struct ::flock l;
|
||||
std::memset(&l, 0, sizeof(l));
|
||||
l.l_type = F_UNLCK;
|
||||
l.l_whence = SEEK_SET;
|
||||
l.l_start = 0;
|
||||
l.l_len = 0;
|
||||
DBG(std::cout << "Unlock..." << std::endl);
|
||||
bool res = -1 != ::fcntl(handle, F_SETLK, &l);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool lock_shared()
|
||||
{
|
||||
struct ::flock l;
|
||||
std::memset(&l, 0, sizeof(l));
|
||||
l.l_type = F_RDLCK;
|
||||
l.l_whence = SEEK_SET;
|
||||
l.l_start = 0;
|
||||
l.l_len = 0;
|
||||
DBG(std::cout << "Lock read..." << std::endl);
|
||||
bool res = -1 != ::fcntl(handle, F_SETLKW, &l);
|
||||
return res;
|
||||
}
|
||||
bool unlock_shared()
|
||||
{
|
||||
return unlock();
|
||||
}
|
||||
|
||||
int handle;
|
||||
|
||||
private:
|
||||
Impl(const Impl&); // disabled
|
||||
Impl& operator=(const Impl&); // disabled
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
FileLock::FileLock(const char* fname)
|
||||
: pImpl(new Impl(fname))
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
FileLock::~FileLock()
|
||||
{
|
||||
delete pImpl;
|
||||
pImpl = NULL;
|
||||
}
|
||||
|
||||
void FileLock::lock() { CV_Assert(pImpl->lock()); }
|
||||
void FileLock::unlock() { CV_Assert(pImpl->unlock()); }
|
||||
void FileLock::lock_shared() { CV_Assert(pImpl->lock_shared()); }
|
||||
void FileLock::unlock_shared() { CV_Assert(pImpl->unlock_shared()); }
|
||||
|
||||
|
||||
|
||||
cv::String getCacheDirectory(const char* sub_directory_name, const char* configuration_name)
|
||||
{
|
||||
String cache_path;
|
||||
if (configuration_name)
|
||||
{
|
||||
cache_path = utils::getConfigurationParameterString(configuration_name, "");
|
||||
}
|
||||
if (cache_path.empty())
|
||||
{
|
||||
cv::String default_cache_path;
|
||||
#ifdef _WIN32
|
||||
char tmp_path_buf[MAX_PATH+1] = {0};
|
||||
DWORD res = GetTempPath(MAX_PATH, tmp_path_buf);
|
||||
if (res > 0 && res <= MAX_PATH)
|
||||
{
|
||||
default_cache_path = tmp_path_buf;
|
||||
}
|
||||
#elif defined __ANDROID__
|
||||
// no defaults
|
||||
#elif defined __APPLE__
|
||||
const char* tmpdir_env = getenv("TMPDIR");
|
||||
if (tmpdir_env && utils::fs::isDirectory(tmpdir_env))
|
||||
{
|
||||
default_cache_path = tmpdir_env;
|
||||
}
|
||||
else
|
||||
{
|
||||
default_cache_path = "/tmp/";
|
||||
CV_LOG_WARNING(NULL, "Using world accessible cache directory. This may be not secure: " << default_cache_path);
|
||||
}
|
||||
#elif defined __linux__
|
||||
// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
if (default_cache_path.empty())
|
||||
{
|
||||
const char* xdg_cache_env = getenv("XDG_CACHE_HOME");
|
||||
if (xdg_cache_env && xdg_cache_env[0] && utils::fs::isDirectory(xdg_cache_env))
|
||||
{
|
||||
default_cache_path = xdg_cache_env;
|
||||
}
|
||||
}
|
||||
if (default_cache_path.empty())
|
||||
{
|
||||
const char* home_env = getenv("HOME");
|
||||
if (home_env && home_env[0] && utils::fs::isDirectory(home_env))
|
||||
{
|
||||
cv::String home_path = home_env;
|
||||
cv::String home_cache_path = home_path + "/.cache/";
|
||||
if (utils::fs::isDirectory(home_cache_path))
|
||||
{
|
||||
default_cache_path = home_cache_path;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (default_cache_path.empty())
|
||||
{
|
||||
const char* temp_path = "/var/tmp/";
|
||||
if (utils::fs::isDirectory(temp_path))
|
||||
{
|
||||
default_cache_path = temp_path;
|
||||
CV_LOG_WARNING(NULL, "Using world accessible cache directory. This may be not secure: " << default_cache_path);
|
||||
}
|
||||
}
|
||||
if (default_cache_path.empty())
|
||||
{
|
||||
default_cache_path = "/tmp/";
|
||||
CV_LOG_WARNING(NULL, "Using world accessible cache directory. This may be not secure: " << default_cache_path);
|
||||
}
|
||||
#else
|
||||
// no defaults
|
||||
#endif
|
||||
CV_LOG_VERBOSE(NULL, 0, "default_cache_path = " << default_cache_path);
|
||||
if (!default_cache_path.empty())
|
||||
{
|
||||
if (utils::fs::isDirectory(default_cache_path))
|
||||
{
|
||||
default_cache_path += "/opencv/" CV_VERSION "/";
|
||||
if (sub_directory_name && sub_directory_name[0] != '\0')
|
||||
default_cache_path += cv::String(sub_directory_name) + "/";
|
||||
if (!utils::fs::createDirectories(default_cache_path))
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "Can't create OpenCV cache sub-directory: " << default_cache_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
cache_path = default_cache_path;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_LOG_INFO(NULL, "Can't find default cache directory (does it exist?): " << default_cache_path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "OpenCV has no support to discover default cache directory on the current platform");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cache_path == "disabled")
|
||||
return cache_path;
|
||||
if (!isDirectory(cache_path))
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "Specified non-existed directory, creating OpenCV sub-directory for caching purposes: " << cache_path);
|
||||
if (!createDirectories(cache_path))
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "Can't create OpenCV cache sub-directory: " << cache_path);
|
||||
cache_path.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
CV_Assert(cache_path.empty() || utils::fs::isDirectory(cache_path));
|
||||
if (!cache_path.empty())
|
||||
{
|
||||
if (!isPathSeparator(cache_path[cache_path.size() - 1]))
|
||||
{
|
||||
cache_path += '/';
|
||||
}
|
||||
}
|
||||
return cache_path;
|
||||
}
|
||||
|
||||
}}} // namespace
|
||||
|
||||
#endif // OPENCV_HAVE_FILESYSTEM_SUPPORT
|
||||
Reference in New Issue
Block a user