ceph/src/rados_import.cc
Samuel Just 717621f66e librados,Objecter,PG: list objects now includes the locator key
Previously, there was no way to recover the locator key used to create
and object.  Now, rados_objects_list_next and ObjectIterator will return
the key as well as the object name.

Signed-off-by: Samuel Just <samuel.just@dreamhost.com>
2011-12-07 11:40:11 -08:00

240 lines
7.1 KiB
C++

// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
* Ceph - scalable distributed file system
*
* Copyright (C) 2011 New Dream Network
*
* This is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software
* Foundation. See file COPYING.
*
*/
#include <dirent.h>
#include <errno.h>
#include <fstream>
#include <inttypes.h>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "rados_sync.h"
#include "common/errno.h"
#include "common/strtol.h"
#include "include/rados/librados.hpp"
using namespace librados;
using std::auto_ptr;
class ImportLocalFileWQ : public RadosSyncWQ {
public:
ImportLocalFileWQ(const char *dir_name, bool force,
IoCtxDistributor *io_ctx_dist, time_t ti, ThreadPool *tp)
: RadosSyncWQ(io_ctx_dist, ti, 0, tp),
m_dir_name(dir_name),
m_force(force)
{
}
private:
void _process(std::string *s) {
IoCtx &io_ctx(m_io_ctx_dist->get_ioctx());
const std::string &local_name(*s);
auto_ptr <BackedUpObject> sobj;
auto_ptr <BackedUpObject> dobj;
std::list < std::string > only_in_a;
std::list < std::string > only_in_b;
std::list < std::string > diff;
int flags = 0;
int ret = BackedUpObject::from_file(local_name.c_str(),
m_dir_name.c_str(), sobj);
if (ret) {
cerr << ERR_PREFIX << "BackedUpObject::from_file: got error "
<< ret << std::endl;
_exit(ret);
}
const char *rados_name(sobj->get_rados_name());
if (m_force) {
flags |= (CHANGED_CONTENTS | CHANGED_XATTRS);
}
else {
ret = BackedUpObject::from_rados(io_ctx, rados_name, dobj);
if (ret == -ENOENT) {
flags |= CHANGED_CONTENTS;
sobj->get_xattrs(only_in_a);
}
else if (ret) {
cerr << ERR_PREFIX << "BackedUpObject::from_rados returned "
<< ret << std::endl;
_exit(ret);
}
else {
sobj->xattr_diff(dobj.get(), only_in_a, only_in_b, diff);
if ((sobj->get_rados_size() == dobj->get_rados_size()) &&
(sobj->get_mtime() == dobj->get_mtime())) {
flags |= CHANGED_CONTENTS;
}
}
}
if (flags & CHANGED_CONTENTS) {
ret = sobj->upload(io_ctx, local_name.c_str(), m_dir_name.c_str());
if (ret) {
cerr << ERR_PREFIX << "upload error: " << ret << std::endl;
_exit(ret);
}
}
for (std::list < std::string >::const_iterator x = only_in_a.begin();
x != only_in_a.end(); ++x) {
flags |= CHANGED_XATTRS;
const Xattr *xattr = sobj->get_xattr(*x);
if (xattr == NULL) {
cerr << ERR_PREFIX << "internal error on line: " << __LINE__ << std::endl;
_exit(ret);
}
bufferlist bl;
bl.append(xattr->data, xattr->len);
ret = io_ctx.setxattr(rados_name, x->c_str(), bl);
if (ret < 0) {
ret = errno;
cerr << ERR_PREFIX << "io_ctx.setxattr(rados_name='" << rados_name
<< "', xattr_name='" << x->c_str() << "'): " << cpp_strerror(ret)
<< std::endl;
_exit(ret);
}
}
for (std::list < std::string >::const_iterator x = diff.begin();
x != diff.end(); ++x) {
flags |= CHANGED_XATTRS;
const Xattr *xattr = sobj->get_xattr(*x);
if (xattr == NULL) {
cerr << ERR_PREFIX << "internal error on line: " << __LINE__ << std::endl;
_exit(ret);
}
bufferlist bl;
bl.append(xattr->data, xattr->len);
ret = io_ctx.rmxattr(rados_name, x->c_str());
if (ret < 0) {
cerr << ERR_PREFIX << "io_ctx.rmxattr error2: " << cpp_strerror(ret)
<< std::endl;
_exit(ret);
}
ret = io_ctx.setxattr(rados_name, x->c_str(), bl);
if (ret < 0) {
ret = errno;
cerr << ERR_PREFIX << "io_ctx.setxattr(rados_name='" << rados_name
<< "', xattr='" << x->c_str() << "'): " << cpp_strerror(ret) << std::endl;
_exit(ret);
}
}
for (std::list < std::string >::const_iterator x = only_in_b.begin();
x != only_in_b.end(); ++x) {
flags |= CHANGED_XATTRS;
ret = io_ctx.rmxattr(rados_name, x->c_str());
if (ret < 0) {
ret = errno;
cerr << ERR_PREFIX << "rmxattr error3: " << cpp_strerror(ret) << std::endl;
_exit(ret);
}
}
if (m_force) {
cout << "[force] " << rados_name << std::endl;
}
else if (flags & CHANGED_CONTENTS) {
cout << "[imported] " << rados_name << std::endl;
}
else if (flags & CHANGED_XATTRS) {
cout << "[xattr] " << rados_name << std::endl;
}
}
std::string m_dir_name;
bool m_force;
};
class ImportValidateExistingWQ : public RadosSyncWQ {
public:
ImportValidateExistingWQ(ExportDir *export_dir,
IoCtxDistributor *io_ctx_dist, time_t ti, ThreadPool *tp)
: RadosSyncWQ(io_ctx_dist, ti, 0, tp),
m_export_dir(export_dir)
{
}
private:
void _process(std::string *s) {
IoCtx &io_ctx(m_io_ctx_dist->get_ioctx());
const std::string &rados_name(*s);
auto_ptr <BackedUpObject> robj;
int ret = BackedUpObject::from_rados(io_ctx, rados_name.c_str(), robj);
if (ret) {
cerr << ERR_PREFIX << "BackedUpObject::from_rados in delete loop "
<< "returned " << ret << std::endl;
_exit(ret);
}
std::string obj_path(robj->get_fs_path(m_export_dir));
auto_ptr <BackedUpObject> lobj;
ret = BackedUpObject::from_path(obj_path.c_str(), lobj);
if (ret == ENOENT) {
ret = io_ctx.remove(rados_name);
if (ret && ret != -ENOENT) {
cerr << ERR_PREFIX << "io_ctx.remove(" << obj_path << ") failed "
<< "with error " << ret << std::endl;
_exit(ret);
}
cout << "[deleted] " << "removed '" << rados_name << "'" << std::endl;
}
else if (ret) {
cerr << ERR_PREFIX << "BackedUpObject::from_path in delete loop "
<< "returned " << ret << std::endl;
_exit(ret);
}
}
ExportDir *m_export_dir;
};
int do_rados_import(ThreadPool *tp, IoCtx &io_ctx, IoCtxDistributor* io_ctx_dist,
const char *dir_name, bool force, bool delete_after)
{
auto_ptr <ExportDir> export_dir;
export_dir.reset(ExportDir::from_file_system(dir_name));
if (!export_dir.get())
return -EIO;
DirHolder dh;
int ret = dh.opendir(dir_name);
if (ret) {
cerr << ERR_PREFIX << "opendir(" << dir_name << ") error: "
<< cpp_strerror(ret) << std::endl;
return ret;
}
ImportLocalFileWQ import_file_wq(dir_name, force,
io_ctx_dist, time(NULL), tp);
while (true) {
struct dirent *de = readdir(dh.dp);
if (!de)
break;
if ((strcmp(de->d_name, ".") == 0) || (strcmp(de->d_name, "..") == 0))
continue;
if (is_suffix(de->d_name, RADOS_SYNC_TMP_SUFFIX))
continue;
import_file_wq.queue(new std::string(de->d_name));
}
import_file_wq.drain();
if (delete_after) {
ImportValidateExistingWQ import_val_wq(export_dir.get(), io_ctx_dist,
time(NULL), tp);
librados::ObjectIterator oi = io_ctx.objects_begin();
librados::ObjectIterator oi_end = io_ctx.objects_end();
for (; oi != oi_end; ++oi) {
import_val_wq.queue(new std::string((*oi).first));
}
import_val_wq.drain();
}
cout << "[done]" << std::endl;
return 0;
}