sapling/eden/fs/takeover/TakeoverData.cpp
Chad Austin 697eb8a6fd run clang-format across eden
Summary:
```
find . \( -iname '*.cpp' -o -iname '*.h' \) -exec arc lint --apply-patches {} +
```

Differential Revision: D6820436

fbshipit-source-id: 173c0e3b5c023c1c9276f34e17d732f1dd161892
2018-01-26 11:20:31 -08:00

194 lines
6.5 KiB
C++

/*
* Copyright (c) 2004-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
#include "eden/fs/takeover/TakeoverData.h"
#include <folly/Format.h>
#include <folly/io/Cursor.h>
#include <folly/io/IOBuf.h>
#include <thrift/lib/cpp2/protocol/Serializer.h>
using apache::thrift::CompactSerializer;
using folly::IOBuf;
using std::string;
namespace facebook {
namespace eden {
IOBuf TakeoverData::serialize() {
// Compute the body data length
uint64_t bodyLength = sizeof(uint32_t);
for (const auto& mount : mountPoints) {
bodyLength += sizeof(uint32_t) + mount.mountPath.stringPiece().size();
bodyLength += sizeof(uint32_t) + mount.stateDirectory.stringPiece().size();
bodyLength += sizeof(uint32_t);
for (const auto& bindMount : mount.bindMounts) {
bodyLength += sizeof(uint32_t) + bindMount.stringPiece().size();
}
bodyLength += sizeof(fuse_init_out);
// TODO: remove this redundant serialization. We're doing this here
// solely to compute the size of the data. We plan to refactor this
// whole thing to use a single thrift struct; T25009883
auto serializedFileHandleMap =
CompactSerializer::serialize<std::string>(mount.fileHandleMap);
bodyLength += sizeof(uint32_t) + serializedFileHandleMap.size();
auto serializedInodeMap =
CompactSerializer::serialize<std::string>(mount.inodeMap);
bodyLength += sizeof(uint32_t) + serializedInodeMap.size();
}
// Build a buffer with all of the mount paths
auto fullCapacity = kHeaderLength + bodyLength;
IOBuf buf(IOBuf::CREATE, fullCapacity);
folly::io::Appender app(&buf, 0);
// Serialize the message type
app.writeBE<uint32_t>(MessageType::MOUNTS);
// Write the number of mount points
app.writeBE<uint32_t>(mountPoints.size());
// Serialize each mount point
for (const auto& mount : mountPoints) {
// The mount path
const auto& pathStr = mount.mountPath.stringPiece();
app.writeBE<uint32_t>(pathStr.size());
app(pathStr);
// The client configuration dir
const auto& clientStr = mount.stateDirectory.stringPiece();
app.writeBE<uint32_t>(clientStr.size());
app(clientStr);
// Number of bind mounts, followed by the bind mount paths
app.writeBE<uint32_t>(mount.bindMounts.size());
for (const auto& bindMount : mount.bindMounts) {
app.writeBE<uint32_t>(bindMount.stringPiece().size());
app(bindMount.stringPiece());
}
// Stuffing the fuse connection information in as a binary
// blob because we know that the endianness of the target
// machine must match the current system for a graceful
// takeover.
app.push(folly::StringPiece{reinterpret_cast<const char*>(&mount.connInfo),
sizeof(mount.connInfo)});
auto serializedFileHandleMap =
CompactSerializer::serialize<std::string>(mount.fileHandleMap);
app.writeBE<uint32_t>(serializedFileHandleMap.size());
app.push(folly::StringPiece{serializedFileHandleMap});
auto serializedInodeMap =
CompactSerializer::serialize<std::string>(mount.inodeMap);
app.writeBE<uint32_t>(serializedInodeMap.size());
app.push(folly::StringPiece{serializedInodeMap});
}
return buf;
}
folly::IOBuf TakeoverData::serializeError(const folly::exception_wrapper& ew) {
// Compute the body data length
auto exceptionClassName = ew.class_name();
folly::StringPiece what = ew ? ew.get_exception()->what() : "";
uint64_t bodyLength = sizeof(uint32_t) + exceptionClassName.size() +
sizeof(uint32_t) + what.size();
// Allocate the buffer
auto fullCapacity = kHeaderLength + bodyLength;
IOBuf buf(IOBuf::CREATE, fullCapacity);
folly::io::Appender app(&buf, 0);
// Serialize the message type
app.writeBE<uint32_t>(MessageType::ERROR);
// Write the error type and message
app.writeBE<uint32_t>(exceptionClassName.size());
app(exceptionClassName);
app.writeBE<uint32_t>(what.size());
app(what);
return buf;
}
TakeoverData TakeoverData::deserialize(const IOBuf* buf) {
folly::io::Cursor cursor(buf);
auto messageType = cursor.readBE<uint32_t>();
if (messageType != MessageType::ERROR && messageType != MessageType::MOUNTS) {
throw std::runtime_error(
folly::to<string>("unknown takeover data message type ", messageType));
}
// Check the message type
if (messageType == MessageType::ERROR) {
auto errorTypeLength = cursor.readBE<uint32_t>();
auto errorType = cursor.readFixedString(errorTypeLength);
auto errorMessageLength = cursor.readBE<uint32_t>();
auto errorMessage = cursor.readFixedString(errorMessageLength);
throw std::runtime_error(errorType + ": " + errorMessage);
}
if (messageType != MessageType::MOUNTS) {
throw std::runtime_error(
folly::to<string>("unknown takeover data message type ", messageType));
}
TakeoverData data;
auto numMounts = cursor.readBE<uint32_t>();
for (uint32_t mountIdx = 0; mountIdx < numMounts; ++mountIdx) {
auto pathLength = cursor.readBE<uint32_t>();
auto mountPath = cursor.readFixedString(pathLength);
auto clientPathLength = cursor.readBE<uint32_t>();
auto stateDirectory = cursor.readFixedString(clientPathLength);
auto numBindMounts = cursor.readBE<uint32_t>();
std::vector<AbsolutePath> bindMounts;
bindMounts.reserve(numBindMounts);
for (uint32_t bindIdx = 0; bindIdx < numBindMounts; ++bindIdx) {
auto bindPathLength = cursor.readBE<uint32_t>();
auto bindPath = cursor.readFixedString(bindPathLength);
bindMounts.emplace_back(AbsolutePathPiece{bindPath});
}
fuse_init_out connInfo;
cursor.pull(&connInfo, sizeof(connInfo));
auto fileHandleMapLength = cursor.readBE<uint32_t>();
auto fileHandleMapBuffer = cursor.readFixedString(fileHandleMapLength);
auto fileHandleMap =
CompactSerializer::deserialize<SerializedFileHandleMap>(
fileHandleMapBuffer);
auto inodeMapLength = cursor.readBE<uint32_t>();
auto inodeMapBuffer = cursor.readFixedString(inodeMapLength);
auto inodeMap =
CompactSerializer::deserialize<SerializedInodeMap>(inodeMapBuffer);
data.mountPoints.emplace_back(
AbsolutePath{mountPath},
AbsolutePath{stateDirectory},
std::move(bindMounts),
folly::File{},
connInfo,
std::move(fileHandleMap),
std::move(inodeMap));
}
return data;
}
} // namespace eden
} // namespace facebook