rocksdb/thrift/lib/cpp/util/ThriftSerializer.h
Dhruba Borthakur 80c663882a Create leveldb server via Thrift.
Summary:
First draft.
Unit tests pass.

Test Plan: unit tests attached

Reviewers: heyongqiang

Reviewed By: heyongqiang

Differential Revision: https://reviews.facebook.net/D3969
2012-07-07 09:42:39 -07:00

225 lines
6.9 KiB
C++

/*
* 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.
*/
// @author Karl Voskuil (karl@facebook.com)
// @author Mark Rabkin (mrabkin@facebook.com)
//
#ifndef COMMON_STRINGS_THRIFT_SERIALIZER_H
#define COMMON_STRINGS_THRIFT_SERIALIZER_H
#include <string>
#include <boost/shared_ptr.hpp>
#include "thrift/lib/cpp/protocol/TBinaryProtocol.h" // for serialization
#include "thrift/lib/cpp/protocol/TCompactProtocol.h" // for serialization
#include "thrift/lib/cpp/protocol/TJSONProtocol.h" // for serialization
#include "thrift/lib/cpp/protocol/TSimpleJSONProtocol.h" // for serialization
#include "thrift/lib/cpp/transport/TTransportUtils.h" // for serialization
namespace apache { namespace thrift { namespace util {
using apache::thrift::protocol::TBinaryProtocolT;
using apache::thrift::protocol::TCompactProtocolT;
using apache::thrift::protocol::TCompactProtocol;
using apache::thrift::protocol::TSimpleJSONProtocol;
using apache::thrift::protocol::TJSONProtocol;
using apache::thrift::transport::TBufferBase;
using apache::thrift::transport::TTransport;
using apache::thrift::transport::TMemoryBuffer;
using boost::shared_ptr;
/**
* Encapsulates methods to serialize or deserialize a code-gen-ed
* Thrift class to and from a string. For example:
*
* extern StatsMcValue data;
*
* ThriftSerializerBinary<StatsMcValue> serializer;
* string serialized;
* serializer.serialize(data, &serizalied);
*
* StatsMcValue result;
* try {
* if (serializer.deserialize(serialized, &result) !=
* serialized.length()) {
* // Handle deserialization error, not all data consumed.
* }
* } catch (TProtocolException& tpe) {
* // Handle deserialization error, underlying protocol threw.
* }
* // Use deserialized thrift object.
* ...
*
* @author Karl Voskuil
*/
template <typename T, typename P>
class ThriftSerializer {
public:
ThriftSerializer()
: prepared_(false)
, lastDeserialized_(false)
, setVersion_(false) {}
/**
* Serializes the passed type into the passed string.
*
* @author Karl Voskuil
*/
template <class String>
void serialize(const T& fields, String* serialized);
/**
* Serializes the passed type into the internal buffer
* and returns a pointer to the internal buffer and its size.
*
* @author Yuri Putivsky
*/
void serialize(const T& fields, const uint8_t** serializedBuffer,
size_t* serializedLen);
/**
* Deserializes the passed string into the passed type, returns the number of
* bytes that have been consumed from the passed string.
*
* The return value can be used to verify if the deserialization is successful
* or not. When a type is serialized then deserialized back, the number of
* consumed bytes must equal to the size of serialized string. But please
* note, equality of these two values doesn't guarantee the serialized string
* isn't corrupt. It's up to the underlying implementation of the type and
* thrift protocol to detect and handle invalid serialized string, they may
* throw exception or just ignore the unrecognized data.
* @author Karl Voskuil
*/
template <class String>
uint32_t deserialize(const String& serialized, T* fields)
{
return deserialize((const uint8_t*)serialized.data(),
serialized.size(),
fields);
}
/**
* Deserializes the passed char array into the passed type, returns the number
* of bytes that have been consumed from the passed string.
*
* See notes on return value for:
* deserilize(const String* serialized, T* fields)
*/
uint32_t deserialize(const uint8_t* serializedBuffer,
size_t length,
T* fields);
/**
* Same as deserialize() above, but won't touch/reset any optional fields
* that are not present in 'serialized'. So, if T has any optional fields,
* the caller is responsible for resetting those (or somehow handling the
* potentially dirty data.)
*
* Use this method if:
* 1) your thrift class doesn't contain any optional fields, and
* 2) you are trying to avoid memory allocations/fragmentation during
* deserialization of thift objects
*
* @author Rafael Sagula
*/
template <class String>
uint32_t deserializeClean(const String& serialized, T* fields);
/**
* Set version of protocol data to read/write. This is only necessary
* for data that will be saved to disk between protocol versions!
* You probably don't need to use this unless you know what you are doing
*
* @author davejwatson
*/
void setVersion(int8_t version);
private:
void prepare();
private:
typedef P Protocol;
bool prepared_;
bool lastDeserialized_;
shared_ptr<TMemoryBuffer> buffer_;
shared_ptr<Protocol> protocol_;
int8_t version_;
bool setVersion_;
};
template <typename T>
struct ThriftSerializerBinary
: public ThriftSerializer<T, TBinaryProtocolT<TBufferBase> >
{ };
template <typename T>
struct ThriftSerializerCompact
: public ThriftSerializer<T, TCompactProtocolT<TBufferBase> >
{ };
/**
* This version is deprecated. Please do not use it anymore,
* unless you have data already serialized to disk in this format.
* Doubles are not serialized in correct network order, so making RPC
* calls with this data will not work.
*/
template <typename T>
struct ThriftSerializerCompactDeprecated
: public ThriftSerializer<T, TCompactProtocolT<TBufferBase> >
{
public:
ThriftSerializerCompactDeprecated() {
this->setVersion(TCompactProtocol::VERSION_LOW);
}
};
template <typename T>
struct ThriftSerializerJson
: public ThriftSerializer<T, TJSONProtocol>
{ };
template <typename T>
struct ThriftSerializerSimpleJson
: public ThriftSerializer<T, TSimpleJSONProtocol>
{ };
}}} // namespace apache::thrift:util
namespace apache { namespace thrift {
template<typename ThriftStruct>
std::string ThriftJSONString(const ThriftStruct& ts) {
using namespace apache::thrift::protocol;
using namespace apache::thrift::util;
ThriftSerializer<ThriftStruct, TJSONProtocol> serializer;
std::string serialized;
serializer.serialize(ts, &serialized);
return serialized;
}
}} // apache::thrift
#include "thrift/lib/cpp/util/ThriftSerializer-inl.h"
#endif