1 /* 2 * Copyright 2012 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Paweł Dziepak, pdziepak@quarnos.org 7 */ 8 9 10 #include "MetadataCache.h" 11 12 #include <NodeMonitor.h> 13 14 #include "Inode.h" 15 16 17 MetadataCache::MetadataCache(Inode* inode) 18 : 19 fExpire(0), 20 fForceValid(false), 21 fInode(inode), 22 fInited(false) 23 { 24 ASSERT(inode != NULL); 25 mutex_init(&fLock, NULL); 26 } 27 28 29 MetadataCache::~MetadataCache() 30 { 31 mutex_destroy(&fLock); 32 } 33 34 35 status_t 36 MetadataCache::GetStat(struct stat* st) 37 { 38 ASSERT(st != NULL); 39 40 MutexLocker _(fLock); 41 if (fForceValid || fExpire > time(NULL)) { 42 // Do not touch other members of struct stat 43 st->st_size = fStatCache.st_size; 44 st->st_mode = fStatCache.st_mode; 45 st->st_nlink = fStatCache.st_nlink; 46 st->st_uid = fStatCache.st_uid; 47 st->st_gid = fStatCache.st_gid; 48 st->st_atim = fStatCache.st_atim; 49 st->st_ctim = fStatCache.st_ctim; 50 st->st_crtim = fStatCache.st_crtim; 51 st->st_mtim = fStatCache.st_mtim; 52 st->st_blksize = fStatCache.st_blksize; 53 st->st_blocks = fStatCache.st_blocks; 54 return B_OK; 55 } 56 57 return B_ERROR; 58 } 59 60 61 void 62 MetadataCache::SetStat(const struct stat& st) 63 { 64 MutexLocker _(fLock); 65 if (fInited) 66 NotifyChanges(&fStatCache, &st); 67 68 fStatCache = st; 69 fExpire = time(NULL) + kExpirationTime; 70 fInited = true; 71 } 72 73 74 void 75 MetadataCache::GrowFile(size_t newSize) 76 { 77 MutexLocker _(fLock); 78 fStatCache.st_size = max_c((off_t)newSize, fStatCache.st_size); 79 } 80 81 82 status_t 83 MetadataCache::GetAccess(uid_t uid, uint32* allowed) 84 { 85 ASSERT(allowed != NULL); 86 87 MutexLocker _(fLock); 88 AVLTreeMap<uid_t, AccessEntry>::Iterator it = fAccessCache.Find(uid); 89 if (!it.HasCurrent()) 90 return B_ENTRY_NOT_FOUND; 91 92 if (!fForceValid) 93 it.CurrentValuePointer()->fForceValid = false; 94 95 if (!it.Current().fForceValid && it.Current().fExpire < time(NULL)) { 96 it.Remove(); 97 return B_ERROR; 98 } 99 100 *allowed = it.Current().fAllowed; 101 102 return B_OK; 103 } 104 105 106 void 107 MetadataCache::SetAccess(uid_t uid, uint32 allowed) 108 { 109 MutexLocker _(fLock); 110 AVLTreeMap<uid_t, AccessEntry>::Iterator it = fAccessCache.Find(uid); 111 if (it.HasCurrent()) 112 it.Remove(); 113 114 AccessEntry entry; 115 entry.fAllowed = allowed; 116 entry.fExpire = time(NULL) + kExpirationTime; 117 entry.fForceValid = fForceValid; 118 119 fAccessCache.Insert(uid, entry); 120 } 121 122 123 status_t 124 MetadataCache::LockValid() 125 { 126 MutexLocker _(fLock); 127 if (fForceValid || fExpire > time(NULL)) { 128 fForceValid = true; 129 return B_OK; 130 } 131 132 return B_ERROR; 133 } 134 135 136 void 137 MetadataCache::UnlockValid() 138 { 139 MutexLocker _(fLock); 140 fExpire = time(NULL) + kExpirationTime; 141 fForceValid = false; 142 } 143 144 145 void 146 MetadataCache::NotifyChanges(const struct stat* oldStat, 147 const struct stat* newStat) 148 { 149 ASSERT(oldStat != NULL); 150 ASSERT(newStat != NULL); 151 152 uint32 flags = 0; 153 if (oldStat->st_size != newStat->st_size) 154 flags |= B_STAT_SIZE; 155 if (oldStat->st_mode != newStat->st_mode) 156 flags |= B_STAT_MODE; 157 if (oldStat->st_uid != newStat->st_uid) 158 flags |= B_STAT_UID; 159 if (oldStat->st_gid != newStat->st_gid) 160 flags |= B_STAT_GID; 161 162 if (memcmp(&oldStat->st_atim, &newStat->st_atim, 163 sizeof(struct timespec) == 0)) 164 flags |= B_STAT_ACCESS_TIME; 165 166 if (memcmp(&oldStat->st_ctim, &newStat->st_ctim, 167 sizeof(struct timespec) == 0)) 168 flags |= B_STAT_CHANGE_TIME; 169 170 if (memcmp(&oldStat->st_crtim, &newStat->st_crtim, 171 sizeof(struct timespec) == 0)) 172 flags |= B_STAT_CREATION_TIME; 173 174 if (memcmp(&oldStat->st_mtim, &newStat->st_mtim, 175 sizeof(struct timespec) == 0)) 176 flags |= B_STAT_MODIFICATION_TIME; 177 178 notify_stat_changed(fInode->GetFileSystem()->DevId(), fInode->ID(), flags); 179 } 180 181