blob: 87a14fd14b9f33fa0be27d259435950388cef5fc [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/ledger/bin/storage/impl/object_impl.h"
#include <lib/fsl/vmo/strings.h>
#include <utility>
#include "src/ledger/bin/storage/impl/object_digest.h"
#include "src/ledger/bin/storage/public/data_source.h"
#include "src/ledger/bin/storage/public/types.h"
namespace storage {
namespace {
uint64_t ToFullPages(uint64_t value) {
return (value + PAGE_SIZE - 1) & (~(PAGE_SIZE - 1));
}
} // namespace
InlinePiece::InlinePiece(ObjectIdentifier identifier)
: identifier_(std::move(identifier)) {}
fxl::StringView InlinePiece::GetData() const {
return ExtractObjectDigestData(identifier_.object_digest());
}
ObjectIdentifier InlinePiece::GetIdentifier() const { return identifier_; }
DataChunkPiece::DataChunkPiece(ObjectIdentifier identifier,
std::unique_ptr<DataSource::DataChunk> chunk)
: identifier_(std::move(identifier)), chunk_(std::move(chunk)) {}
fxl::StringView DataChunkPiece::GetData() const { return chunk_->Get(); }
ObjectIdentifier DataChunkPiece::GetIdentifier() const { return identifier_; }
LevelDBPiece::LevelDBPiece(ObjectIdentifier identifier,
std::unique_ptr<leveldb::Iterator> iterator)
: identifier_(std::move(identifier)), iterator_(std::move(iterator)) {}
fxl::StringView LevelDBPiece::GetData() const {
return convert::ExtendedStringView(iterator_->value());
}
ObjectIdentifier LevelDBPiece::GetIdentifier() const { return identifier_; }
ChunkObject::ChunkObject(std::unique_ptr<const Piece> piece)
: piece_(std::move(piece)) {
FXL_DCHECK(
GetObjectDigestInfo(piece_->GetIdentifier().object_digest()).is_chunk())
<< "INDEX piece " << piece_->GetIdentifier()
<< " cannot be used as an object.";
}
ObjectIdentifier ChunkObject::GetIdentifier() const {
return piece_->GetIdentifier();
}
Status ChunkObject::GetData(fxl::StringView* data) const {
*data = piece_->GetData();
return Status::OK;
}
VmoObject::VmoObject(ObjectIdentifier identifier, fsl::SizedVmo vmo)
: identifier_(std::move(identifier)), vmo_(std::move(vmo)) {}
VmoObject::~VmoObject() {
if (vmar_) {
vmar_.destroy();
}
}
ObjectIdentifier VmoObject::GetIdentifier() const { return identifier_; }
Status VmoObject::GetData(fxl::StringView* data) const {
Status status = Initialize();
if (status != Status::OK) {
return status;
}
*data = data_;
return Status::OK;
}
Status VmoObject::GetVmo(fsl::SizedVmo* vmo) const {
zx_status_t zx_status =
vmo_.Duplicate(ZX_RIGHTS_BASIC | ZX_RIGHT_READ | ZX_RIGHT_MAP, vmo);
if (zx_status != ZX_OK) {
FXL_LOG(ERROR) << "Unable to duplicate a vmo. Status: " << zx_status;
return Status::INTERNAL_ERROR;
}
return Status::OK;
}
Status VmoObject::Initialize() const {
if (initialized_) {
return Status::OK;
}
uintptr_t allocate_address;
zx_status_t zx_status = zx::vmar::root_self()->allocate(
0, ToFullPages(vmo_.size()),
ZX_VM_CAN_MAP_READ | ZX_VM_CAN_MAP_WRITE | ZX_VM_CAN_MAP_SPECIFIC, &vmar_,
&allocate_address);
if (zx_status != ZX_OK) {
FXL_LOG(ERROR) << "Unable to allocate VMAR. Error: " << zx_status;
return Status::INTERNAL_ERROR;
}
char* mapped_address;
zx_status = vmar_.map(0, vmo_.vmo(), 0, vmo_.size(),
ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_SPECIFIC,
reinterpret_cast<uintptr_t*>(&mapped_address));
if (zx_status != ZX_OK) {
FXL_LOG(ERROR) << "Unable to map VMO. Error: " << zx_status;
vmar_.reset();
return Status::INTERNAL_ERROR;
}
data_ = fxl::StringView(mapped_address, vmo_.size());
initialized_ = true;
return Status::OK;
}
} // namespace storage