proxygen
FileUtilDetail.h
Go to the documentation of this file.
1 /*
2  * Copyright 2013-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <algorithm>
20 #include <cerrno>
21 
24 
29 namespace folly {
30 namespace fileutil_detail {
31 
32 // Wrap call to f(args) in loop to retry on EINTR
33 template <class F, class... Args>
34 ssize_t wrapNoInt(F f, Args... args) {
35  ssize_t r;
36  do {
37  r = f(args...);
38  } while (r == -1 && errno == EINTR);
39  return r;
40 }
41 
42 inline void incr(ssize_t /* n */) {}
43 inline void incr(ssize_t n, off_t& offset) {
44  offset += off_t(n);
45 }
46 
47 // Wrap call to read/pread/write/pwrite(fd, buf, count, offset?) to retry on
48 // incomplete reads / writes. The variadic argument magic is there to support
49 // an additional argument (offset) for pread / pwrite; see the incr() functions
50 // above which do nothing if the offset is not present and increment it if it
51 // is.
52 template <class F, class... Offset>
53 ssize_t wrapFull(F f, int fd, void* buf, size_t count, Offset... offset) {
54  char* b = static_cast<char*>(buf);
55  ssize_t totalBytes = 0;
56  ssize_t r;
57  do {
58  r = f(fd, b, count, offset...);
59  if (r == -1) {
60  if (errno == EINTR) {
61  continue;
62  }
63  return r;
64  }
65 
66  totalBytes += r;
67  b += r;
68  count -= r;
69  incr(r, offset...);
70  } while (r != 0 && count); // 0 means EOF
71 
72  return totalBytes;
73 }
74 
75 // Wrap call to readv/preadv/writev/pwritev(fd, iov, count, offset?) to
76 // retry on incomplete reads / writes.
77 template <class F, class... Offset>
78 ssize_t wrapvFull(F f, int fd, iovec* iov, int count, Offset... offset) {
79  ssize_t totalBytes = 0;
80  ssize_t r;
81  do {
82  r = f(fd, iov, std::min<int>(count, kIovMax), offset...);
83  if (r == -1) {
84  if (errno == EINTR) {
85  continue;
86  }
87  return r;
88  }
89 
90  if (r == 0) {
91  break; // EOF
92  }
93 
94  totalBytes += r;
95  incr(r, offset...);
96  while (r != 0 && count != 0) {
97  if (r >= ssize_t(iov->iov_len)) {
98  r -= ssize_t(iov->iov_len);
99  ++iov;
100  --count;
101  } else {
102  iov->iov_base = static_cast<char*>(iov->iov_base) + r;
103  iov->iov_len -= r;
104  r = 0;
105  }
106  }
107  } while (count);
108 
109  return totalBytes;
110 }
111 
112 } // namespace fileutil_detail
113 } // namespace folly
ssize_t wrapNoInt(F f, Args...args)
auto f
char b
constexpr size_t kIovMax
Definition: SysUio.h:39
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
ssize_t wrapvFull(F f, int fd, iovec *iov, int count, Offset...offset)
ssize_t wrapFull(F f, int fd, void *buf, size_t count, Offset...offset)
int * count