XRootD
XrdOssCsiTagstoreFile.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d O s s C s i T a g s t o r e F i l e . c c */
4 /* */
5 /* (C) Copyright 2020 CERN. */
6 /* */
7 /* This file is part of the XRootD software suite. */
8 /* */
9 /* XRootD is free software: you can redistribute it and/or modify it under */
10 /* the terms of the GNU Lesser General Public License as published by the */
11 /* Free Software Foundation, either version 3 of the License, or (at your */
12 /* option) any later version. */
13 /* */
14 /* In applying this licence, CERN does not waive the privileges and */
15 /* immunities granted to it by virtue of its status as an Intergovernmental */
16 /* Organization or submit itself to any jurisdiction. */
17 /* */
18 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
19 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
20 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
21 /* License for more details. */
22 /* */
23 /* You should have received a copy of the GNU Lesser General Public License */
24 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
25 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
26 /* */
27 /* The copyright holder's institutional names and contributor's names may not */
28 /* be used to endorse or promote products derived from this software without */
29 /* specific prior written permission of the institution or contributor. */
30 /******************************************************************************/
31 
32 #include "XrdOssCsiTrace.hh"
33 #include "XrdOssCsiTagstoreFile.hh"
34 
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <unistd.h>
38 
40 
41 int XrdOssCsiTagstoreFile::Open(const char *path, const off_t dsize, const int Oflag, XrdOucEnv &Env)
42 {
43  EPNAME("TagstoreFile::Open");
44 
45  const int ret = fd_->Open(path, Oflag, 0666, Env);
46  if (ret<0)
47  {
48  return ret;
49  }
50  isOpen = true;
51 
52  struct guard_s
53  {
54  guard_s(XrdOssDF *fd, bool &isopen) : fd_(fd), isopen_(isopen) { }
55  ~guard_s() { if (fd_) { fd_->Close(); isopen_ = false; } }
56  void disarm() { fd_ = NULL; }
57 
58  XrdOssDF *fd_;
59  bool &isopen_;
60  } fdguard(fd_.get(),isOpen);
61 
62  const static int little = 1;
63  if (*(char const *)&little)
64  {
65  machineIsBige_ = false;
66  }
67  else
68  {
69  machineIsBige_ = true;
70  }
71 
72  uint32_t magic;
73 
74  const ssize_t mread = XrdOssCsiTagstoreFile::fullread(*fd_, header_, 0, 20);
75  bool mok = false;
76  if (mread >= 0)
77  {
78  memcpy(&magic, header_, 4);
79  if (magic == cmagic_)
80  {
81  fileIsBige_ = machineIsBige_;
82  mok = true;
83  }
84  else if (magic == bswap_32(cmagic_))
85  {
86  fileIsBige_ = !machineIsBige_;
87  mok = true;
88  }
89  }
90 
91  if (!mok)
92  {
93  fileIsBige_ = machineIsBige_;
94  hflags_ = (dsize==0) ? XrdOssCsiTagstore::csVer : 0;
95  trackinglen_ = 0;
96  const int stret = MarshallAndWriteHeader();
97  if (stret<0) return stret;
98  }
99  else
100  {
101  memcpy(&trackinglen_, &header_[4], 8);
102  if (fileIsBige_ != machineIsBige_)
103  {
104  trackinglen_ = bswap_64(trackinglen_);
105  }
106  memcpy(&hflags_,&header_[12], 4);
107  if (fileIsBige_ != machineIsBige_)
108  {
109  hflags_ = bswap_32(hflags_);
110  }
111  const uint32_t cv = XrdOucCRC::Calc32C(header_, 16, 0U);
112  uint32_t rv;
113  memcpy(&rv, &header_[16], 4);
114  if (fileIsBige_ != machineIsBige_) rv = bswap_32(rv);
115  if (rv != cv)
116  {
117  return -EDOM;
118  }
119  }
120 
121  if (trackinglen_ != dsize)
122  {
123  TRACE(Warn, "Tagfile disagrees with actual filelength for " << fn_ << " expected " << trackinglen_ << " actual " << dsize);
124  }
125 
126  const int rsret = ResetSizes(dsize);
127  if (rsret<0) return rsret;
128 
129  fdguard.disarm();
130  return 0;
131 }
132 
134 {
135  EPNAME("ResetSizes");
136  if (!isOpen) return -EBADF;
137  actualsize_ = size;
138  struct stat sb;
139  const int ssret = fd_->Fstat(&sb);
140  if (ssret<0) return ssret;
141  const off_t expected_tagfile_size = 20LL + 4*((trackinglen_+XrdSys::PageSize-1)/XrdSys::PageSize);
142  // truncate can be relatively slow
143  if (expected_tagfile_size < sb.st_size)
144  {
145  TRACE(Warn, "Truncating tagfile to " << expected_tagfile_size <<
146  ", from current size " << sb.st_size << " for " << fn_);
147  const int tret = fd_->Ftruncate(expected_tagfile_size);
148  if (tret<0) return tret;
149  }
150  else if (expected_tagfile_size > sb.st_size)
151  {
152  off_t nb = 0;
153  if (sb.st_size>20) nb = (sb.st_size - 20)/4;
154  TRACE(Warn, "Reducing tracked size to " << (nb*XrdSys::PageSize) <<
155  " instead of " << trackinglen_ << ", because of short tagfile for " << fn_);
156  const int stret = WriteTrackedTagSize(nb*XrdSys::PageSize);
157  if (stret<0) return stret;
158  const int tret = fd_->Ftruncate(20LL + 4*nb);
159  if (tret<0) return tret;
160  }
161  return 0;
162 }
163 
165 {
166  if (!isOpen) return -EBADF;
167  return fd_->Fsync();
168 }
169 
171 {
172  if (!isOpen) return;
173  fd_->Flush();
174 }
175 
177 {
178  if (!isOpen) return -EBADF;
179  isOpen = false;
180  return fd_->Close();
181 }
182 
183 ssize_t XrdOssCsiTagstoreFile::WriteTags(const uint32_t *const buf, const off_t off, const size_t n)
184 {
185  if (!isOpen) return -EBADF;
186  if (machineIsBige_ != fileIsBige_) return WriteTags_swap(buf, off, n);
187 
188  const ssize_t nwritten = XrdOssCsiTagstoreFile::fullwrite(*fd_, buf, 20LL+4*off, 4*n);
189  if (nwritten<0) return nwritten;
190  return nwritten/4;
191 }
192 
193 ssize_t XrdOssCsiTagstoreFile::ReadTags(uint32_t *const buf, const off_t off, const size_t n)
194 {
195  if (!isOpen) return -EBADF;
196  if (machineIsBige_ != fileIsBige_) return ReadTags_swap(buf, off, n);
197 
198  const ssize_t nread = XrdOssCsiTagstoreFile::fullread(*fd_, buf, 20LL+4*off, 4*n);
199  if (nread<0) return nread;
200  return nread/4;
201 }
202 
203 int XrdOssCsiTagstoreFile::Truncate(const off_t size, bool datatoo)
204 {
205  if (!isOpen)
206  {
207  return -EBADF;
208  }
209 
210  // set tag file to correct length for value of size
211  const off_t expected_tagfile_size = 20LL + 4*((size+XrdSys::PageSize-1)/XrdSys::PageSize);
212  const int tret = fd_->Ftruncate(expected_tagfile_size);
213 
214  // if failed to set the tagfile length return error before updating header
215  if (tret != XrdOssOK) return tret;
216 
217  // truncating down to zero, so reset to content verified
218  if (datatoo && size==0) hflags_ |= XrdOssCsiTagstore::csVer;
219 
220  int wtt = WriteTrackedTagSize(size);
221  if (wtt<0) return wtt;
222 
223  if (datatoo) actualsize_ = size;
224  return 0;
225 }
226 
227 ssize_t XrdOssCsiTagstoreFile::WriteTags_swap(const uint32_t *const buf, const off_t off, const size_t n)
228 {
229  uint32_t b[1024];
230  const size_t bsz = sizeof(b)/sizeof(uint32_t);
231  size_t towrite = n;
232  size_t nwritten = 0;
233  while(towrite>0)
234  {
235  const size_t bs = std::min(towrite, bsz);
236  for(size_t i=0;i<bs;i++)
237  {
238  b[i] = bswap_32(buf[i+nwritten]);
239  }
240  const ssize_t wret = XrdOssCsiTagstoreFile::fullwrite(*fd_, b, 20LL+4*(nwritten+off), 4*bs);
241  if (wret<0) return wret;
242  towrite -= wret/4;
243  nwritten += wret/4;
244  }
245  return n;
246 }
247 
248 ssize_t XrdOssCsiTagstoreFile::ReadTags_swap(uint32_t *const buf, const off_t off, const size_t n)
249 {
250  uint32_t b[1024];
251  const size_t bsz = sizeof(b)/sizeof(uint32_t);
252  size_t toread = n;
253  size_t nread = 0;
254  while(toread>0)
255  {
256  const size_t bs = std::min(toread, bsz);
257  const ssize_t rret = XrdOssCsiTagstoreFile::fullread(*fd_, b, 20LL+4*(nread+off), 4*bs);
258  if (rret<0) return rret;
259  for(size_t i=0;i<bs;i++)
260  {
261  buf[i+nread] = bswap_32(b[i]);
262  }
263  toread -= rret/4;
264  nread += rret/4;
265  }
266  return n;
267 }
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
XrdOucTrace OssCsiTrace
#define XrdOssOK
Definition: XrdOss.hh:50
int stat(const char *path, struct stat *buf)
#define TRACE(act, x)
Definition: XrdTrace.hh:63
virtual int Truncate(off_t, bool)
virtual int ResetSizes(const off_t size)
virtual ssize_t ReadTags(uint32_t *, off_t, size_t)
virtual ssize_t WriteTags(const uint32_t *, off_t, size_t)
static ssize_t fullread(XrdOssDF &fd, void *buff, const off_t off, const size_t sz)
virtual int Open(const char *, off_t, int, XrdOucEnv &)
static ssize_t fullwrite(XrdOssDF &fd, const void *buff, const off_t off, const size_t sz)
static const uint32_t csVer
static uint32_t Calc32C(const void *data, size_t count, uint32_t prevcs=0)
Definition: XrdOucCRC.cc:190
static const int PageSize