Estou envolvido num projeto que emula a comunicação com um elemento de rede. Trata-se de um servidor simples que responde à requisições feitas por um outro serviço, utilizando o protocolo ROSE+ASN.1 codificado com BER.
O servidor tem 3 operações principais ( adicionar, remover e listar ). Quando um item é adicionado ele fica em memória até que o servidor receba o comando para excluí-lo. Porém durante os testes surgiu a necessidade de reiniciar o servidor sem perder as informações que estavam em memória.
Optei por utilizar a boost serialization já que não preciso de um banco de dados elaborado. Já tinha uma classe chamada Interception. Já tenho a struct que será utilizada para persistência ela estava assim:
struct Interception { string liid_; string targetId_; TargetType targetType_; string deliveryOfIRI_; string deliveryOfIPR_; string startTime_; string endTime_; }
Basicamente o que precisei fazer foi:
A serialização da boost é feita utilizando templates para o stream de destino. Para enviar dados para o stream você pode utilizar os operadores “<<” ou “&”, para ler dados da stream utilize “>>” ou “&”. O operador & é melhor porque utilizando ele você não precisa definir métodos específicos para ler e salvar na stream. Apenas o método serialize resolve.
O código de serialização ficou assim:
#include <boost/serialization/serialization.hpp> //.... template void serialize(Archive &ar, const unsigned int version) { ar & liid_; ar & targetId_; ar & targetType_; ar & deliveryOfIRI_; ar & deliveryOfIPR_; ar & startTime_; ar & endTime_; };
Adicionei este template method à struct Interception como um membro. Se não fosse possível fazer isso ( ex.: se eu não pudesse alterar essa struct. A solução seria criar esse método dentro da namespace boost::serialization. Assim:
#include <boost/serialization/serialization.hpp> //.... namespace boost { namespace serialization { template void serialize(Archive &ar, Interception &i const unsigned int version) { ar & i.liid_; ar & i.targetId_; ar & i.targetType_; ar & i.deliveryOfIRI_; ar & i.deliveryOfIPR_; ar & i.startTime_; ar & i.endTime_; }; }}
Depois da implementação do método serialize, bastou criar os métodos de leitura e escrita em arquivos:
template void saveToFile(const std::string &fileName, const ListType& in) { std::ofstream ofs(fileName.c_str()); boost::archive::text_oarchive oa(ofs); boost::serialization::save(oa, in, 1); } template void readFromFile(const std::string &fileName, ListType &out) { std::ifstream f(fileName.c_str()); boost::archive::text_iarchive ia(f); boost::serialization::load(ia, out, 1); }
Para usar as funções readFromFile e saveToFile o código ficou assim:
string fn = "file.txt"; saveToFile(fn, server->getConfig().getInterceptions()); //... readFromFile(fn, server->getConfig().getInterceptions());