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 = do_refcount_ ? fd_mgr_->Close(fd) : 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_);
183 if ((transaction->
label.
flags & kLabelPinned) ||
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());
209 if ((transaction->
label.
flags & kLabelPinned) ||
212 quota_mgr_->Remove(transaction->
id);
216 if (transaction->
label.
flags & kLabelVolatile) {
217 quota_mgr_->InsertVolatile(transaction->
id, transaction->
size,
222 quota_mgr_->Insert(transaction->
id, transaction->
size,
226 transaction->~Transaction();
227 atomic_dec32(&no_inflight_txns_);
243 "Cache directory structure created.");
244 switch (fs_info.
type) {
246 rename_workaround_ = kRenameLink;
248 "Alien cache is on NFS.");
251 rename_workaround_ = kRenameSamedir;
253 "Alien cache is on BeeGFS.");
264 if (
FileExists(cache_path +
"/cvmfscatalog.cache")) {
266 "Not mounting on cvmfs 2.0.X cache");
273 const string &cache_path,
274 const bool alien_cache,
276 const bool do_refcount)
289 return cache_manager.
Release();
299 transaction->
label = label;
306 msg =
"Refcounting Posix cache manager"
307 "(cache directory: " + cache_path_ +
")\n";
309 msg =
"Posix cache manager (cache directory: " + cache_path_ +
")\n";
322 state->
fd_mgr = fd_mgr_->Clone();
325 char *c =
reinterpret_cast<char *
>(smalloc(1));
326 *c = kMagicNoRefcount;
337 "refcounted posix cache manager");
342 "non-refcounted posix cache manager");
347 char *c =
reinterpret_cast<char *
>(data);
348 assert(*c == kMagicNoRefcount || *c == kMagicRefcount);
349 if (*c == kMagicRefcount) {
352 "refcounted posix cache manager - this "
353 " is not possible, keep refcounting.");
377 int new_fd = do_refcount_ ? fd_mgr_->Dup(fd) : dup(fd);
391 if (static_cast<unsigned>(written) != transaction->
buf_pos) {
392 transaction->
buf_pos -= written;
401 return cache_path_ +
"/" +
id.MakePathWithoutSuffix();
415 const string path = GetPathInCache(
object.
id);
418 result = fd_mgr_->Open(
object.
id, path);
420 result = open(path.c_str(), O_RDONLY);
425 quota_mgr_->Touch(
object.
id);
436 int retval = Flush(transaction);
442 fd_rdonly = fd_mgr_->Open(transaction->
id, transaction->
tmp_path.c_str());
444 fd_rdonly = open(transaction->
tmp_path.c_str(), O_RDONLY);
461 result = pread(fd, buf, size, offset);
462 }
while ((result == -1) && (errno == EINTR));
471 if (rename_workaround_ != kRenameLink) {
472 result = rename(oldpath, newpath);
478 result = link(oldpath, newpath);
480 if (errno == EEXIST) {
486 result = unlink(oldpath);
500 unsigned char *buf[4096];
507 nbytes = Pread(fd, buf, 4096, pos);
509 }
while (nbytes == 4096);
520 transaction->
size = 0;
521 int retval = lseek(transaction->
fd, 0, SEEK_SET);
524 retval = ftruncate(transaction->
fd, 0);
536 atomic_inc32(&no_inflight_txns_);
538 atomic_dec32(&no_inflight_txns_);
542 if (size != kSizeUnknown) {
543 if (size > quota_mgr_->GetMaxFileSize()) {
545 "requested but only %" PRIu64
" bytes free)",
546 size, quota_mgr_->GetMaxFileSize());
547 atomic_dec32(&no_inflight_txns_);
552 if (size > kBigFile) {
553 uint64_t cache_size = quota_mgr_->GetSize();
554 uint64_t cache_capacity = quota_mgr_->GetCapacity();
555 assert(cache_capacity >= size);
556 if ((cache_size + size) > cache_capacity) {
557 uint64_t leave_size =
558 std::min(cache_capacity / 2, cache_capacity - size);
559 quota_mgr_->Cleanup(leave_size);
564 string path_in_cache = GetPathInCache(
id);
567 char *template_path = NULL;
568 unsigned temp_path_len = 0;
569 if (rename_workaround_ == kRenameSamedir) {
570 temp_path_len = path_in_cache.length() + 6;
571 template_path =
reinterpret_cast<char *
>(alloca(temp_path_len + 1));
572 memcpy(template_path, path_in_cache.data(), path_in_cache.length());
573 memset(template_path + path_in_cache.length(),
'X', 6);
575 temp_path_len = txn_template_path_.length();
576 template_path =
reinterpret_cast<char *
>(alloca(temp_path_len + 1));
577 memcpy(template_path, &txn_template_path_[0], temp_path_len);
579 template_path[temp_path_len] =
'\0';
581 transaction->
fd = mkstemp(template_path);
582 if (transaction->
fd == -1) {
583 transaction->~Transaction();
584 atomic_dec32(&no_inflight_txns_);
589 template_path, transaction->
fd);
590 transaction->
tmp_path = template_path;
592 return transaction->
fd;
609 return breadcrumb.
Export(fqrn, cache_path_, 0600);
615 while (atomic_read32(&no_inflight_txns_) != 0)
630 "Transaction size (%" PRIu64
") > expected size (%" PRIu64
")",
636 uint64_t written = 0;
637 const unsigned char *read_pos =
reinterpret_cast<const unsigned char *
>(buf);
638 while (written < size) {
640 int retval = Flush(transaction);
642 transaction->
size += written;
646 uint64_t remaining = size - written;
647 uint64_t space_in_buffer =
649 uint64_t batch_size = std::min(remaining, space_in_buffer);
650 memcpy(transaction->
buffer + transaction->
buf_pos, read_pos, batch_size);
651 transaction->
buf_pos += batch_size;
652 written += batch_size;
653 read_pos += batch_size;
655 transaction->
size += written;
bool MakeCacheDirectories(const std::string &path, const mode_t mode)
RenameWorkarounds rename_workaround_
virtual int64_t Write(const void *buf, uint64_t size, void *txn)
const manifest::Manifest * manifest() const
virtual int Open(const LabeledObject &object)
std::string GetDescription() const
int Flush(Transaction *transaction)
virtual int CommitTxn(void *txn)
std::string ToString(const bool with_suffix=false) const
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")
virtual void CtrlTxn(const Label &label, const int flags, void *txn)
bool CopyPath2Path(const string &src, const string &dest)
int Rename(const char *oldpath, const char *newpath)
std::string GetPathInCache(const shash::Any &id)
bool InitCacheDirectory(const string &cache_path)
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
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)
static PosixCacheManager * Create(const std::string &cache_path, const bool alien_cache, const RenameWorkarounds rename_workaround=kRenameNormal, const bool do_refcount=false)
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)
UniquePtr< FdRefcountMgr > fd_mgr
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)