blob: f5624c78509978b1600829f997f72b1592660699 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include "paimon/common/data/blob_descriptor.h"
#include <utility>
#include "fmt/format.h"
#include "paimon/common/io/memory_segment_output_stream.h"
#include "paimon/common/memory/memory_segment_utils.h"
#include "paimon/io/byte_array_input_stream.h"
#include "paimon/io/byte_order.h"
#include "paimon/io/data_input_stream.h"
#include "paimon/memory/bytes.h"
#include "paimon/status.h"
namespace paimon {
Result<std::unique_ptr<BlobDescriptor>> BlobDescriptor::Create(const std::string& uri,
int64_t offset, int64_t length) {
return Create(kCurrentVersion, uri, offset, length);
}
Result<std::unique_ptr<BlobDescriptor>> BlobDescriptor::Create(int8_t version,
const std::string& uri,
int64_t offset, int64_t length) {
if (offset < 0) {
return Status::Invalid(fmt::format("offset {} is less than 0", offset));
}
// length == -1 means it's dynamic length
if (length < -1) {
return Status::Invalid(fmt::format("length {} is less than -1", length));
}
return std::unique_ptr<BlobDescriptor>(new BlobDescriptor(version, uri, offset, length));
}
PAIMON_UNIQUE_PTR<Bytes> BlobDescriptor::Serialize(const std::shared_ptr<MemoryPool>& pool) const {
MemorySegmentOutputStream out(MemorySegmentOutputStream::DEFAULT_SEGMENT_SIZE, pool);
out.SetOrder(ByteOrder::PAIMON_LITTLE_ENDIAN);
out.WriteValue<int8_t>(version_);
out.WriteValue<int64_t>(kMagic);
out.WriteValue<int32_t>(static_cast<int32_t>(uri_.size()));
auto uri_bytes = std::make_shared<Bytes>(uri_, pool.get());
out.WriteBytes(uri_bytes);
out.WriteValue<int64_t>(offset_);
out.WriteValue<int64_t>(length_);
return MemorySegmentUtils::CopyToBytes(out.Segments(), 0, out.CurrentSize(), pool.get());
}
Result<std::unique_ptr<BlobDescriptor>> BlobDescriptor::Deserialize(const char* buffer,
uint64_t size) {
auto input_stream = std::make_shared<ByteArrayInputStream>(buffer, size);
DataInputStream in(std::move(input_stream));
in.SetOrder(ByteOrder::PAIMON_LITTLE_ENDIAN);
PAIMON_ASSIGN_OR_RAISE(int8_t version, in.ReadValue<int8_t>());
if (version > kCurrentVersion) {
return Status::Invalid(fmt::format(
"Expecting BlobDescriptor version to be less than or equal to {}, but found {}.",
kCurrentVersion, version));
}
if (version > 1) {
PAIMON_ASSIGN_OR_RAISE(int64_t magic, in.ReadValue<int64_t>());
if (kMagic != magic) {
return Status::Invalid(fmt::format(
"Invalid BlobDescriptor: missing magic header. Expected magic: {}, but found {}",
kMagic, magic));
}
}
PAIMON_ASSIGN_OR_RAISE(int32_t uri_length, in.ReadValue<int32_t>());
std::string uri(uri_length, '\0');
PAIMON_RETURN_NOT_OK(in.Read(uri.data(), uri.size()));
PAIMON_ASSIGN_OR_RAISE(int64_t offset, in.ReadValue<int64_t>());
PAIMON_ASSIGN_OR_RAISE(int64_t length, in.ReadValue<int64_t>());
return BlobDescriptor::Create(version, uri, offset, length);
}
Result<bool> BlobDescriptor::IsBlobDescriptor(const char* buffer, uint64_t size) {
if (size < kMinDescriptorLength) {
return false;
}
auto input_stream = std::make_shared<ByteArrayInputStream>(buffer, size);
DataInputStream in(std::move(input_stream));
in.SetOrder(ByteOrder::PAIMON_LITTLE_ENDIAN);
PAIMON_ASSIGN_OR_RAISE(int8_t version, in.ReadValue<int8_t>());
if (version > kCurrentVersion) {
return false;
}
PAIMON_ASSIGN_OR_RAISE(int64_t magic, in.ReadValue<int64_t>());
return kMagic == magic;
}
std::string BlobDescriptor::ToString() const {
return fmt::format("BlobDescriptor{{version={}, uri='{}', offset={}, length={}}}", version_,
uri_, offset_, length_);
}
} // namespace paimon