27 #define __STDC_FORMAT_MACROS
29 #include "cvmfs_config.h"
38 #include <sys/types.h>
40 #include <sys/statfs.h>
82 int32_t global_drainout = atomic_read32(&global_drainout_);
83 drainout_ = (global_drainout != 0);
85 atomic_inc32(&num_inflight_calls_);
89 atomic_dec32(&num_inflight_calls_);
92 atomic_cas32(&global_drainout_, 0, 1);
93 while (atomic_read32(&num_inflight_calls_) != 0)
116 close(transaction->
fd);
117 int result = unlink(transaction->
tmp_path.c_str());
118 transaction->~Transaction();
119 atomic_dec32(&no_inflight_txns_);
132 if (quota_mgr == NULL)
135 quota_mgr_ = quota_mgr;
141 int retval = close(fd);
154 result = Flush(transaction);
155 close(transaction->
fd);
157 unlink(transaction->
tmp_path.c_str());
158 transaction->~Transaction();
159 atomic_dec32(&no_inflight_txns_);
168 (reports_correct_filesize_ || (transaction->
size != 0)) )
171 "size check failure for %s, expected %lu, got %lu",
175 cache_path_ +
"/quarantaine/" + transaction->
id.
ToString());
176 unlink(transaction->
tmp_path.c_str());
177 transaction->~Transaction();
178 atomic_dec32(&no_inflight_txns_);
186 bool retval = quota_mgr_->Pin(
192 unlink(transaction->
tmp_path.c_str());
193 transaction->~Transaction();
194 atomic_dec32(&no_inflight_txns_);
201 int retval = chmod(transaction->
tmp_path.c_str(), 0660);
208 unlink(transaction->
tmp_path.c_str());
212 quota_mgr_->Remove(transaction->
id);
217 quota_mgr_->InsertVolatile(transaction->
id, transaction->
size,
220 quota_mgr_->Insert(transaction->
id, transaction->
size,
224 transaction->~Transaction();
225 atomic_dec32(&no_inflight_txns_);
231 const string &cache_path,
232 const bool alien_cache,
245 "Cache directory structure created.");
247 switch (fs_info.
type) {
251 "Alien cache is on NFS.");
256 "Alien cache is on BeeGFS.");
267 if (
FileExists(cache_path +
"/cvmfscatalog.cache")) {
269 "Not mounting on cvmfs 2.0.X cache");
273 return cache_manager.
Release();
288 return "Posix cache manager (cache directory: " + cache_path_ +
")\n";
297 char *c =
reinterpret_cast<char *
>(smalloc(1));
305 char *c =
reinterpret_cast<char *
>(data);
319 int new_fd = dup(fd);
333 if (static_cast<unsigned>(written) != transaction->
buf_pos) {
334 transaction->
buf_pos -= written;
343 return cache_path_ +
"/" +
id.MakePathWithoutSuffix();
357 const string path = GetPathInCache(
object.
id);
358 int result = open(path.c_str(), O_RDONLY);
363 quota_mgr_->Touch(
object.
id);
374 int retval = Flush(transaction);
377 int fd_rdonly = open(transaction->
tmp_path.c_str(), O_RDONLY);
393 result = pread(fd, buf, size, offset);
394 }
while ((result == -1) && (errno == EINTR));
403 if (rename_workaround_ != kRenameLink) {
404 result = rename(oldpath, newpath);
410 result = link(oldpath, newpath);
412 if (errno == EEXIST) {
418 result = unlink(oldpath);
430 unsigned char *buf[4096];
434 nbytes = Pread(fd, buf, 4096, pos);
436 }
while (nbytes == 4096);
447 transaction->
size = 0;
448 int retval = lseek(transaction->
fd, 0, SEEK_SET);
451 retval = ftruncate(transaction->
fd, 0);
463 atomic_inc32(&no_inflight_txns_);
465 atomic_dec32(&no_inflight_txns_);
469 if (size != kSizeUnknown) {
470 if (size > quota_mgr_->GetMaxFileSize()) {
472 "requested but only %" PRIu64
" bytes free)",
473 size, quota_mgr_->GetMaxFileSize());
474 atomic_dec32(&no_inflight_txns_);
479 if (size > kBigFile) {
480 uint64_t cache_size = quota_mgr_->GetSize();
481 uint64_t cache_capacity = quota_mgr_->GetCapacity();
482 assert(cache_capacity >= size);
483 if ((cache_size + size) > cache_capacity) {
484 uint64_t leave_size =
485 std::min(cache_capacity / 2, cache_capacity - size);
486 quota_mgr_->Cleanup(leave_size);
491 string path_in_cache = GetPathInCache(
id);
494 char *template_path = NULL;
495 unsigned temp_path_len = 0;
496 if (rename_workaround_ == kRenameSamedir) {
497 temp_path_len = path_in_cache.length() + 6;
498 template_path =
reinterpret_cast<char *
>(alloca(temp_path_len + 1));
499 memcpy(template_path, path_in_cache.data(), path_in_cache.length());
500 memset(template_path + path_in_cache.length(),
'X', 6);
502 temp_path_len = txn_template_path_.length();
503 template_path =
reinterpret_cast<char *
>(alloca(temp_path_len + 1));
504 memcpy(template_path, &txn_template_path_[0], temp_path_len);
506 template_path[temp_path_len] =
'\0';
508 transaction->
fd = mkstemp(template_path);
509 if (transaction->
fd == -1) {
510 transaction->~Transaction();
511 atomic_dec32(&no_inflight_txns_);
516 template_path, transaction->
fd);
517 transaction->
tmp_path = template_path;
519 return transaction->
fd;
536 return breadcrumb.
Export(fqrn, cache_path_, 0600);
542 while (atomic_read32(&no_inflight_txns_) != 0)
557 "Transaction size (%" PRIu64
") > expected size (%" PRIu64
")",
563 uint64_t written = 0;
564 const unsigned char *read_pos =
reinterpret_cast<const unsigned char *
>(buf);
565 while (written < size) {
567 int retval = Flush(transaction);
569 transaction->
size += written;
573 uint64_t remaining = size - written;
574 uint64_t space_in_buffer =
576 uint64_t batch_size = std::min(remaining, space_in_buffer);
577 memcpy(transaction->
buffer + transaction->
buf_pos, read_pos, batch_size);
578 transaction->
buf_pos += batch_size;
579 written += batch_size;
580 read_pos += batch_size;
582 transaction->
size += written;
bool MakeCacheDirectories(const std::string &path, const mode_t mode)
#define LogCvmfs(source, mask,...)
RenameWorkarounds rename_workaround_
virtual int64_t Write(const void *buf, uint64_t size, void *txn)
const manifest::Manifest * manifest() const
int Flush(Transaction *transaction)
virtual int CommitTxn(void *txn)
std::string ToString(const bool with_suffix=false) const
virtual int Open(const BlessedObject &object)
virtual int AbortTxn(void *txn)
virtual void * DoSaveState()
virtual int64_t GetSize(int fd)
virtual bool AcquireQuotaManager(QuotaManager *quota_mgr)
assert((mem||(size==0))&&"Out Of Memory")
bool CopyPath2Path(const string &src, const string &dest)
int Rename(const char *oldpath, const char *newpath)
std::string GetPathInCache(const shash::Any &id)
virtual int OpenFromTxn(void *txn)
virtual int Readahead(int fd)
bool FileExists(const std::string &path)
unsigned char buffer[4096]
bool ExportBreadcrumb(const std::string &directory, const int mode) const
virtual void CtrlTxn(const ObjectInfo &object_info, const int flags, void *txn)
FileSystemInfo GetFileSystemInfo(const std::string &path)
static const uint64_t kBigFile
virtual int StartTxn(const shash::Any &id, uint64_t size, void *txn)
virtual manifest::Breadcrumb LoadBreadcrumb(const std::string &fqrn)
bool Export(const std::string &fqrn, const std::string &directory, const int mode) const
static atomic_int32 num_inflight_calls_
static atomic_int32 global_drainout_
virtual int Reset(void *txn)
virtual bool DoFreeState(void *data)
static Breadcrumb ReadBreadcrumb(const std::string &repo_name, const std::string &directory)
void SafeSleepMs(const unsigned ms)
virtual int DoRestoreState(void *data)
virtual std::string Describe()
virtual bool StoreBreadcrumb(const manifest::Manifest &manifest)
virtual int Close(int fd)
virtual int64_t Pread(int fd, void *buf, uint64_t size, uint64_t offset)
static PosixCacheManager * Create(const std::string &cache_path, const bool alien_cache, const RenameWorkarounds rename_workaround=kRenameNormal)