ewmscp  ..
outputHandlerDavix.cpp
Go to the documentation of this file.
1 #include "OptionsChrono.h"
2 #include "ewmscp.h"
3 #include "block.h"
4 #include "copyRequestTypes.h"
5 #include "outputHandlerDavix.h"
6 #include "throwcall.h"
7 #include "errMsgQueue.h"
8 #include <libgen.h>
9 
10 namespace outputHandler {
11  decltype(davix::factory) davix::factory("davix");
12  std::unique_ptr<base::writer> davix::newWriter(const std::string& path,
13  bool /*mightAppend*/,
14  size_t /*sourceSize*/,
15  size_t /*readBlockSize*/,
17  bool noWrite,
18  std::unique_ptr<ioHandle::attrDataType>,
19  std::unique_ptr<acl::list>) {
20  return std::unique_ptr<base::writer>(new writerDavix(*this, path,
21  state, noWrite));
22  }
23 
24 
25  static davixConfigObject outputConfig("davixOut");
26 
27 
28 
31  };
32 
33 
34 
35  void davix::ensureParentDirs(const std::string& path,
36  const std::string& srcPath,
37  inputHandler::base* InputHandler) {
38  std::vector<std::remove_reference<decltype(path)>::type::value_type> disposable_buffer(path.c_str(), path.c_str() + path.size() + 1);
39  std::string dir(dirname(disposable_buffer.data()));
40  struct stat statbuf;
41  errorReport report(__func__, "stat", dir);
42  if (posix.stat(&params, dir, &statbuf, report) != 0) {
43  if (report->getStatus() == Davix::StatusCode::FileNotFound) {
44  ensureParentDirs(dir, srcPath, InputHandler);
45  errorReport report2(__func__, "mkdir", dir);
46  if (posix.mkdir(&params, dir, 0777u, report2) != 0) {
47  if (report2->getStatus() == Davix::StatusCode::FileExist) {
48  return; // we lost a race with another copy process...
49  }
50  report2.throwUp();
51  }
52  } else {
53  report.throwUp();
54  }
55  } else if (! S_ISDIR(statbuf.st_mode)) {
57  dir, "ensure parents",
58  "is not a directory (st_mode is ", statbuf.st_mode, ") but should be");
59  }
60  }
61 
62 
63  void davix::remove(const std::string& path, copyRequest::stateType& state) {
64  struct stat dsttat;
65  {
66  errorReport report(__func__, "stat", path);
67  if (posix.stat(&params, path, &dsttat, report) != 0) {
68  if (report->getStatus() == Davix::StatusCode::FileNotFound) {
70  return;
71  }
72  report.throwUp();
73  }
74  }
75  if (S_ISDIR(dsttat.st_mode)) {
76  errorReport report(__func__, "rmdir", path);
77  if (posix.rmdir(nullptr, path, report) != 0) {
78  if (report->getStatus() == Davix::StatusCode::FileNotFound) {
80  return;
81  } else if (report->getStatus() == Davix::StatusCode::FileExist) {
83  return;
84  } else {
85  report.throwUp();
86  }
87  } else {
89  return;
90  }
91  } else {
92  errorReport report(__func__, "unlink", path);
93  if (posix.unlink(&params, path, report) != 0) {
94  if (report->getStatus() == Davix::StatusCode::FileNotFound) {
96  return;
97  }
98  report.throwUp();
99  }
101  }
102  }
103 
104 
105  bool davix::renameSimple(const std::string& fromPath,
106  const std::string& toPath) {
107  {
108  // rename chokes when target already exists, so remove it beforehand
109  errorReport report(__func__, "unlink", toPath);
110  if (posix.unlink(&params, toPath, report) != 0) {
111  if (report->getStatus() != Davix::StatusCode::FileNotFound) {
112  report.throwUp();
113  }
114  }
115  }
116  {
117  errorReport report(__func__, "rename", fromPath);
118  if (posix.rename(&params, fromPath, toPath, report)) {
119  if (report->getStatus() == Davix::StatusCode::FileNotFound) {
120  return false;
121  }
122  report.throwUp();
123  }
124  }
125  return true;
126  }
127 
128  base::renameRetvalType davix::rename(const std::string& /*fromPath*/,
129  const std::unique_ptr<const genericStat>& /*readInitialStat*/,
130  const std::string& /*toPath*/,
131  copyRequest::stateType& /*state*/) {
132  // we cannot be sure that the fromPath is up to date, always do a new copy
134  }
135 
136 
138  const std::string& aPath,
139  copyRequest::stateType &state,
140  bool noWrite):
141  davixIoCommon(aPath, aHandler) {
142  if (noWrite) {
143  fd = nullptr;
144  } else {
145  auto openMode = O_CREAT | O_WRONLY;
146  state.clear(copyRequest::stateBitType::append); // clear any old append sets, may be left over from former attempts
147  errorReport report(__func__, "open", path);
148  fd = handler.posix.open(&handler.params, path.c_str(), openMode, report);
149  if (fd == nullptr) {
150  report.throwUp();
151  }
152  }
153  };
155  errorReport report(__func__, "close", path);
156  if (handler.posix.close(fd, report) != 0) {
158  path, "close during unwind ",
159  report.getMessage());
160  }
161  errorReport report2(__func__, "unlink", path);
163  path, "unlink failed copy", "due to exception");
164  if (handler.posix.unlink(&handler.params, path, report) != 0) {
165  report2.throwUp();
166  }
167  };
169  if (fd != nullptr) {
170  if (isUnwinding()) {
171  closeAndRemoveBadCopy();
172  return;
173  }
174  errorReport report(__func__, "close", path);
175  if (handler.posix.close(fd, report) != 0) {
176  report.throwUp();
177  }
178  }
179  };
180 
181 
183  size_t bytes_writen_so_far = 0;
184 
185  while (bytes_writen_so_far < b.size()) {
187  auto count = b.size() - bytes_writen_so_far;
188 
189  if (b.isHole()) { // just write zeroes
190  count = std::min({count, blockSize, block::nullBufferSize()});
191  } else {
192  count = std::min(count, blockSize);
193  }
194  errorReport report(__func__, "write", path);
195  auto bytes_writen = handler.posix.write(fd, b.bufferAt(bytes_writen_so_far), count, report);
196  if (bytes_writen < 0) {
197  report.throwUp();
198  }
199 
200  writeRateLimit.update(bytes_writen);
201  bytes_writen_so_far += bytes_writen;
202  }
203  }
204 
205 
206 
208  // not supportted
209  }
210 
212  throw std::runtime_error("sync not supported");
213  }
214 }; // end namespace outputHandler
outputHandler::davix
Definition: outputHandlerDavix.h:8
block.h
outputHandler::outputConfig
static davixConfigObject outputConfig("davixOut")
outputHandler::davix::renameSimple
bool renameSimple(const std::string &fromPath, const std::string &toPath) override
Definition: outputHandlerDavix.cpp:105
errMsgQueue.h
outputHandler::davix::newWriter
std::unique_ptr< writer > newWriter(const std::string &path, bool mightAppend, size_t sourceSize, size_t readBlockSize, copyRequest::stateType &state, bool noWrite, std::unique_ptr< ioHandle::attrDataType > aAttrData, std::unique_ptr< acl::list > aAclData) override
Definition: outputHandlerDavix.cpp:12
errMsg::location
class for defining the location of a error message in the source code.
Definition: errMsgQueue.h:14
davixIoCommon::fd
DAVIX_FD * fd
Definition: davixCommon.h:228
genericStat
generic stat abstraction class Used to abstract the variants of the stat structure.
Definition: genericStat.h:12
copyRequestTypes.h
davixCommon
Definition: davixCommon.h:193
errMsg::level::info
@ info
outputHandler::davix::writerDavix
Definition: outputHandlerDavix.h:13
outputHandler::davix::writerDavix::writerDavix
writerDavix(davix &aHandler, const std::string &aPath, copyRequest::stateType &state, bool noWrite)
Definition: outputHandlerDavix.cpp:137
copyRequest::stateBitType::done
@ done
outputHandler::base::renameRetvalType::fileChanged
@ fileChanged
copyRequest::stateBitType::failed
@ failed
outputHandler
Definition: ioHandle.h:9
copyRequest::stateBitType::vanished
@ vanished
copyRequest::stateType
Definition: copyRequestTypes.h:66
block::isHole
bool isHole() const
Definition: block.h:36
errMsg::level::debug
@ debug
outputHandler::davix::writerDavix::doAttributePreservations
void doAttributePreservations(const genericStat &readInitialStat) override
Definition: outputHandlerDavix.cpp:207
outputHandler::davix::davix
davix()
Definition: outputHandlerDavix.cpp:29
outputHandlerDavix.h
outputHandler::davix::writerDavix::closeAndRemoveBadCopy
void closeAndRemoveBadCopy() override
Definition: outputHandlerDavix.cpp:154
OptionsChrono.h
block::bufferAt
void * bufferAt(size_t offset)
only way to access the data in the block
Definition: block.cpp:28
errorReport
class for easy error handling with davix ensures proper cleanup of the error report when going out of...
Definition: davixCommon.h:12
davixIoCommon
Definition: davixCommon.h:224
davixIoCommon::handler
davixCommon & handler
Definition: davixCommon.h:227
outputHandler::base::renameRetvalType
renameRetvalType
Definition: outputHandler.h:106
throwcall.h
block
data block, used to hold the data that are being copied (or checksummed).
Definition: block.h:7
outputHandler::davix::writerDavix::sync
void sync() override
Definition: outputHandlerDavix.cpp:211
davixCommon::posix
Davix::DavPosix posix
Definition: davixCommon.h:198
outputHandler::davix::writerDavix::writeBlock
void writeBlock(const block &b) override
Definition: outputHandlerDavix.cpp:182
block::nullBufferSize
static size_t nullBufferSize()
Definition: block.cpp:34
inputHandler::base
class for handling input This is the (abstract) base class for handling input, both reading a file vi...
Definition: inputHandler.h:35
throttle::watch::wait
void wait()
Definition: throttle.h:50
outputHandler::davix::remove
void remove(const std::string &path, copyRequest::stateType &state) override
Definition: outputHandlerDavix.cpp:63
outputHandler::davix::factory
static factoryTemplate< davix > factory
Definition: outputHandlerDavix.h:9
errMsg::emit
void emit(level aLogLevel, const location &loc, const std::string &aObject, const std::string &aAction, const Args &... args)
function to create and enqueue a message, this is the only way that messages should be created!
Definition: errMsgQueue.h:148
block::size
size_t size() const
Definition: block.h:16
writeRateLimit
throttle::watch writeRateLimit
outputHandler::davix::writerDavix::~writerDavix
~writerDavix() noexcept(false) override
Definition: outputHandlerDavix.cpp:168
enumAsBitmask::clear
void clear(const T aBits)
Definition: enumAsBitmask.h:31
davixCommon::params
Davix::RequestParams params
Definition: davixCommon.h:197
outputHandler::davix::rename
base::renameRetvalType rename(const std::string &fromPath, const std::unique_ptr< const genericStat > &readInitialStat, const std::string &toPath, copyRequest::stateType &state) override
Definition: outputHandlerDavix.cpp:128
errorReport::getMessage
const std::string & getMessage() const
Definition: davixCommon.h:37
throttle::watch::update
void update(double units=1.0)
Definition: throttle.h:35
davixConfigObject
class for configuring one davix instance holds all options necessary for that
Definition: davixCommon.h:169
ewmscp.h
davixIoCommon::path
const std::string & path
Definition: davixCommon.h:226
copyRequest::stateBitType::append
@ append
errorReport::throwUp
void throwUp()
Definition: davixCommon.h:45
outputHandler::davix::ensureParentDirs
void ensureParentDirs(const std::string &path, const std::string &srcPath, inputHandler::base *InputHandler) override
Definition: outputHandlerDavix.cpp:35