2011-02-09 01:19:39 +00:00
|
|
|
#ifndef CEPH_RGWCACHE_H
|
|
|
|
#define CEPH_RGWCACHE_H
|
|
|
|
|
2012-03-15 00:16:05 +00:00
|
|
|
#include "rgw_rados.h"
|
2011-02-09 01:19:39 +00:00
|
|
|
#include <string>
|
|
|
|
#include <map>
|
|
|
|
#include "include/types.h"
|
2011-07-15 17:57:48 +00:00
|
|
|
#include "include/utime.h"
|
2012-06-06 23:57:31 +00:00
|
|
|
#include "include/assert.h"
|
2011-02-09 01:19:39 +00:00
|
|
|
|
2011-07-01 00:13:42 +00:00
|
|
|
enum {
|
2011-07-07 22:04:26 +00:00
|
|
|
UPDATE_OBJ,
|
|
|
|
REMOVE_OBJ,
|
2011-07-01 00:13:42 +00:00
|
|
|
};
|
|
|
|
|
2011-10-25 23:23:08 +00:00
|
|
|
#define CACHE_FLAG_DATA 0x1
|
|
|
|
#define CACHE_FLAG_XATTRS 0x2
|
|
|
|
#define CACHE_FLAG_META 0x4
|
2012-02-23 21:56:22 +00:00
|
|
|
#define CACHE_FLAG_MODIFY_XATTRS 0x8
|
2011-07-07 22:04:26 +00:00
|
|
|
|
2012-03-27 17:41:12 +00:00
|
|
|
#define mydout(v) lsubdout(T::cct, rgw, v)
|
|
|
|
|
2011-07-07 22:04:26 +00:00
|
|
|
struct ObjectMetaInfo {
|
|
|
|
uint64_t size;
|
|
|
|
time_t mtime;
|
|
|
|
|
2011-12-30 22:18:40 +00:00
|
|
|
ObjectMetaInfo() : size(0), mtime(0) {}
|
|
|
|
|
2011-07-07 22:04:26 +00:00
|
|
|
void encode(bufferlist& bl) const {
|
2012-03-08 00:29:11 +00:00
|
|
|
ENCODE_START(2, 2, bl);
|
2011-07-07 22:04:26 +00:00
|
|
|
::encode(size, bl);
|
2011-07-15 17:57:48 +00:00
|
|
|
utime_t t(mtime, 0);
|
|
|
|
::encode(t, bl);
|
2012-03-08 00:29:11 +00:00
|
|
|
ENCODE_FINISH(bl);
|
2011-07-07 22:04:26 +00:00
|
|
|
}
|
|
|
|
void decode(bufferlist::iterator& bl) {
|
2012-03-08 00:29:11 +00:00
|
|
|
DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, bl);
|
2011-07-07 22:04:26 +00:00
|
|
|
::decode(size, bl);
|
2011-07-15 17:57:48 +00:00
|
|
|
utime_t t;
|
|
|
|
::decode(t, bl);
|
|
|
|
mtime = t.sec();
|
2012-03-08 00:29:11 +00:00
|
|
|
DECODE_FINISH(bl);
|
2011-07-07 22:04:26 +00:00
|
|
|
}
|
2012-03-09 00:58:00 +00:00
|
|
|
void dump(Formatter *f) const;
|
|
|
|
static void generate_test_instances(list<ObjectMetaInfo*>& o);
|
2011-07-07 22:04:26 +00:00
|
|
|
};
|
|
|
|
WRITE_CLASS_ENCODER(ObjectMetaInfo)
|
|
|
|
|
|
|
|
struct ObjectCacheInfo {
|
|
|
|
int status;
|
|
|
|
uint32_t flags;
|
2012-11-13 20:09:05 +00:00
|
|
|
uint64_t epoch;
|
2011-07-07 22:04:26 +00:00
|
|
|
bufferlist data;
|
|
|
|
map<string, bufferlist> xattrs;
|
2012-02-23 21:56:22 +00:00
|
|
|
map<string, bufferlist> rm_xattrs;
|
2011-07-07 22:04:26 +00:00
|
|
|
ObjectMetaInfo meta;
|
|
|
|
|
2012-11-13 20:09:05 +00:00
|
|
|
ObjectCacheInfo() : status(0), flags(0), epoch(0) {}
|
2011-07-07 22:04:26 +00:00
|
|
|
|
|
|
|
void encode(bufferlist& bl) const {
|
2012-11-13 20:09:05 +00:00
|
|
|
ENCODE_START(4, 3, bl);
|
2011-07-07 22:04:26 +00:00
|
|
|
::encode(status, bl);
|
|
|
|
::encode(flags, bl);
|
|
|
|
::encode(data, bl);
|
|
|
|
::encode(xattrs, bl);
|
|
|
|
::encode(meta, bl);
|
2012-02-23 21:56:22 +00:00
|
|
|
::encode(rm_xattrs, bl);
|
2012-11-13 20:09:05 +00:00
|
|
|
::encode(epoch, bl);
|
2012-03-08 00:29:11 +00:00
|
|
|
ENCODE_FINISH(bl);
|
2011-07-07 22:04:26 +00:00
|
|
|
}
|
|
|
|
void decode(bufferlist::iterator& bl) {
|
2012-11-13 20:09:05 +00:00
|
|
|
DECODE_START_LEGACY_COMPAT_LEN(4, 3, 3, bl);
|
2011-07-07 22:04:26 +00:00
|
|
|
::decode(status, bl);
|
|
|
|
::decode(flags, bl);
|
|
|
|
::decode(data, bl);
|
|
|
|
::decode(xattrs, bl);
|
|
|
|
::decode(meta, bl);
|
2012-02-23 21:56:22 +00:00
|
|
|
if (struct_v >= 2)
|
|
|
|
::decode(rm_xattrs, bl);
|
2012-11-13 20:09:05 +00:00
|
|
|
if (struct_v >= 4)
|
|
|
|
::decode(epoch, bl);
|
2012-03-08 00:29:11 +00:00
|
|
|
DECODE_FINISH(bl);
|
2011-07-07 22:04:26 +00:00
|
|
|
}
|
2012-03-09 00:58:00 +00:00
|
|
|
void dump(Formatter *f) const;
|
|
|
|
static void generate_test_instances(list<ObjectCacheInfo*>& o);
|
2011-07-07 22:04:26 +00:00
|
|
|
};
|
|
|
|
WRITE_CLASS_ENCODER(ObjectCacheInfo)
|
|
|
|
|
2011-07-01 00:13:42 +00:00
|
|
|
struct RGWCacheNotifyInfo {
|
|
|
|
uint32_t op;
|
|
|
|
rgw_obj obj;
|
2011-07-07 22:04:26 +00:00
|
|
|
ObjectCacheInfo obj_info;
|
2011-07-01 00:13:42 +00:00
|
|
|
off_t ofs;
|
2011-07-07 22:04:26 +00:00
|
|
|
string ns;
|
2011-07-01 00:13:42 +00:00
|
|
|
|
2011-12-30 22:18:40 +00:00
|
|
|
RGWCacheNotifyInfo() : op(0), ofs(0) {}
|
|
|
|
|
2011-07-01 00:13:42 +00:00
|
|
|
void encode(bufferlist& obl) const {
|
2012-03-08 00:29:11 +00:00
|
|
|
ENCODE_START(2, 2, obl);
|
2011-07-01 00:13:42 +00:00
|
|
|
::encode(op, obl);
|
|
|
|
::encode(obj, obl);
|
2011-07-07 22:04:26 +00:00
|
|
|
::encode(obj_info, obl);
|
2011-07-01 00:13:42 +00:00
|
|
|
::encode(ofs, obl);
|
2011-07-07 22:04:26 +00:00
|
|
|
::encode(ns, obl);
|
2012-03-08 00:29:11 +00:00
|
|
|
ENCODE_FINISH(obl);
|
2011-07-01 00:13:42 +00:00
|
|
|
}
|
|
|
|
void decode(bufferlist::iterator& ibl) {
|
2012-03-08 00:29:11 +00:00
|
|
|
DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, ibl);
|
2011-07-01 00:13:42 +00:00
|
|
|
::decode(op, ibl);
|
|
|
|
::decode(obj, ibl);
|
2011-07-07 22:04:26 +00:00
|
|
|
::decode(obj_info, ibl);
|
2011-07-01 00:13:42 +00:00
|
|
|
::decode(ofs, ibl);
|
2011-07-07 22:04:26 +00:00
|
|
|
::decode(ns, ibl);
|
2012-03-08 00:29:11 +00:00
|
|
|
DECODE_FINISH(ibl);
|
2011-07-01 00:13:42 +00:00
|
|
|
}
|
2012-03-09 00:58:00 +00:00
|
|
|
void dump(Formatter *f) const;
|
|
|
|
static void generate_test_instances(list<RGWCacheNotifyInfo*>& o);
|
2011-07-01 00:13:42 +00:00
|
|
|
};
|
|
|
|
WRITE_CLASS_ENCODER(RGWCacheNotifyInfo)
|
|
|
|
|
2011-07-09 00:17:32 +00:00
|
|
|
struct ObjectCacheEntry {
|
|
|
|
ObjectCacheInfo info;
|
|
|
|
std::list<string>::iterator lru_iter;
|
|
|
|
};
|
|
|
|
|
2011-02-09 01:19:39 +00:00
|
|
|
class ObjectCache {
|
2011-07-09 00:17:32 +00:00
|
|
|
std::map<string, ObjectCacheEntry> cache_map;
|
|
|
|
std::list<string> lru;
|
2011-08-19 19:56:38 +00:00
|
|
|
Mutex lock;
|
2012-03-13 21:59:00 +00:00
|
|
|
CephContext *cct;
|
2011-02-09 01:19:39 +00:00
|
|
|
|
2011-07-09 00:17:32 +00:00
|
|
|
void touch_lru(string& name, std::list<string>::iterator& lru_iter);
|
|
|
|
void remove_lru(string& name, std::list<string>::iterator& lru_iter);
|
2011-02-09 01:19:39 +00:00
|
|
|
public:
|
2012-03-13 21:59:00 +00:00
|
|
|
ObjectCache() : lock("ObjectCache"), cct(NULL) { }
|
2011-07-07 22:04:26 +00:00
|
|
|
int get(std::string& name, ObjectCacheInfo& bl, uint32_t mask);
|
|
|
|
void put(std::string& name, ObjectCacheInfo& bl);
|
|
|
|
void remove(std::string& name);
|
2012-03-13 21:59:00 +00:00
|
|
|
void set_ctx(CephContext *_cct) { cct = _cct; }
|
2011-02-09 01:19:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
class RGWCache : public T
|
|
|
|
{
|
|
|
|
ObjectCache cache;
|
|
|
|
|
2011-09-29 18:23:02 +00:00
|
|
|
int list_objects_raw_init(rgw_bucket& bucket, RGWAccessHandle *handle) {
|
|
|
|
return T::list_objects_raw_init(bucket, handle);
|
|
|
|
}
|
|
|
|
int list_objects_raw_next(RGWObjEnt& obj, RGWAccessHandle *handle) {
|
|
|
|
return T::list_objects_raw_next(obj, handle);
|
|
|
|
}
|
|
|
|
|
2011-08-18 00:11:55 +00:00
|
|
|
string normal_name(rgw_bucket& bucket, std::string& oid) {
|
|
|
|
string& bucket_name = bucket.name;
|
|
|
|
char buf[bucket_name.size() + 1 + oid.size() + 1];
|
|
|
|
const char *bucket_str = bucket_name.c_str();
|
2011-03-04 22:11:21 +00:00
|
|
|
const char *oid_str = oid.c_str();
|
2011-07-07 22:04:26 +00:00
|
|
|
sprintf(buf, "%s+%s", bucket_str, oid_str);
|
2011-02-09 01:19:39 +00:00
|
|
|
return string(buf);
|
|
|
|
}
|
|
|
|
|
2012-08-10 21:16:42 +00:00
|
|
|
void normalize_bucket_and_obj(rgw_bucket& src_bucket, string& src_obj, rgw_bucket& dst_bucket, string& dst_obj);
|
2011-07-11 21:26:16 +00:00
|
|
|
string normal_name(rgw_obj& obj) {
|
|
|
|
return normal_name(obj.bucket, obj.object);
|
|
|
|
}
|
|
|
|
|
2012-03-13 21:59:00 +00:00
|
|
|
int initialize() {
|
2011-07-14 19:43:25 +00:00
|
|
|
int ret;
|
2012-03-13 21:59:00 +00:00
|
|
|
cache.set_ctx(T::cct);
|
|
|
|
ret = T::initialize();
|
2011-07-14 19:43:25 +00:00
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
ret = T::init_watch();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void finalize() {
|
|
|
|
T::finalize_watch();
|
2012-08-21 22:05:38 +00:00
|
|
|
T::finalize();
|
2011-07-14 19:43:25 +00:00
|
|
|
}
|
2012-11-13 21:06:22 +00:00
|
|
|
int distribute_cache(const string& normal_name, rgw_obj& obj, ObjectCacheInfo& obj_info, int op);
|
2011-07-01 00:13:42 +00:00
|
|
|
int watch_cb(int opcode, uint64_t ver, bufferlist& bl);
|
2011-02-09 01:19:39 +00:00
|
|
|
public:
|
|
|
|
RGWCache() {}
|
|
|
|
|
2011-10-25 23:23:08 +00:00
|
|
|
int set_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& bl);
|
2012-02-23 21:56:22 +00:00
|
|
|
int set_attrs(void *ctx, rgw_obj& obj,
|
|
|
|
map<string, bufferlist>& attrs,
|
|
|
|
map<string, bufferlist>* rmattrs);
|
2011-10-28 18:48:38 +00:00
|
|
|
int put_obj_meta(void *ctx, rgw_obj& obj, uint64_t size, time_t *mtime,
|
2012-11-13 20:09:05 +00:00
|
|
|
map<std::string, bufferlist>& attrs, RGWObjCategory category, int flags,
|
2012-05-03 19:50:23 +00:00
|
|
|
map<std::string, bufferlist>* rmattrs, const bufferlist *data,
|
2012-11-27 19:50:38 +00:00
|
|
|
RGWObjManifest *manifest, const string *ptag, list<string> *remove_objs);
|
2011-10-25 23:23:08 +00:00
|
|
|
|
2011-10-28 18:48:38 +00:00
|
|
|
int put_obj_data(void *ctx, rgw_obj& obj, const char *data,
|
2011-12-29 00:33:14 +00:00
|
|
|
off_t ofs, size_t len, bool exclusive);
|
2011-02-09 01:19:39 +00:00
|
|
|
|
2012-03-20 17:25:59 +00:00
|
|
|
int get_obj(void *ctx, void **handle, rgw_obj& obj, bufferlist& bl, off_t ofs, off_t end);
|
2011-02-09 01:19:39 +00:00
|
|
|
|
2012-11-13 20:09:05 +00:00
|
|
|
int obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime, uint64_t *epoch, map<string, bufferlist> *attrs, bufferlist *first_chunk);
|
2011-07-11 23:55:05 +00:00
|
|
|
|
2012-09-15 22:21:56 +00:00
|
|
|
int delete_obj(void *ctx, rgw_obj& obj);
|
2011-02-09 01:19:39 +00:00
|
|
|
};
|
|
|
|
|
2012-08-10 21:16:42 +00:00
|
|
|
template <class T>
|
|
|
|
void RGWCache<T>::normalize_bucket_and_obj(rgw_bucket& src_bucket, string& src_obj, rgw_bucket& dst_bucket, string& dst_obj)
|
|
|
|
{
|
|
|
|
if (src_obj.size()) {
|
|
|
|
dst_bucket = src_bucket;
|
|
|
|
dst_obj = src_obj;
|
|
|
|
} else {
|
|
|
|
dst_bucket = T::params.domain_root;
|
|
|
|
dst_obj = src_bucket.name;
|
|
|
|
}
|
|
|
|
}
|
2011-02-09 01:19:39 +00:00
|
|
|
|
2011-07-11 23:55:05 +00:00
|
|
|
template <class T>
|
2012-09-15 22:21:56 +00:00
|
|
|
int RGWCache<T>::delete_obj(void *ctx, rgw_obj& obj)
|
2011-07-11 23:55:05 +00:00
|
|
|
{
|
2011-10-25 23:23:08 +00:00
|
|
|
rgw_bucket bucket;
|
|
|
|
string oid;
|
|
|
|
normalize_bucket_and_obj(obj.bucket, obj.object, bucket, oid);
|
|
|
|
if (bucket.name[0] != '.')
|
2012-09-15 22:21:56 +00:00
|
|
|
return T::delete_obj(ctx, obj);
|
2011-07-11 23:55:05 +00:00
|
|
|
|
|
|
|
string name = normal_name(obj);
|
|
|
|
cache.remove(name);
|
|
|
|
|
|
|
|
ObjectCacheInfo info;
|
2012-11-13 21:06:22 +00:00
|
|
|
distribute_cache(name, obj, info, REMOVE_OBJ);
|
2011-07-11 23:55:05 +00:00
|
|
|
|
2012-09-15 22:21:56 +00:00
|
|
|
return T::delete_obj(ctx, obj);
|
2011-07-11 23:55:05 +00:00
|
|
|
}
|
2011-07-07 22:04:26 +00:00
|
|
|
|
2011-02-09 01:19:39 +00:00
|
|
|
template <class T>
|
2012-03-20 17:25:59 +00:00
|
|
|
int RGWCache<T>::get_obj(void *ctx, void **handle, rgw_obj& obj, bufferlist& obl, off_t ofs, off_t end)
|
2011-02-09 01:19:39 +00:00
|
|
|
{
|
2011-10-25 23:23:08 +00:00
|
|
|
rgw_bucket bucket;
|
|
|
|
string oid;
|
|
|
|
normalize_bucket_and_obj(obj.bucket, obj.object, bucket, oid);
|
|
|
|
if (bucket.name[0] != '.' || ofs != 0)
|
2012-03-20 17:25:59 +00:00
|
|
|
return T::get_obj(ctx, handle, obj, obl, ofs, end);
|
2011-02-09 01:19:39 +00:00
|
|
|
|
2011-08-18 00:11:55 +00:00
|
|
|
string name = normal_name(obj.bucket, oid);
|
2011-07-11 21:26:16 +00:00
|
|
|
|
2011-07-07 22:04:26 +00:00
|
|
|
ObjectCacheInfo info;
|
|
|
|
if (cache.get(name, info, CACHE_FLAG_DATA) == 0) {
|
|
|
|
if (info.status < 0)
|
|
|
|
return info.status;
|
|
|
|
|
|
|
|
bufferlist& bl = info.data;
|
|
|
|
|
2012-03-20 17:25:59 +00:00
|
|
|
bufferlist::iterator i = bl.begin();
|
|
|
|
|
|
|
|
obl.clear();
|
|
|
|
|
|
|
|
i.copy_all(obl);
|
2011-02-09 01:19:39 +00:00
|
|
|
return bl.length();
|
|
|
|
}
|
2012-03-20 17:25:59 +00:00
|
|
|
int r = T::get_obj(ctx, handle, obj, obl, ofs, end);
|
2011-07-07 22:04:26 +00:00
|
|
|
if (r < 0) {
|
|
|
|
if (r == -ENOENT) { // only update ENOENT, we'd rather retry other errors
|
|
|
|
info.status = r;
|
|
|
|
cache.put(name, info);
|
|
|
|
}
|
2011-02-09 01:19:39 +00:00
|
|
|
return r;
|
2011-07-07 22:04:26 +00:00
|
|
|
}
|
2011-02-09 01:19:39 +00:00
|
|
|
|
2012-11-29 21:39:22 +00:00
|
|
|
if (obl.length() == end + 1) {
|
|
|
|
/* in this case, most likely object contains more data, we can't cache it */
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2011-02-09 01:19:39 +00:00
|
|
|
bufferptr p(r);
|
2011-07-07 22:04:26 +00:00
|
|
|
bufferlist& bl = info.data;
|
2011-02-09 01:19:39 +00:00
|
|
|
bl.clear();
|
2012-03-20 17:25:59 +00:00
|
|
|
bufferlist::iterator o = obl.begin();
|
|
|
|
o.copy_all(bl);
|
2011-07-07 22:04:26 +00:00
|
|
|
info.status = 0;
|
|
|
|
info.flags = CACHE_FLAG_DATA;
|
|
|
|
cache.put(name, info);
|
2011-02-09 01:19:39 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2011-10-25 23:23:08 +00:00
|
|
|
template <class T>
|
|
|
|
int RGWCache<T>::set_attr(void *ctx, rgw_obj& obj, const char *attr_name, bufferlist& bl)
|
|
|
|
{
|
|
|
|
rgw_bucket bucket;
|
|
|
|
string oid;
|
|
|
|
normalize_bucket_and_obj(obj.bucket, obj.object, bucket, oid);
|
|
|
|
ObjectCacheInfo info;
|
|
|
|
bool cacheable = false;
|
|
|
|
if (bucket.name[0] == '.') {
|
|
|
|
cacheable = true;
|
|
|
|
info.xattrs[attr_name] = bl;
|
|
|
|
info.status = 0;
|
2012-02-23 21:56:22 +00:00
|
|
|
info.flags = CACHE_FLAG_MODIFY_XATTRS;
|
2011-10-25 23:23:08 +00:00
|
|
|
}
|
|
|
|
int ret = T::set_attr(ctx, obj, attr_name, bl);
|
|
|
|
if (cacheable) {
|
|
|
|
string name = normal_name(bucket, oid);
|
|
|
|
if (ret >= 0) {
|
|
|
|
cache.put(name, info);
|
2012-11-13 21:06:22 +00:00
|
|
|
int r = distribute_cache(name, obj, info, UPDATE_OBJ);
|
2011-10-25 23:23:08 +00:00
|
|
|
if (r < 0)
|
2012-03-27 17:41:12 +00:00
|
|
|
mydout(0) << "ERROR: failed to distribute cache for " << obj << dendl;
|
2011-10-25 23:23:08 +00:00
|
|
|
} else {
|
|
|
|
cache.remove(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-02-23 21:56:22 +00:00
|
|
|
template <class T>
|
|
|
|
int RGWCache<T>::set_attrs(void *ctx, rgw_obj& obj,
|
|
|
|
map<string, bufferlist>& attrs,
|
|
|
|
map<string, bufferlist>* rmattrs)
|
|
|
|
{
|
|
|
|
rgw_bucket bucket;
|
|
|
|
string oid;
|
|
|
|
normalize_bucket_and_obj(obj.bucket, obj.object, bucket, oid);
|
|
|
|
ObjectCacheInfo info;
|
|
|
|
bool cacheable = false;
|
|
|
|
if (bucket.name[0] == '.') {
|
|
|
|
cacheable = true;
|
|
|
|
info.xattrs = attrs;
|
|
|
|
if (rmattrs)
|
|
|
|
info.rm_xattrs = *rmattrs;
|
|
|
|
info.status = 0;
|
|
|
|
info.flags = CACHE_FLAG_MODIFY_XATTRS;
|
|
|
|
}
|
|
|
|
int ret = T::set_attrs(ctx, obj, attrs, rmattrs);
|
|
|
|
if (cacheable) {
|
|
|
|
string name = normal_name(bucket, oid);
|
|
|
|
if (ret >= 0) {
|
|
|
|
cache.put(name, info);
|
2012-11-13 21:06:22 +00:00
|
|
|
int r = distribute_cache(name, obj, info, UPDATE_OBJ);
|
2012-02-23 21:56:22 +00:00
|
|
|
if (r < 0)
|
2012-03-27 17:41:12 +00:00
|
|
|
mydout(0) << "ERROR: failed to distribute cache for " << obj << dendl;
|
2012-02-23 21:56:22 +00:00
|
|
|
} else {
|
|
|
|
cache.remove(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-10-25 23:23:08 +00:00
|
|
|
template <class T>
|
2011-10-28 18:48:38 +00:00
|
|
|
int RGWCache<T>::put_obj_meta(void *ctx, rgw_obj& obj, uint64_t size, time_t *mtime,
|
2012-11-13 20:09:05 +00:00
|
|
|
map<std::string, bufferlist>& attrs, RGWObjCategory category, int flags,
|
2012-10-26 19:17:05 +00:00
|
|
|
map<std::string, bufferlist>* rmattrs, const bufferlist *data,
|
2012-11-27 19:50:38 +00:00
|
|
|
RGWObjManifest *manifest, const string *ptag, list<string> *remove_objs)
|
2011-10-25 23:23:08 +00:00
|
|
|
{
|
|
|
|
rgw_bucket bucket;
|
|
|
|
string oid;
|
|
|
|
normalize_bucket_and_obj(obj.bucket, obj.object, bucket, oid);
|
|
|
|
ObjectCacheInfo info;
|
|
|
|
bool cacheable = false;
|
|
|
|
if (bucket.name[0] == '.') {
|
|
|
|
cacheable = true;
|
|
|
|
info.xattrs = attrs;
|
|
|
|
info.status = 0;
|
|
|
|
info.flags = CACHE_FLAG_XATTRS;
|
2012-01-07 00:16:06 +00:00
|
|
|
if (data) {
|
|
|
|
info.data = *data;
|
|
|
|
info.flags |= CACHE_FLAG_DATA;
|
|
|
|
}
|
2011-10-25 23:23:08 +00:00
|
|
|
}
|
2012-11-27 19:50:38 +00:00
|
|
|
int ret = T::put_obj_meta(ctx, obj, size, mtime, attrs, category, flags, rmattrs, data, manifest, ptag, remove_objs);
|
2011-10-25 23:23:08 +00:00
|
|
|
if (cacheable) {
|
|
|
|
string name = normal_name(bucket, oid);
|
|
|
|
if (ret >= 0) {
|
|
|
|
cache.put(name, info);
|
2012-11-13 21:06:22 +00:00
|
|
|
int r = distribute_cache(name, obj, info, UPDATE_OBJ);
|
2011-10-25 23:23:08 +00:00
|
|
|
if (r < 0)
|
2012-03-27 17:41:12 +00:00
|
|
|
mydout(0) << "ERROR: failed to distribute cache for " << obj << dendl;
|
2011-10-25 23:23:08 +00:00
|
|
|
} else {
|
|
|
|
cache.remove(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-09 01:19:39 +00:00
|
|
|
template <class T>
|
2011-10-28 18:48:38 +00:00
|
|
|
int RGWCache<T>::put_obj_data(void *ctx, rgw_obj& obj, const char *data,
|
2011-12-29 00:33:14 +00:00
|
|
|
off_t ofs, size_t len, bool exclusive)
|
2011-02-09 01:19:39 +00:00
|
|
|
{
|
2011-10-25 23:23:08 +00:00
|
|
|
rgw_bucket bucket;
|
|
|
|
string oid;
|
|
|
|
normalize_bucket_and_obj(obj.bucket, obj.object, bucket, oid);
|
2011-07-07 22:04:26 +00:00
|
|
|
ObjectCacheInfo info;
|
2011-07-01 00:13:42 +00:00
|
|
|
bool cacheable = false;
|
2011-10-25 23:23:08 +00:00
|
|
|
if ((bucket.name[0] == '.') && ((ofs == 0) || (ofs == -1))) {
|
2011-07-01 00:13:42 +00:00
|
|
|
cacheable = true;
|
2011-02-09 01:19:39 +00:00
|
|
|
bufferptr p(len);
|
|
|
|
memcpy(p.c_str(), data, len);
|
2011-07-07 22:04:26 +00:00
|
|
|
bufferlist& bl = info.data;
|
2011-02-09 01:19:39 +00:00
|
|
|
bl.append(p);
|
2011-07-07 22:04:26 +00:00
|
|
|
info.meta.size = bl.length();
|
|
|
|
info.status = 0;
|
|
|
|
info.flags = CACHE_FLAG_DATA;
|
2011-02-09 01:19:39 +00:00
|
|
|
}
|
2011-12-29 00:33:14 +00:00
|
|
|
int ret = T::put_obj_data(ctx, obj, data, ofs, len, exclusive);
|
2011-07-07 22:04:26 +00:00
|
|
|
if (cacheable) {
|
2011-10-25 23:23:08 +00:00
|
|
|
string name = normal_name(bucket, oid);
|
2011-07-07 22:04:26 +00:00
|
|
|
if (ret >= 0) {
|
|
|
|
cache.put(name, info);
|
2012-11-13 21:06:22 +00:00
|
|
|
int r = distribute_cache(name, obj, info, UPDATE_OBJ);
|
2011-07-07 22:04:26 +00:00
|
|
|
if (r < 0)
|
2012-03-27 17:41:12 +00:00
|
|
|
mydout(0) << "ERROR: failed to distribute cache for " << obj << dendl;
|
2011-07-07 22:04:26 +00:00
|
|
|
} else {
|
|
|
|
cache.remove(name);
|
|
|
|
}
|
2011-07-01 00:13:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2011-02-09 01:19:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
2012-11-13 20:09:05 +00:00
|
|
|
int RGWCache<T>::obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime,
|
|
|
|
uint64_t *pepoch, map<string, bufferlist> *attrs,
|
|
|
|
bufferlist *first_chunk)
|
2011-02-09 01:19:39 +00:00
|
|
|
{
|
2011-10-25 23:23:08 +00:00
|
|
|
rgw_bucket bucket;
|
|
|
|
string oid;
|
|
|
|
normalize_bucket_and_obj(obj.bucket, obj.object, bucket, oid);
|
|
|
|
if (bucket.name[0] != '.')
|
2012-11-13 20:09:05 +00:00
|
|
|
return T::obj_stat(ctx, obj, psize, pmtime, pepoch, attrs, first_chunk);
|
2011-02-09 01:19:39 +00:00
|
|
|
|
2011-10-25 23:23:08 +00:00
|
|
|
string name = normal_name(bucket, oid);
|
2011-02-09 01:19:39 +00:00
|
|
|
|
2011-03-16 17:45:43 +00:00
|
|
|
uint64_t size;
|
2011-02-09 01:19:39 +00:00
|
|
|
time_t mtime;
|
2012-11-13 20:09:05 +00:00
|
|
|
uint64_t epoch;
|
2011-02-09 01:19:39 +00:00
|
|
|
|
2011-07-07 22:04:26 +00:00
|
|
|
ObjectCacheInfo info;
|
2011-10-21 23:14:11 +00:00
|
|
|
int r = cache.get(name, info, CACHE_FLAG_META | CACHE_FLAG_XATTRS);
|
2011-02-09 01:19:39 +00:00
|
|
|
if (r == 0) {
|
2011-07-07 22:04:26 +00:00
|
|
|
if (info.status < 0)
|
|
|
|
return info.status;
|
|
|
|
|
|
|
|
size = info.meta.size;
|
|
|
|
mtime = info.meta.mtime;
|
2012-11-13 20:09:05 +00:00
|
|
|
epoch = info.epoch;
|
2011-02-09 01:19:39 +00:00
|
|
|
goto done;
|
|
|
|
}
|
2012-11-13 20:09:05 +00:00
|
|
|
r = T::obj_stat(ctx, obj, &size, &mtime, &epoch, &info.xattrs, first_chunk);
|
2011-07-07 22:04:26 +00:00
|
|
|
if (r < 0) {
|
|
|
|
if (r == -ENOENT) {
|
|
|
|
info.status = r;
|
|
|
|
cache.put(name, info);
|
|
|
|
}
|
2011-02-09 01:19:39 +00:00
|
|
|
return r;
|
2011-07-07 22:04:26 +00:00
|
|
|
}
|
|
|
|
info.status = 0;
|
2012-11-13 20:09:05 +00:00
|
|
|
info.epoch = epoch;
|
2011-07-07 22:04:26 +00:00
|
|
|
info.meta.mtime = mtime;
|
|
|
|
info.meta.size = size;
|
2011-10-21 23:14:11 +00:00
|
|
|
info.flags = CACHE_FLAG_META | CACHE_FLAG_XATTRS;
|
2011-07-07 22:04:26 +00:00
|
|
|
cache.put(name, info);
|
2011-02-09 01:19:39 +00:00
|
|
|
done:
|
|
|
|
if (psize)
|
|
|
|
*psize = size;
|
|
|
|
if (pmtime)
|
|
|
|
*pmtime = mtime;
|
2012-11-13 20:09:05 +00:00
|
|
|
if (pepoch)
|
|
|
|
*pepoch = epoch;
|
2011-10-21 23:14:11 +00:00
|
|
|
if (attrs)
|
|
|
|
*attrs = info.xattrs;
|
2011-02-09 01:19:39 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-01 00:13:42 +00:00
|
|
|
template <class T>
|
2012-11-13 21:06:22 +00:00
|
|
|
int RGWCache<T>::distribute_cache(const string& normal_name, rgw_obj& obj, ObjectCacheInfo& obj_info, int op)
|
2011-07-01 00:13:42 +00:00
|
|
|
{
|
|
|
|
RGWCacheNotifyInfo info;
|
|
|
|
|
2011-07-11 23:55:05 +00:00
|
|
|
info.op = op;
|
2011-07-07 22:04:26 +00:00
|
|
|
|
|
|
|
info.obj_info = obj_info;
|
2011-07-01 00:13:42 +00:00
|
|
|
info.obj = obj;
|
2011-07-07 22:04:26 +00:00
|
|
|
bufferlist bl;
|
2011-07-01 00:13:42 +00:00
|
|
|
::encode(info, bl);
|
2012-06-18 20:25:44 +00:00
|
|
|
int ret = T::distribute(normal_name, bl);
|
2011-07-01 00:13:42 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
int RGWCache<T>::watch_cb(int opcode, uint64_t ver, bufferlist& bl)
|
|
|
|
{
|
|
|
|
RGWCacheNotifyInfo info;
|
|
|
|
|
|
|
|
try {
|
|
|
|
bufferlist::iterator iter = bl.begin();
|
|
|
|
::decode(info, iter);
|
2011-09-02 20:26:21 +00:00
|
|
|
} catch (buffer::end_of_buffer& err) {
|
2012-03-27 17:41:12 +00:00
|
|
|
mydout(0) << "ERROR: got bad notification" << dendl;
|
2011-07-01 00:13:42 +00:00
|
|
|
return -EIO;
|
2011-09-02 20:26:21 +00:00
|
|
|
} catch (buffer::error& err) {
|
2012-03-27 17:41:12 +00:00
|
|
|
mydout(0) << "ERROR: buffer::error" << dendl;
|
2011-09-02 20:26:21 +00:00
|
|
|
return -EIO;
|
2011-07-01 00:13:42 +00:00
|
|
|
}
|
|
|
|
|
2012-05-01 23:47:32 +00:00
|
|
|
rgw_bucket bucket;
|
|
|
|
string oid;
|
|
|
|
normalize_bucket_and_obj(info.obj.bucket, info.obj.object, bucket, oid);
|
|
|
|
string name = normal_name(bucket, oid);
|
2011-07-11 21:26:16 +00:00
|
|
|
|
2011-07-01 00:13:42 +00:00
|
|
|
switch (info.op) {
|
2011-07-07 22:04:26 +00:00
|
|
|
case UPDATE_OBJ:
|
2011-07-11 21:26:16 +00:00
|
|
|
cache.put(name, info.obj_info);
|
2011-07-01 00:13:42 +00:00
|
|
|
break;
|
2011-07-11 23:55:05 +00:00
|
|
|
case REMOVE_OBJ:
|
|
|
|
cache.remove(name);
|
|
|
|
break;
|
2011-07-01 00:13:42 +00:00
|
|
|
default:
|
2012-03-27 17:41:12 +00:00
|
|
|
mydout(0) << "WARNING: got unknown notification op: " << info.op << dendl;
|
2011-07-01 00:13:42 +00:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-02-09 01:19:39 +00:00
|
|
|
#endif
|