27 #define __STDC_FORMAT_MACROS
38 #include <sys/types.h>
40 #include <sys/statfs.h>
82 const 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)
117 close(transaction->
fd);
118 const int result = unlink(transaction->
tmp_path.c_str());
119 transaction->~Transaction();
120 atomic_dec32(&no_inflight_txns_);
133 if (quota_mgr == NULL)
136 quota_mgr_ = quota_mgr;
142 const int retval = do_refcount_ ? fd_mgr_->Close(fd) : close(fd);
155 result = Flush(transaction);
156 close(transaction->
fd);
158 unlink(transaction->
tmp_path.c_str());
159 transaction->~Transaction();
160 atomic_dec32(&no_inflight_txns_);
169 && (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_);
184 || (transaction->
label.
flags & kLabelCatalog)) {
185 const bool retval = quota_mgr_->Pin(
191 unlink(transaction->
tmp_path.c_str());
192 transaction->~Transaction();
193 atomic_dec32(&no_inflight_txns_);
200 const int retval = chmod(transaction->
tmp_path.c_str(), 0660);
203 result = Rename(transaction->
tmp_path.c_str(),
207 unlink(transaction->
tmp_path.c_str());
209 || (transaction->
label.
flags & kLabelCatalog)) {
210 quota_mgr_->Remove(transaction->
id);
214 if (transaction->
label.
flags & kLabelVolatile) {
215 quota_mgr_->InsertVolatile(transaction->
id, transaction->
size,
219 quota_mgr_->Insert(transaction->
id, transaction->
size,
223 transaction->~Transaction();
224 atomic_dec32(&no_inflight_txns_);
240 "Cache directory structure created.");
241 switch (fs_info.
type) {
243 rename_workaround_ = kRenameLink;
247 rename_workaround_ = kRenameSamedir;
249 "Alien cache is on BeeGFS.");
260 if (
FileExists(cache_path +
"/cvmfscatalog.cache")) {
262 "Not mounting on cvmfs 2.0.X cache");
269 const string &cache_path,
270 const bool alien_cache,
272 const bool do_refcount) {
284 return cache_manager.
Release();
292 transaction->
label = label;
299 msg =
"Refcounting Posix cache manager"
301 + cache_path_ +
")\n";
303 msg =
"Posix cache manager (cache directory: " + cache_path_ +
")\n";
316 state->
fd_mgr = fd_mgr_->Clone();
319 char *c =
reinterpret_cast<char *
>(smalloc(1));
320 *c = kMagicNoRefcount;
331 "Restoring refcount cache manager from "
332 "refcounted posix cache manager");
337 "Restoring refcount cache manager from "
338 "non-refcounted posix cache manager");
343 char *c =
reinterpret_cast<char *
>(data);
344 assert(*c == kMagicNoRefcount || *c == kMagicRefcount);
345 if (*c == kMagicRefcount) {
348 "Restoring non-refcount cache manager from "
349 "refcounted posix cache manager - this "
350 " is not possible, keep refcounting.");
373 const int new_fd = do_refcount_ ? fd_mgr_->Dup(fd) : dup(fd);
387 if (static_cast<unsigned>(written) != transaction->
buf_pos) {
388 transaction->
buf_pos -= written;
397 return cache_path_ +
"/" +
id.MakePathWithoutSuffix();
411 const string path = GetPathInCache(
object.
id);
414 result = fd_mgr_->Open(
object.
id, path);
416 result = open(path.c_str(), O_RDONLY);
421 quota_mgr_->Touch(
object.
id);
432 const int retval = Flush(transaction);
438 fd_rdonly = fd_mgr_->Open(transaction->
id, transaction->
tmp_path.c_str());
440 fd_rdonly = open(transaction->
tmp_path.c_str(), O_RDONLY);
455 result = pread(fd, buf, size, offset);
456 }
while ((result == -1) && (errno == EINTR));
465 if (rename_workaround_ != kRenameLink) {
466 result = rename(oldpath, newpath);
472 result = link(oldpath, newpath);
474 if (errno == EEXIST) {
480 result = unlink(oldpath);
494 unsigned char *buf[4096];
501 nbytes = Pread(fd, buf, 4096, pos);
503 }
while (nbytes == 4096);
514 transaction->
size = 0;
515 int retval = lseek(transaction->
fd, 0, SEEK_SET);
518 retval = ftruncate(transaction->
fd, 0);
528 atomic_inc32(&no_inflight_txns_);
530 atomic_dec32(&no_inflight_txns_);
534 if (size != kSizeUnknown) {
535 if (size > quota_mgr_->GetMaxFileSize()) {
537 "file too big for lru cache (%" PRIu64
" "
538 "requested but only %" PRIu64
" bytes free)",
539 size, quota_mgr_->GetMaxFileSize());
540 atomic_dec32(&no_inflight_txns_);
545 if (size > kBigFile) {
546 const uint64_t cache_size = quota_mgr_->GetSize();
547 const uint64_t cache_capacity = quota_mgr_->GetCapacity();
548 assert(cache_capacity >= size);
549 if ((cache_size + size) > cache_capacity) {
550 const uint64_t leave_size =
551 std::min(cache_capacity / 2, cache_capacity - size);
552 quota_mgr_->Cleanup(leave_size);
557 string path_in_cache = GetPathInCache(
id);
560 char *template_path = NULL;
561 unsigned temp_path_len = 0;
562 if (rename_workaround_ == kRenameSamedir) {
563 temp_path_len = path_in_cache.length() + 6;
564 template_path =
reinterpret_cast<char *
>(alloca(temp_path_len + 1));
565 memcpy(template_path, path_in_cache.data(), path_in_cache.length());
566 memset(template_path + path_in_cache.length(),
'X', 6);
568 temp_path_len = txn_template_path_.length();
569 template_path =
reinterpret_cast<char *
>(alloca(temp_path_len + 1));
570 memcpy(template_path, &txn_template_path_[0], temp_path_len);
572 template_path[temp_path_len] =
'\0';
574 transaction->
fd = mkstemp(template_path);
575 if (transaction->
fd == -1) {
576 transaction->~Transaction();
577 atomic_dec32(&no_inflight_txns_);
582 template_path, transaction->
fd);
583 transaction->
tmp_path = template_path;
585 return transaction->
fd;
590 const std::string &fqrn) {
602 return breadcrumb.
Export(fqrn, cache_path_, 0600);
608 while (atomic_read32(&no_inflight_txns_) != 0)
623 "Transaction size (%" PRIu64
") > expected size (%" PRIu64
")",
629 uint64_t written = 0;
630 const unsigned char *read_pos =
reinterpret_cast<const unsigned char *
>(buf);
631 while (written < size) {
633 const int retval = Flush(transaction);
635 transaction->
size += written;
639 const uint64_t remaining = size - written;
640 const uint64_t space_in_buffer =
642 const uint64_t batch_size = std::min(remaining, space_in_buffer);
643 memcpy(transaction->
buffer + transaction->
buf_pos, read_pos, batch_size);
644 transaction->
buf_pos += batch_size;
645 written += batch_size;
646 read_pos += batch_size;
648 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 PosixCacheManager * Create(const std::string &cache_path, const bool alien_cache, const RenameWorkarounds rename_workaround=kRenameNormal, const bool do_refcount=true)
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)
UniquePtr< FdRefcountMgr > fd_mgr
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)