XRootD
XrdFfsWcache.hh File Reference
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

int XrdFfsWcache_create (int fd, int flags)
 
void XrdFfsWcache_destroy (int fd)
 
ssize_t XrdFfsWcache_flush (int fd)
 
void XrdFfsWcache_init (int basefd, int maxfd)
 
ssize_t XrdFfsWcache_pread (int fd, char *buf, size_t len, off_t offset)
 
ssize_t XrdFfsWcache_pwrite (int fd, char *buf, size_t len, off_t offset)
 

Function Documentation

◆ XrdFfsWcache_create()

int XrdFfsWcache_create ( int  fd,
int  flags 
)

Definition at line 126 of file XrdFfsWcache.cc.

134 {
136  fd -= XrdFfsPosix_baseFD;
137 
138  XrdFfsWcacheFbufs[fd].offset = 0;
139  XrdFfsWcacheFbufs[fd].len = 0;
140  // "flag & O_RDONLY" is not equivalant to ! (flags & O_RDWR) && ! (flags & O_WRONLY)
141  if ( ! (flags & O_RDWR) &&
142  ! (flags & O_WRONLY) &&
143  (flags & O_DIRECT) ) // Limit the usage scenario of the read cache
144  {
145  XrdFfsWcacheFbufs[fd].buf = (char*)malloc(XrdFfsRcacheBufsize);
147  }
148  else
149  {
150  XrdFfsWcacheFbufs[fd].buf = (char*)malloc(XrdFfsWcacheBufsize);
152  }
153  if (XrdFfsWcacheFbufs[fd].buf == NULL)
154  {
155  errno = ENOMEM;
156  return 0;
157  }
158  XrdFfsWcacheFbufs[fd].mlock = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
159  if (XrdFfsWcacheFbufs[fd].mlock == NULL)
160  {
161  errno = ENOMEM;
162  return 0;
163  }
164  errno = pthread_mutex_init(XrdFfsWcacheFbufs[fd].mlock, NULL);
165  if (errno)
166  return 0;
167  return 1;
168 }
void XrdFfsWcache_destroy(int fd)
ssize_t XrdFfsWcacheBufsize
Definition: XrdFfsWcache.cc:70
#define O_DIRECT
Definition: XrdFfsWcache.cc:62
pthread_mutex_t * mlock
Definition: XrdFfsWcache.cc:77
ssize_t XrdFfsRcacheBufsize
Definition: XrdFfsWcache.cc:69
int XrdFfsPosix_baseFD
Definition: XrdFfsWcache.cc:84
struct XrdFfsWcacheFilebuf * XrdFfsWcacheFbufs
Definition: XrdFfsWcache.cc:80

References XrdFfsWcacheFilebuf::buf, XrdFfsWcacheFilebuf::bufsize, XrdFfsWcacheFilebuf::len, XrdFfsWcacheFilebuf::mlock, O_DIRECT, XrdFfsWcacheFilebuf::offset, XrdFfsPosix_baseFD, XrdFfsRcacheBufsize, XrdFfsWcache_destroy(), XrdFfsWcacheBufsize, and XrdFfsWcacheFbufs.

+ Here is the call graph for this function:

◆ XrdFfsWcache_destroy()

void XrdFfsWcache_destroy ( int  fd)

Definition at line 170 of file XrdFfsWcache.cc.

171 {
172 /* XrdFfsWcache_flush(fd); */
173  fd -= XrdFfsPosix_baseFD;
174 
175  XrdFfsWcacheFbufs[fd].offset = 0;
176  XrdFfsWcacheFbufs[fd].len = 0;
177  if (XrdFfsWcacheFbufs[fd].buf != NULL)
178  free(XrdFfsWcacheFbufs[fd].buf);
179  XrdFfsWcacheFbufs[fd].buf = NULL;
180  if (XrdFfsWcacheFbufs[fd].mlock != NULL)
181  {
182  pthread_mutex_destroy(XrdFfsWcacheFbufs[fd].mlock);
183  free(XrdFfsWcacheFbufs[fd].mlock);
184  }
185  XrdFfsWcacheFbufs[fd].mlock = NULL;
186 }

References XrdFfsWcacheFilebuf::buf, XrdFfsWcacheFilebuf::len, XrdFfsWcacheFilebuf::mlock, XrdFfsWcacheFilebuf::offset, XrdFfsPosix_baseFD, and XrdFfsWcacheFbufs.

Referenced by XrdFfsWcache_create().

+ Here is the caller graph for this function:

◆ XrdFfsWcache_flush()

ssize_t XrdFfsWcache_flush ( int  fd)

Definition at line 188 of file XrdFfsWcache.cc.

189 {
190  ssize_t rc;
191  fd -= XrdFfsPosix_baseFD;
192 
193  if (XrdFfsWcacheFbufs[fd].len == 0 || XrdFfsWcacheFbufs[fd].buf == NULL )
194  return 0;
195 
197  XrdFfsWcacheFbufs[fd].buf, XrdFfsWcacheFbufs[fd].len, XrdFfsWcacheFbufs[fd].offset);
198  if (rc > 0)
199  {
200  XrdFfsWcacheFbufs[fd].offset = 0;
201  XrdFfsWcacheFbufs[fd].len = 0;
202  }
203  return rc;
204 }
ssize_t XrdFfsPosix_pwrite(int fildes, const void *buf, size_t nbyte, off_t offset)
Definition: XrdFfsPosix.cc:152

References XrdFfsWcacheFilebuf::buf, XrdFfsWcacheFilebuf::len, XrdFfsWcacheFilebuf::offset, XrdFfsPosix_baseFD, XrdFfsPosix_pwrite(), and XrdFfsWcacheFbufs.

Referenced by XrdFfsWcache_pwrite().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ XrdFfsWcache_init()

void XrdFfsWcache_init ( int  basefd,
int  maxfd 
)

Definition at line 85 of file XrdFfsWcache.cc.

86 {
87  int fd;
88 /* We are now using virtual file descriptors (from Xrootd Posix interface) in XrdFfsXrootdfs.cc so we need to set
89  * base (lowest) file descriptor, and max number of file descriptors..
90  *
91  struct rlimit rlp;
92 
93  getrlimit(RLIMIT_NOFILE, &rlp);
94  XrdFfsWcacheNFILES = rlp.rlim_cur;
95  XrdFfsWcacheNFILES = (XrdFfsWcacheNFILES == (int)RLIM_INFINITY? 4096 : XrdFfsWcacheNFILES);
96  */
97 
98  XrdFfsPosix_baseFD = basefd;
99  XrdFfsWcacheNFILES = maxfd;
100 
101 /* printf("%d %d\n", XrdFfsWcacheNFILES, sizeof(struct XrdFfsWcacheFilebuf)); */
103  for (fd = 0; fd < XrdFfsWcacheNFILES; fd++)
104  {
105  XrdFfsWcacheFbufs[fd].offset = 0;
106  XrdFfsWcacheFbufs[fd].len = 0;
107  XrdFfsWcacheFbufs[fd].buf = NULL;
108  XrdFfsWcacheFbufs[fd].mlock = NULL;
109  }
110  if (!getenv("XRDCL_EC"))
111  {
112  XrdFfsRcacheBufsize = 1024 * 128;
113  }
114  else
115  {
116  char *savptr;
117  int nbdat = atoi(strtok_r(getenv("XRDCL_EC"), ",", &savptr));
118  strtok_r(NULL, ",", &savptr);
119  int chsz = atoi(strtok_r(NULL, ",", &savptr));
120  XrdFfsRcacheBufsize = nbdat * chsz;
121  }
122  if (getenv("XROOTDFS_WCACHESZ"))
123  XrdFfsRcacheBufsize = atoi(getenv("XROOTDFS_WCACHESZ"));
124 }
int XrdFfsWcacheNFILES
Definition: XrdFfsWcache.cc:84

References XrdFfsWcacheFilebuf::buf, XrdFfsWcacheFilebuf::len, XrdFfsWcacheFilebuf::mlock, XrdFfsWcacheFilebuf::offset, XrdFfsPosix_baseFD, XrdFfsRcacheBufsize, XrdFfsWcacheFbufs, and XrdFfsWcacheNFILES.

◆ XrdFfsWcache_pread()

ssize_t XrdFfsWcache_pread ( int  fd,
char *  buf,
size_t  len,
off_t  offset 
)

Definition at line 230 of file XrdFfsWcache.cc.

231 {
232  ssize_t rc;
233  fd -= XrdFfsPosix_baseFD;
234  if (fd < 0)
235  {
236  errno = EBADF;
237  return -1;
238  }
239 
240  char *bufptr;
241  size_t bufsize = XrdFfsWcacheFbufs[fd].bufsize;
242 
243  pthread_mutex_lock(XrdFfsWcacheFbufs[fd].mlock);
244 
245  // identity which block to cache
246  if (XrdFfsWcacheFbufs[fd].len == 0 ||
247  (offset / bufsize != XrdFfsWcacheFbufs[fd].offset / bufsize))
248  {
249  XrdFfsWcacheFbufs[fd].offset = (offset / bufsize) * bufsize;
251  XrdFfsWcacheFbufs[fd].buf,
252  bufsize,
253  XrdFfsWcacheFbufs[fd].offset);
254  } // when XrdFfsWcacheFbufs[fd].len < bufsize, the block is partially cached.
255 
256 
257  // fetch data from the cache, up to the block's upper boundary.
258  if (XrdFfsWcacheFbufs[fd].offset <= offset &&
259  offset < XrdFfsWcacheFbufs[fd].offset + (off_t)XrdFfsWcacheFbufs[fd].len)
260  { // read from cache,
261 //----------------------------------------------------------
262 // FUSE doesn't like this block of the code, unless direct_io is enabled, or
263 // O_DIRECT flags is used. Otherwise, FUSES will stop reading prematurely
264 // when two processes read the same file at the same time.
265  bufptr = &XrdFfsWcacheFbufs[fd].buf[offset - XrdFfsWcacheFbufs[fd].offset];
266  rc = (len < XrdFfsWcacheFbufs[fd].len - (offset - XrdFfsWcacheFbufs[fd].offset))?
267  len : XrdFfsWcacheFbufs[fd].len - (offset - XrdFfsWcacheFbufs[fd].offset);
268  memcpy(buf, bufptr, rc);
269 //----------------------------------------------------------
270  }
271  else
272  { // offset fall into the uncached part of the partically cached block
273  rc = XrdFfsPosix_pread(fd + XrdFfsPosix_baseFD, buf, len, offset);
274  }
275  pthread_mutex_unlock(XrdFfsWcacheFbufs[fd].mlock);
276 /*
277  // prefetch the next block
278  if ( (offset + rc) ==
279  (XrdFfsWcacheFbufs[fd].offset + bufsize) )
280  {
281  pthread_t thread;
282  pthread_attr_t attr;
283  //size_t stacksize = 4*1024*1024;
284 
285  pthread_attr_init(&attr);
286  //pthread_attr_setstacksize(&attr, stacksize);
287  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
288 
289  struct fd_n_offset nextblock(fd, (offset + bufsize));
290  if (! pthread_create(&thread, &attr, XrdFfsWcache_updateReadCache, &nextblock))
291  pthread_detach(thread);
292  pthread_attr_destroy(&attr);
293  }
294 */
295  return rc;
296 }
ssize_t XrdFfsPosix_pread(int fildes, void *buf, size_t nbyte, off_t offset)
Definition: XrdFfsPosix.cc:142

References XrdFfsWcacheFilebuf::buf, XrdFfsWcacheFilebuf::bufsize, XrdFfsWcacheFilebuf::len, XrdFfsWcacheFilebuf::mlock, XrdFfsWcacheFilebuf::offset, XrdFfsPosix_baseFD, XrdFfsPosix_pread(), and XrdFfsWcacheFbufs.

+ Here is the call graph for this function:

◆ XrdFfsWcache_pwrite()

ssize_t XrdFfsWcache_pwrite ( int  fd,
char *  buf,
size_t  len,
off_t  offset 
)

Definition at line 298 of file XrdFfsWcache.cc.

299 {
300  ssize_t rc;
301  char *bufptr;
302  fd -= XrdFfsPosix_baseFD;
303  if (fd < 0)
304  {
305  errno = EBADF;
306  return -1;
307  }
308 
309 /* do not use caching under these cases */
310  if (len > (size_t)(XrdFfsWcacheBufsize/2) || fd >= XrdFfsWcacheNFILES)
311  {
312  rc = XrdFfsPosix_pwrite(fd + XrdFfsPosix_baseFD, buf, len, offset);
313  return rc;
314  }
315 
316  pthread_mutex_lock(XrdFfsWcacheFbufs[fd].mlock);
317  rc = XrdFfsWcacheFbufs[fd].len;
318 /*
319  in the following two cases, a XrdFfsWcache_flush is required:
320  1. current offset isnn't pointing to the tail of data in buffer
321  2. adding new data will exceed the current buffer
322 */
323  if (offset != (off_t)(XrdFfsWcacheFbufs[fd].offset + XrdFfsWcacheFbufs[fd].len) ||
324  (off_t)(offset + len) > (XrdFfsWcacheFbufs[fd].offset + XrdFfsWcacheBufsize))
326 
327  errno = 0;
328  if (rc < 0)
329  {
330  errno = ENOSPC;
331  pthread_mutex_unlock(XrdFfsWcacheFbufs[fd].mlock);
332  return -1;
333  }
334 
335  bufptr = &XrdFfsWcacheFbufs[fd].buf[XrdFfsWcacheFbufs[fd].len];
336  memcpy(bufptr, buf, len);
337  if (XrdFfsWcacheFbufs[fd].len == 0)
338  XrdFfsWcacheFbufs[fd].offset = offset;
339  XrdFfsWcacheFbufs[fd].len += len;
340 
341  pthread_mutex_unlock(XrdFfsWcacheFbufs[fd].mlock);
342  return (ssize_t)len;
343 }
ssize_t XrdFfsWcache_flush(int fd)

References XrdFfsWcacheFilebuf::buf, XrdFfsWcacheFilebuf::len, XrdFfsWcacheFilebuf::mlock, XrdFfsWcacheFilebuf::offset, XrdFfsPosix_baseFD, XrdFfsPosix_pwrite(), XrdFfsWcache_flush(), XrdFfsWcacheBufsize, XrdFfsWcacheFbufs, and XrdFfsWcacheNFILES.

+ Here is the call graph for this function: