]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
Merge branch 'wip-admin-rest'
authorYehuda Sadeh <yehuda@inktank.com>
Mon, 8 Oct 2012 21:30:17 +0000 (14:30 -0700)
committerYehuda Sadeh <yehuda@inktank.com>
Mon, 8 Oct 2012 21:30:17 +0000 (14:30 -0700)
Conflicts:
doc/radosgw/index.rst
src/rgw/rgw_admin.cc
src/rgw/rgw_main.cc
src/rgw/rgw_op.cc
src/rgw/rgw_op.h
src/rgw/rgw_rest.cc
src/rgw/rgw_rest.h
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_rest_s3.h
src/rgw/rgw_rest_swift.cc
src/rgw/rgw_rest_swift.h
src/rgw/rgw_swift_auth.cc
src/rgw/rgw_swift_auth.h

Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
20 files changed:
1  2 
doc/radosgw/index.rst
src/Makefile.am
src/common/config_opts.h
src/rgw/rgw_admin.cc
src/rgw/rgw_common.cc
src/rgw/rgw_common.h
src/rgw/rgw_main.cc
src/rgw/rgw_op.cc
src/rgw/rgw_op.h
src/rgw/rgw_rest.cc
src/rgw/rgw_rest.h
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_rest_s3.h
src/rgw/rgw_rest_swift.cc
src/rgw/rgw_rest_swift.h
src/rgw/rgw_rest_usage.cc
src/rgw/rgw_swift_auth.cc
src/rgw/rgw_swift_auth.h
src/rgw/rgw_usage.cc
src/test/cli/radosgw-admin/help.t

index 1f3f9a9cb06fc0fb0f35c0908b35f260d92110f0,42ed8cdde040e7b88926ef1ecd4ab10f0e7ceab2..feaf53915983c72c73ee500a64ec259f7e425679
@@@ -40,5 -26,4 +40,6 @@@ one API and retrieve it with the other
        Config Reference <config-ref>
        S3 API <s3>
        Swift API <swift/index>
-       
+       Admin API <admin/index>
 +      troubleshooting
++      
diff --cc src/Makefile.am
Simple merge
Simple merge
index c39e74027609982304967a355e773a8ab3ddc24f,d67598de61506e944a6ddce89328aecd47253922..ad58f78807bb6358a0fec2fabb654bf5fcec7c29
@@@ -151,7 -150,8 +155,9 @@@ enum 
    OPT_OBJECT_RM,
    OPT_GC_LIST,
    OPT_GC_PROCESS,
 +  OPT_CLUSTER_INFO,
+   OPT_CAPS_ADD,
+   OPT_CAPS_RM,
  };
  
  static uint32_t str_to_perm(const char *str)
@@@ -224,8 -224,8 +230,9 @@@ static int get_cmd(const char *cmd, con
        strcmp(cmd, "log") == 0 ||
        strcmp(cmd, "usage") == 0 ||
        strcmp(cmd, "object") == 0 ||
 +      strcmp(cmd, "cluster") == 0 ||
        strcmp(cmd, "temp") == 0 ||
+       strcmp(cmd, "caps") == 0 ||
        strcmp(cmd, "gc") == 0) {
      *need_more = true;
      return 0;
@@@ -558,49 -554,18 +572,18 @@@ enum ObjectKeyType 
    KEY_TYPE_S3,
  };
  
- static void parse_date(string& date, uint64_t *epoch, string *out_date = NULL, string *out_time = NULL)
- {
-   struct tm tm;
-   memset(&tm, 0, sizeof(tm));
-   const char *p = strptime(date.c_str(), "%Y-%m-%d", &tm);
-   if (p) {
-     if (*p == ' ') {
-       p++;
-       strptime(p, " %H:%M:%S", &tm);
-     }
-   } else {
-     return;
-   }
-   time_t t = timegm(&tm);
-   if (epoch)
-     *epoch = (uint64_t)t;
-   if (out_date) {
-     char buf[32];
-     strftime(buf, sizeof(buf), "%F", &tm);
-     *out_date = buf;
-   }
-   if (out_time) {
-     char buf[32];
-     strftime(buf, sizeof(buf), "%T", &tm);
-     *out_time = buf;
-   }
- }
 -static int remove_object(rgw_bucket& bucket, std::string& object)
 +static int remove_object(RGWRados *store, rgw_bucket& bucket, std::string& object)
  {
    int ret = -EINVAL;
 -  RGWRadosCtx *rctx = new RGWRadosCtx();
 +  RGWRadosCtx *rctx = new RGWRadosCtx(store);
    rgw_obj obj(bucket,object);
  
 -  ret = rgwstore->delete_obj(rctx, obj);
 +  ret = store->delete_obj(rctx, obj);
  
    return ret;
  }
  
--static int remove_bucket(rgw_bucket& bucket, bool delete_children)
++static int remove_bucket(RGWRados *store, rgw_bucket& bucket, bool delete_children)
  {
    int ret;
    map<RGWObjCategory, RGWBucketStats> stats;
@@@ -732,9 -672,9 +687,10 @@@ int main(int argc, char **argv
    int purge_keys = false;
    int yes_i_really_mean_it = false;
    int delete_child_objects = false;
 +  int fix = false;
    int max_buckets = -1;
    map<string, bool> categories;
+   string caps;
  
    std::string val;
    std::ostringstream errs;
        // do nothing
      } else if (ceph_argparse_binary_flag(args, i, &yes_i_really_mean_it, NULL, "--yes-i-really-mean-it", (char*)NULL)) {
        // do nothing
 +    } else if (ceph_argparse_binary_flag(args, i, &fix, NULL, "--fix", (char*)NULL)) {
 +      // do nothing
+     } else if (ceph_argparse_witharg(args, i, &val, "--caps", (char*)NULL)) {
+       caps = val;
      } else {
        ++i;
      }
  
    user_modify_op = (opt_cmd == OPT_USER_MODIFY || opt_cmd == OPT_SUBUSER_MODIFY ||
                      opt_cmd == OPT_SUBUSER_CREATE || opt_cmd == OPT_SUBUSER_RM ||
-                     opt_cmd == OPT_KEY_CREATE || opt_cmd == OPT_KEY_RM || opt_cmd == OPT_USER_RM);
+                     opt_cmd == OPT_KEY_CREATE || opt_cmd == OPT_KEY_RM || opt_cmd == OPT_USER_RM ||
+                   opt_cmd == OPT_CAPS_ADD || opt_cmd == OPT_CAPS_RM);
  
 -  RGWStoreManager store_manager;
 -  store = store_manager.init(g_ceph_context, false);
 +  store = RGWStoreManager::get_storage(g_ceph_context, false);
    if (!store) {
      cerr << "couldn't init storage provider" << std::endl;
      return 5; //EIO
@@@ -1448,7 -1409,7 +1423,7 @@@ next
  
        if (m.size() > 0 && purge_data) {
          for (std::map<string, RGWBucketEnt>::iterator it = m.begin(); it != m.end(); it++) {
--          ret = remove_bucket(((*it).second).bucket, true);
++          ret = remove_bucket(store, ((*it).second).bucket, true);
  
            if (ret < 0)
              return ret;
      uint64_t start_epoch = 0;
      uint64_t end_epoch = (uint64_t)-1;
  
-     parse_date(start_date, &start_epoch);
-     parse_date(end_date, &end_epoch);
-     uint32_t max_entries = 1000;
-     bool is_truncated = true;
-     RGWUsageIter usage_iter;
-     map<rgw_user_bucket, rgw_usage_log_entry> usage;
-     formatter->open_object_section("usage");
-     if (show_log_entries) {
-       formatter->open_array_section("entries");
-     }
-     string last_owner;
-     bool user_section_open = false;
-     map<string, rgw_usage_log_entry> summary_map;
-     while (is_truncated) {
-       int ret = store->read_usage(user_id, start_epoch, end_epoch, max_entries,
-                                      &is_truncated, usage_iter, usage);
-       if (ret == -ENOENT) {
-         ret = 0;
-         is_truncated = false;
-       }
-       if (ret < 0) {
-         cerr << "ERROR: read_usage() returned ret=" << ret << std::endl;
-         break;
-       }
-       map<rgw_user_bucket, rgw_usage_log_entry>::iterator iter;
-       for (iter = usage.begin(); iter != usage.end(); ++iter) {
-         const rgw_user_bucket& ub = iter->first;
-         const rgw_usage_log_entry& entry = iter->second;
-         if (show_log_entries) {
-           if (ub.user.compare(last_owner) != 0) {
-             if (user_section_open) {
-               formatter->close_section();
-               formatter->close_section();
-             }
-             formatter->open_object_section("user");
-             formatter->dump_string("owner", ub.user);
-             formatter->open_array_section("buckets");
-             user_section_open = true;
-             last_owner = ub.user;
-           }
-           formatter->open_object_section("bucket");
-           formatter->dump_string("bucket", ub.bucket);
-           utime_t ut(entry.epoch, 0);
-           ut.gmtime(formatter->dump_stream("time"));
-           formatter->dump_int("epoch", entry.epoch);
-         dump_usage_categories_info(formatter, entry, categories);
-           formatter->close_section(); // bucket
-           formatter->flush(cout);
-         }
-         summary_map[ub.user].aggregate(entry, &categories);
-       }
+     int ret = parse_date(start_date, &start_epoch);
+     if (ret < 0) {
+       cerr << "ERROR: failed to parse start date" << std::endl;
+       return 1;
      }
-     if (show_log_entries) {
-       if (user_section_open) {
-         formatter->close_section(); // buckets
-         formatter->close_section(); //user
-       }
-       formatter->close_section(); // entries
+     ret = parse_date(end_date, &end_epoch);
+     if (ret < 0) {
+       cerr << "ERROR: failed to parse end date" << std::endl;
+       return 1;
      }
  
-     if (show_log_sum) {
-       formatter->open_array_section("summary");
-       map<string, rgw_usage_log_entry>::iterator siter;
-       for (siter = summary_map.begin(); siter != summary_map.end(); ++siter) {
-         const rgw_usage_log_entry& entry = siter->second;
-         formatter->open_object_section("user");
-         formatter->dump_string("user", siter->first);
-       dump_usage_categories_info(formatter, entry, categories);
-       rgw_usage_data total_usage;
-       entry.sum(total_usage, categories);
-         formatter->open_object_section("total");
-         formatter->dump_int("bytes_sent", total_usage.bytes_sent);
-         formatter->dump_int("bytes_received", total_usage.bytes_received);
-         formatter->dump_int("ops", total_usage.ops);
-         formatter->dump_int("successful_ops", total_usage.successful_ops);
-         formatter->close_section(); // total
-         formatter->close_section(); // user
-         formatter->flush(cout);
-       }
+     RGWStreamFlusher f(formatter, cout);
  
-       formatter->close_section(); // summary
 -    ret = RGWUsage::show(rgwstore, user_id, start_epoch, end_epoch,
 -                           show_log_entries, show_log_sum, &categories,
 -                           f);
++    ret = RGWUsage::show(store, user_id, start_epoch, end_epoch,
++                       show_log_entries, show_log_sum, &categories,
++                       f);
+     if (ret < 0) {
+       cerr << "ERROR: failed to show usage" << std::endl;
+       return 1;
      }
-     formatter->close_section(); // usage
-     formatter->flush(cout);
    }
  
    if (opt_cmd == OPT_USAGE_TRIM) {
      uint64_t start_epoch = 0;
      uint64_t end_epoch = (uint64_t)-1;
  
-     parse_date(start_date, &start_epoch);
-     parse_date(end_date, &end_epoch);
+     int ret = parse_date(start_date, &start_epoch);
+     if (ret < 0) {
+       cerr << "ERROR: failed to parse start date" << std::endl;
+       return 1;
+     }
+     ret = parse_date(end_date, &end_epoch);
+     if (ret < 0) {
+       cerr << "ERROR: failed to parse end date" << std::endl;
+       return 1;
+     }
  
-     int ret = store->trim_usage(user_id, start_epoch, end_epoch);
 -    ret = RGWUsage::trim(rgwstore, user_id, start_epoch, end_epoch);
++    ret = RGWUsage::trim(store, user_id, start_epoch, end_epoch);
      if (ret < 0) {
        cerr << "ERROR: read_usage() returned ret=" << ret << std::endl;
        return 1;
      }
    }
  
 +  if (opt_cmd == OPT_BUCKET_CHECK) {
 +    map<RGWObjCategory, RGWBucketStats> existing_stats;
 +    map<RGWObjCategory, RGWBucketStats> calculated_stats;
 +
 +    int r = store->bucket_check_index(bucket, &existing_stats, &calculated_stats);
 +    if (r < 0) {
 +      cerr << "failed to check index err=" << cpp_strerror(-r) << std::endl;
 +      return r;
 +    }
 +
 +    formatter->open_object_section("check_result");
 +    formatter->open_object_section("existing_header");
 +    dump_bucket_usage(existing_stats, formatter);
 +    formatter->close_section();
 +    formatter->open_object_section("calculated_header");
 +    dump_bucket_usage(calculated_stats, formatter);
 +    formatter->close_section();
 +    formatter->close_section();
 +    formatter->flush(cout);
 +
 +    if (fix) {
 +      r = store->bucket_rebuild_index(bucket);
 +      if (r < 0) {
 +        cerr << "failed to rebuild index err=" << cpp_strerror(-r) << std::endl;
 +        return r;
 +      }
 +    }
 +  }
 +
    if (opt_cmd == OPT_BUCKET_RM) {
--    int ret = remove_bucket(bucket, delete_child_objects);
++    int ret = remove_bucket(store, bucket, delete_child_objects);
  
      if (ret < 0) {
        cerr << "ERROR: bucket remove returned: " << cpp_strerror(-ret) << std::endl;
Simple merge
Simple merge
index 5af00f8d3fd7a5ae738482cba5a4beddeb474da7,300906b8414b42549eeaeea911ff9cef860ea9c4..c5f47068aa5fc9bac157bc5f3c2189cc4773475d
@@@ -179,9 -183,10 +184,10 @@@ class RGWProcess 
    uint64_t max_req_id;
  
  public:
-   RGWProcess(CephContext *cct, RGWRados *rgwstore, int num_threads)
 -  RGWProcess(CephContext *cct, int num_threads, RGWREST *_rest)
 -    : m_tp(cct, "RGWProcess::m_tp", num_threads),
++  RGWProcess(CephContext *cct, RGWRados *rgwstore, int num_threads, RGWREST *_rest)
 +    : store(rgwstore), m_tp(cct, "RGWProcess::m_tp", num_threads),
        req_throttle(cct, "rgw_ops", num_threads * 2),
+       rest(_rest),
        req_wq(this, g_conf->rgw_op_thread_timeout,
             g_conf->rgw_op_thread_suicide_timeout, &m_tp),
        max_req_id(0) {}
@@@ -265,14 -270,14 +271,14 @@@ void RGWProcess::handle_request(RGWRequ
  
    RGWOp *op = NULL;
    int init_error = 0;
-   RGWHandler *handler = rest.get_handler(store, s, fcgx, &init_error);
 -  RGWHandler *handler = rest->get_handler(s, &client_io, &init_error);
++  RGWHandler *handler = rest->get_handler(store, s, &client_io, &init_error);
    if (init_error != 0) {
      abort_early(s, init_error);
      goto done;
    }
  
    req->log(s, "getting op");
--  op = handler->get_op();
++  op = handler->get_op(store);
    if (!op) {
      abort_early(s, -ERR_METHOD_NOT_ALLOWED);
      goto done;
  
    req->log(s, "executing");
    op->execute();
+   op->complete();
  done:
 -  rgw_log_op(s, (op ? op->name() : "unknown"));
 +  rgw_log_op(store, s, (op ? op->name() : "unknown"));
  
    int http_ret = s->err.http_ret;
  
    req->log_format(s, "http status=%d", http_ret);
  
-   handler->put_op(op);
+   if (handler)
+     handler->put_op(op);
+   rest->put_handler(handler);
 -  rgwstore->destroy_context(s->obj_ctx);
 +  store->destroy_context(s->obj_ctx);
    FCGX_Finish_r(fcgx);
  
    dout(1) << "====== req done req=" << hex << req << dec << " http_status=" << http_ret << " ======" << dendl;
@@@ -436,9 -444,35 +445,35 @@@ int main(int argc, const char **argv
    if (r) 
      return 1;
  
 -  rgw_log_usage_init(g_ceph_context);
 +  rgw_log_usage_init(g_ceph_context, store);
  
-   RGWProcess process(g_ceph_context, store, g_conf->rgw_thread_pool_size);
+   RGWREST rest;
+   list<string> apis;
+   get_str_list(g_conf->rgw_enable_apis, apis);
+   map<string, bool> apis_map;
+   for (list<string>::iterator li = apis.begin(); li != apis.end(); ++li) {
+     apis_map[*li] = true;
+   }
+   if (apis_map.count("s3") > 0)
+     rest.register_default_mgr(new RGWRESTMgr_S3);
+   if (apis_map.count("swift") > 0)
+     rest.register_resource(g_conf->rgw_swift_url_prefix, new RGWRESTMgr_SWIFT);
+   if (apis_map.count("swift_auth") > 0)
+     rest.register_resource(g_conf->rgw_swift_auth_entry, new RGWRESTMgr_SWIFT_Auth);
+   if (apis_map.count("admin") > 0) {
+     RGWRESTMgr_Admin *admin_resource = new RGWRESTMgr_Admin;
+     admin_resource->register_resource("usage", new RGWRESTMgr_Usage);
+     rest.register_resource(g_conf->rgw_admin_entry, admin_resource);
+   }
 -  RGWProcess process(g_ceph_context, g_conf->rgw_thread_pool_size, &rest);
++  RGWProcess process(g_ceph_context, store, g_conf->rgw_thread_pool_size, &rest);
    process.run();
  
    rgw_log_usage_finalize();
index 8510055e6f4c2fa3c6f1e73c7d6aee7abb27b062,524e01e38b683d1689dd395acd2c79460ea6dcb3..71ad6d19fa2fee9b5b3134adadd305d055e94fe0
@@@ -641,9 -638,9 +637,9 @@@ void RGWListBuckets::execute(
  {
    ret = get_params();
    if (ret < 0)
-     goto done;
+     return;
  
 -  ret = rgw_read_user_buckets(s->user.user_id, buckets, !!(s->prot_flags & RGW_REST_SWIFT));
 +  ret = rgw_read_user_buckets(store, s->user.user_id, buckets, !!(s->prot_flags & RGW_REST_SWIFT));
    if (ret < 0) {
      /* hmm.. something wrong here.. the user was authenticated, so it
         should exist, just try to recreate */
@@@ -764,13 -754,10 +753,10 @@@ void RGWListBucket::execute(
  
    ret = get_params();
    if (ret < 0)
-     goto done;
+     return;
  
 -  ret = rgwstore->list_objects(s->bucket, max, prefix, delimiter, marker, objs, common_prefixes,
 +  ret = store->list_objects(s->bucket, max, prefix, delimiter, marker, objs, common_prefixes,
                                 !!(s->prot_flags & RGW_REST_SWIFT), no_ns, &is_truncated, NULL);
- done:
-   send_response();
  }
  
  int RGWCreateBucket::verify_permission()
@@@ -803,10 -790,10 +789,10 @@@ void RGWCreateBucket::execute(
  
    ret = get_params();
    if (ret < 0)
-     goto done;
+     return;
  
    s->bucket_owner = s->user.user_id;
 -  r = get_policy_from_attr(s->cct, s->obj_ctx, &old_policy, obj);
 +  r = get_policy_from_attr(s->cct, store, s->obj_ctx, &old_policy, obj);
    if (r >= 0)  {
      if (old_policy.get_owner().get_id().compare(s->user.user_id) != 0) {
        ret = -EEXIST;
@@@ -1314,9 -1295,9 +1293,9 @@@ void RGWPutMetadata::execute(
    rgw_get_request_metadata(s, attrs);
  
    /* check if obj exists, read orig attrs */
 -  ret = get_obj_attrs(s, obj, orig_attrs, NULL);
 +  ret = get_obj_attrs(store, s, obj, orig_attrs, NULL);
    if (ret < 0)
-     goto done;
+     return;
  
    /* only remove meta attrs */
    for (iter = orig_attrs.begin(); iter != orig_attrs.end(); ++iter) {
      policy.encode(bl);
      attrs[RGW_ATTR_ACL] = bl;
    }
 -  ret = rgwstore->set_attrs(s->obj_ctx, obj, attrs, &rmattrs);
 +  ret = store->set_attrs(s->obj_ctx, obj, attrs, &rmattrs);
- done:
-   send_response();
  }
  
  int RGWDeleteObj::verify_permission()
@@@ -1351,11 -1329,9 +1327,9 @@@ void RGWDeleteObj::execute(
    ret = -EINVAL;
    rgw_obj obj(s->bucket, s->object_str);
    if (s->object) {
 -    rgwstore->set_atomic(s->obj_ctx, obj);
 -    ret = rgwstore->delete_obj(s->obj_ctx, obj);
 +    store->set_atomic(s->obj_ctx, obj);
 +    ret = store->delete_obj(s->obj_ctx, obj);
    }
-   send_response();
  }
  
  bool RGWCopyObj::parse_copy_location(const char *src, string& bucket_name, string& object)
@@@ -1670,13 -1633,11 +1638,11 @@@ void RGWInitMultipart::execute(
  
      obj.init_ns(s->bucket, tmp_obj_name, mp_ns);
      // the meta object will be indexed with 0 size, we c
 -    ret = rgwstore->put_obj_meta(s->obj_ctx, obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MULTIMETA, true, NULL, NULL, NULL);
 +    ret = store->put_obj_meta(s->obj_ctx, obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MULTIMETA, true, NULL, NULL, NULL, NULL);
    } while (ret == -EEXIST);
- done:
-   send_response();
  }
  
 -static int get_multiparts_info(struct req_state *s, string& meta_oid, map<uint32_t, RGWUploadPartInfo>& parts,
 +static int get_multiparts_info(RGWRados *store, struct req_state *s, string& meta_oid, map<uint32_t, RGWUploadPartInfo>& parts,
                                 RGWAccessControlPolicy& policy, map<string, bufferlist>& attrs)
  {
    map<string, bufferlist> parts_map;
@@@ -1836,10 -1797,10 +1802,10 @@@ void RGWCompleteMultipart::execute(
    attrs[RGW_ATTR_ETAG] = etag_bl;
  
    target_obj.init(s->bucket, s->object_str);
 -  rgwstore->set_atomic(s->obj_ctx, target_obj);
 -  ret = rgwstore->put_obj_meta(s->obj_ctx, target_obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, false, NULL, NULL, NULL);
 +  store->set_atomic(s->obj_ctx, target_obj);
 +  ret = store->put_obj_meta(s->obj_ctx, target_obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, false, NULL, NULL, NULL, NULL);
    if (ret < 0)
-     goto done;
+     return;
    
    for (obj_iter = obj_parts.begin(); obj_iter != obj_parts.end(); ++obj_iter) {
      string oid = mp.get_part(obj_iter->second.num);
  
    manifest.obj_size = ofs;
  
 -  rgwstore->set_atomic(s->obj_ctx, target_obj);
 +  store->set_atomic(s->obj_ctx, target_obj);
  
 -  ret = rgwstore->put_obj_meta(s->obj_ctx, target_obj, ofs, NULL, attrs,
 -                               RGW_OBJ_CATEGORY_MAIN, false, NULL, NULL, &manifest);
 +  ret = store->put_obj_meta(s->obj_ctx, target_obj, ofs, NULL, attrs,
 +                            RGW_OBJ_CATEGORY_MAIN, false, NULL, NULL, &manifest, NULL);
    if (ret < 0)
-     goto done;
+     return;
  
    // remove the upload obj
    meta_obj.init_ns(s->bucket, meta_oid, mp_ns);
 -  rgwstore->delete_obj(s->obj_ctx, meta_obj);
 +  store->delete_obj(s->obj_ctx, meta_obj);
- done:
-   send_response();
  }
  
  int RGWAbortMultipart::verify_permission()
@@@ -1900,17 -1858,17 +1863,17 @@@ void RGWAbortMultipart::execute(
    mp.init(s->object_str, upload_id); 
    meta_oid = mp.get_meta();
  
 -  ret = get_multiparts_info(s, meta_oid, obj_parts, policy, attrs);
 +  ret = get_multiparts_info(store, s, meta_oid, obj_parts, policy, attrs);
    if (ret < 0)
-     goto done;
+     return;
  
    for (obj_iter = obj_parts.begin(); obj_iter != obj_parts.end(); ++obj_iter) {
      string oid = mp.get_part(obj_iter->second.num);
      rgw_obj obj;
      obj.init_ns(s->bucket, oid, mp_ns);
 -    ret = rgwstore->delete_obj(s->obj_ctx, obj);
 +    ret = store->delete_obj(s->obj_ctx, obj);
      if (ret < 0 && ret != -ENOENT)
-       goto done;
+       return;
    }
    // and also remove the metadata obj
    meta_obj.init_ns(s->bucket, meta_oid, mp_ns);
@@@ -1944,10 -1899,7 +1904,7 @@@ void RGWListMultipart::execute(
    mp.init(s->object_str, upload_id);
    meta_oid = mp.get_meta();
  
 -  ret = get_multiparts_info(s, meta_oid, parts, policy, xattrs);
 +  ret = get_multiparts_info(store, s, meta_oid, parts, policy, xattrs);
- done:
-   send_response();
  }
  
  int RGWListBucketMultiparts::verify_permission()
@@@ -2077,9 -2027,12 +2032,13 @@@ error
  
  }
  
- int RGWHandler::init(RGWRados *_store, struct req_state *_s, FCGX_Request *fcgx)
+ RGWHandler::~RGWHandler()
+ {
+ }
 -int RGWHandler::init(struct req_state *_s, RGWClientIO *cio)
++int RGWHandler::init(RGWRados *_store, struct req_state *_s, RGWClientIO *cio)
  {
 +  store = _store;
    s = _s;
  
    if (s->cct->_conf->subsys.should_gather(ceph_subsys_rgw, 20)) {
@@@ -2104,3 -2059,41 +2065,41 @@@ int RGWHandler::do_read_permissions(RGW
    return ret;
  }
  
 -RGWOp *RGWHandler::get_op()
 -    op->init(s, this);
++RGWOp *RGWHandler::get_op(RGWRados *store)
+ {
+   RGWOp *op;
+   switch (s->op) {
+    case OP_GET:
+      op = op_get();
+      break;
+    case OP_PUT:
+      op = op_put();
+      break;
+    case OP_DELETE:
+      op = op_delete();
+      break;
+    case OP_HEAD:
+      op = op_head();
+      break;
+    case OP_POST:
+      op = op_post();
+      break;
+    case OP_COPY:
+      op = op_copy();
+      break;
+    default:
+      return NULL;
+   }
+   if (op) {
++    op->init(store, s, this);
+   }
+   return op;
+ }
+ void RGWHandler::put_op(RGWOp *op)
+ {
+   delete op;
+ }
index 624cac1f73beb736b03a6b8aa177a75461462e40,86e3e67baa37e658bac103da2a7a74215825274a..f8eb41f1835bfd2014cd334637394a7a13fc4edd
@@@ -121,11 -116,7 +118,7 @@@ protected
    RGWUserBuckets buckets;
  
  public:
-   virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
-     RGWOp::init(store, s, h);
-     buckets.clear();
-   }
--  RGWListBuckets() {}
++  RGWListBuckets() : ret(0) {}
  
    int verify_permission();
    void execute();
@@@ -232,10 -207,9 +209,9 @@@ public
  
    int verify_permission();
    void execute();
 -  virtual void init(struct req_state *s, RGWHandler *h) {
 -    RGWOp::init(s, h);
 +  virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
 +    RGWOp::init(store, s, h);
      policy.set_ctx(s->cct);
-     ret = 0;
    }
    virtual int get_params() { return 0; }
    virtual void send_response() = 0;
@@@ -247,12 -221,10 +223,8 @@@ protected
    int ret;
  
  public:
-   RGWDeleteBucket() {}
 -  RGWDeleteBucket() {
 -    ret = 0;
 -  }
++  RGWDeleteBucket() : ret(0) {}
  
-   virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
-     RGWOp::init(store, s, h);
-     ret = 0;
-   }
    int verify_permission();
    void execute();
  
@@@ -300,9 -267,12 +269,12 @@@ public
      ofs = 0;
      supplied_md5_b64 = NULL;
      supplied_etag = NULL;
-     etag = "";
      chunked_upload = false;
      obj_manifest = NULL;
 -  virtual void init(struct req_state *s, RGWHandler *h) {
 -    RGWOp::init(s, h);
+   }
++  virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
++    RGWOp::init(store, s, h);
      policy.set_ctx(s->cct);
    }
  
@@@ -326,12 -296,13 +298,13 @@@ protected
    RGWAccessControlPolicy policy;
  
  public:
-   RGWPutMetadata() {}
+   RGWPutMetadata() {
+     has_policy = false;
+     ret = 0;
+   }
  
 -  virtual void init(struct req_state *s, RGWHandler *h) {
 -    RGWOp::init(s, h);
 +  virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
 +    RGWOp::init(store, s, h);
-     has_policy = false;
-     ret = 0;
      policy.set_ctx(s->cct);
    }
    int verify_permission();
@@@ -347,12 -318,10 +320,8 @@@ protected
    int ret;
  
  public:
-   RGWDeleteObj() {}
 -  RGWDeleteObj() {
 -    ret = 0;
 -  }
++  RGWDeleteObj() : ret(0) {}
  
-   virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
-     RGWOp::init(store, s, h);
-     ret = 0;
-   }
    int verify_permission();
    void execute();
  
@@@ -402,14 -368,15 +368,17 @@@ public
      ofs = 0;
      len = 0;
      end = -1;
++    mod_time = 0;
++    unmod_time = 0;
      mod_ptr = NULL;
      unmod_ptr = NULL;
      ret = 0;
-     attrs.clear();
-     src_bucket.clear();
-     src_object.clear();
      mtime = 0;
      replace_attrs = false;
 -  virtual void init(struct req_state *s, RGWHandler *h) {
 -    RGWOp::init(s, h);
+   }
++  virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
++    RGWOp::init(store, s, h);
      dest_policy.set_ctx(s->cct);
    }
    int verify_permission();
@@@ -427,13 -394,10 +396,8 @@@ protected
    string acls;
  
  public:
-   RGWGetACLs() {}
 -  RGWGetACLs() {
 -    ret = 0;
 -  }
++  RGWGetACLs() : ret(0) {}
  
-   virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
-     RGWOp::init(store, s, h);
-     ret = 0;
-     acls.clear();
-   }
    int verify_permission();
    void execute();
  
@@@ -472,12 -434,12 +434,12 @@@ protected
    RGWAccessControlPolicy policy;
  
  public:
-   RGWInitMultipart() {}
+   RGWInitMultipart() {
+     ret = 0;
+   }
  
 -  virtual void init(struct req_state *s, RGWHandler *h) {
 -    RGWOp::init(s, h);
 +  virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
 +    RGWOp::init(store, s, h);
-     ret = 0;
-     upload_id = "";
      policy.set_ctx(s->cct);
    }
    int verify_permission();
@@@ -520,12 -478,10 +478,8 @@@ protected
    int ret;
  
  public:
-   RGWAbortMultipart() {}
 -  RGWAbortMultipart() {
 -    ret = 0;
 -  }
++  RGWAbortMultipart() : ret(0) {}
  
-   virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
-     RGWOp::init(store, s, h);
-     ret = 0;
-   }
    int verify_permission();
    void execute();
  
@@@ -543,15 -499,14 +497,14 @@@ protected
    RGWAccessControlPolicy policy;
  
  public:
-   RGWListMultipart() {}
-   virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
-     RGWOp::init(store, s, h);
+   RGWListMultipart() {
      ret = 0;
-     upload_id = "";
-     parts.clear();
      max_parts = 1000;
      marker = 0;
 -  virtual void init(struct req_state *s, RGWHandler *h) {
 -    RGWOp::init(s, h);
+   }
++  virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
++    RGWOp::init(store, s, h);
      policy = RGWAccessControlPolicy(s->cct);
    }
    int verify_permission();
@@@ -652,21 -607,12 +605,16 @@@ protected
    int default_max;
  
  public:
-   RGWListBucketMultiparts() {}
+   RGWListBucketMultiparts() {
 -    max_uploads = default_max;
 -    max_uploads = default_max;
+     ret = 0;
+     is_truncated = false;
+   }
 +
 +  virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
 +    RGWOp::init(store, s, h);
-     prefix.clear();
-     marker.clear();
-     next_marker.clear();
 +    max_uploads = default_max;
-     delimiter.clear();
-     max_uploads = default_max;
-     ret = 0;
-     uploads.clear();
-     is_truncated = false;
-     common_prefixes.clear();
 +  }
++
    int verify_permission();
    void execute();
  
@@@ -718,13 -659,20 +662,20 @@@ protected
    struct req_state *s;
  
    int do_read_permissions(RGWOp *op, bool only_bucket);
+   virtual RGWOp *op_get() { return NULL; }
+   virtual RGWOp *op_put() { return NULL; }
+   virtual RGWOp *op_delete() { return NULL; }
+   virtual RGWOp *op_head() { return NULL; }
+   virtual RGWOp *op_post() { return NULL; }
+   virtual RGWOp *op_copy() { return NULL; }
  public:
    RGWHandler() {}
-   virtual ~RGWHandler() {}
-   virtual int init(RGWRados *store, struct req_state *_s, FCGX_Request *fcgx);
+   virtual ~RGWHandler();
 -  virtual int init(struct req_state *_s, RGWClientIO *cio);
++  virtual int init(RGWRados *store, struct req_state *_s, RGWClientIO *cio);
  
-   virtual RGWOp *get_op() = 0;
-   virtual void put_op(RGWOp *op) = 0;
 -  virtual RGWOp *get_op();
++  virtual RGWOp *get_op(RGWRados *store);
+   virtual void put_op(RGWOp *op);
    virtual int read_permissions(RGWOp *op) = 0;
    virtual int authorize() = 0;
  };
index 8b4027e07af75c532dc46613eefaad57c16ae167,478db487f7f76723e942ba36c1b4862ced5c4730..80a080b342d384229bbaef62cf2ea270875e7771
@@@ -963,32 -922,86 +922,86 @@@ RGWRESTMgr *RGWRESTMgr::get_resource_mg
  
  RGWRESTMgr::~RGWRESTMgr()
  {
-   delete m_os_handler;
-   delete m_os_auth_handler;
-   delete m_s3_handler;
+   map<string, RGWRESTMgr *>::iterator iter;
+   for (iter = resource_mgrs.begin(); iter != resource_mgrs.end(); ++iter) {
+     delete iter->second;
+   }
+   delete default_mgr;
  }
  
- RGWHandler *RGWRESTMgr::get_handler(RGWRados *store, struct req_state *s, FCGX_Request *fcgx,
-                                   int *init_error)
+ int RGWREST::preprocess(struct req_state *s, RGWClientIO *cio)
  {
-   RGWHandler *handler;
+   s->cio = cio;
+   s->request_uri = s->env->get("REQUEST_URI");
+   int pos = s->request_uri.find('?');
+   if (pos >= 0) {
+     s->request_params = s->request_uri.substr(pos + 1);
+     s->request_uri = s->request_uri.substr(0, pos);
+   }
+   s->host = s->env->get("HTTP_HOST");
+   if (g_conf->rgw_dns_name.length() && s->host) {
+     string h(s->host);
  
-   *init_error = RGWHandler_REST::preprocess(s, fcgx);
+     ldout(s->cct, 10) << "host=" << s->host << " rgw_dns_name=" << g_conf->rgw_dns_name << dendl;
+     pos = h.find(g_conf->rgw_dns_name);
  
-   if (s->prot_flags & RGW_REST_SWIFT)
-     handler = m_os_handler;
-   else if (s->prot_flags & RGW_REST_SWIFT_AUTH)
-     handler = m_os_auth_handler;
-   else
-     handler = m_s3_handler;
+     if (pos > 0 && h[pos - 1] == '.') {
+       string encoded_bucket = "/";
+       encoded_bucket.append(h.substr(0, pos-1));
+       if (s->request_uri[0] != '/')
+       encoded_bucket.append("/'");
+       encoded_bucket.append(s->request_uri);
+       s->request_uri = encoded_bucket;
+     }
+   }
  
-   handler->init(store, s, fcgx);
+   url_decode(s->request_uri, s->decoded_uri);
+   s->method = s->env->get("REQUEST_METHOD");
+   s->length = s->env->get("CONTENT_LENGTH");
+   if (s->length) {
+     if (*s->length == '\0')
+       return -EINVAL;
+     s->content_length = atoll(s->length);
+   }
  
-   return handler;
+   s->content_type = s->env->get("CONTENT_TYPE");
+   s->http_auth = s->env->get("HTTP_AUTHORIZATION");
+   if (g_conf->rgw_print_continue) {
+     const char *expect = s->env->get("HTTP_EXPECT");
+     s->expect_cont = (expect && !strcasecmp(expect, "100-continue"));
+   }
+   s->op = op_from_method(s->method);
+   init_meta_info(s);
+   return 0;
  }
  
- void RGWHandler_REST::put_op(RGWOp *op)
 -RGWHandler *RGWREST::get_handler(struct req_state *s, RGWClientIO *cio,
++RGWHandler *RGWREST::get_handler(RGWRados *store, struct req_state *s, RGWClientIO *cio,
+                                int *init_error)
  {
-   delete op;
+   RGWHandler *handler;
+   *init_error = preprocess(s, cio);
+   if (*init_error < 0)
+     return NULL;
+   RGWRESTMgr *m = mgr.get_resource_mgr(s, s->decoded_uri);
+   if (!m) {
+     *init_error = -ERR_METHOD_NOT_ALLOWED;
+     return NULL;
+   }
+   handler = m->get_handler(s);
+   if (!handler) {
+     *init_error = -ERR_METHOD_NOT_ALLOWED;
+     return NULL;
+   }
 -  *init_error = handler->init(s, cio);
++  *init_error = handler->init(store, s, cio);
+   if (*init_error < 0)
+     return NULL;
+   return handler;
  }
  
index 369e521c7b9fc8d04cfbbf446f4aad9a8c4dab4a,2750a24c47c82513a0a509ddade8a3175c4e2ca7..c225aa1490a75cc57644f354edff15e0f74da439
@@@ -15,10 -44,10 +44,10 @@@ class RGWGetObj_ObjStore : public RGWGe
  protected:
    bool sent_header;
  public:
-   RGWGetObj_REST() : sent_header(false) {}
+   RGWGetObj_ObjStore() : sent_header(false) {}
  
 -  virtual void init(struct req_state *s, RGWHandler *h) {
 -    RGWGetObj::init(s, h);
 +  virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
 +    RGWGetObj::init(store, s, h);
      sent_header = false;
    }
  
@@@ -151,41 -180,86 +180,86 @@@ public
    int get_params();
  };
  
- class RGWHandler_REST : public RGWHandler {
+ class RGWRESTOp : public RGWOp {
  protected:
-   virtual bool is_acl_op() = 0;
-   virtual bool is_obj_update_op() = 0;
-   virtual RGWOp *get_retrieve_obj_op(bool get_data) = 0;
-   virtual RGWOp *get_retrieve_op(bool get_data) = 0;
-   virtual RGWOp *get_create_op() = 0;
-   virtual RGWOp *get_delete_op() = 0;
-   virtual RGWOp *get_post_op() = 0;
-   virtual RGWOp *get_copy_op() = 0;
+   int http_ret;
+   RGWRESTFlusher flusher;
+ public:
+   RGWRESTOp() : http_ret(0) {}
 -  virtual void init(struct req_state *s, RGWHandler *dialect_handler) {
 -    RGWOp::init(s, dialect_handler);
++  virtual void init(RGWRados *store, struct req_state *s, RGWHandler *dialect_handler) {
++    RGWOp::init(store, s, dialect_handler);
+     flusher.init(s);
+   }
+   virtual void send_response();
+   virtual int check_caps(RGWUserCaps& caps) { return -EPERM; } /* should to be implemented! */
+   virtual int verify_permission();
+ };
  
+ class RGWHandler_ObjStore : public RGWHandler {
+ protected:
+   virtual bool is_obj_update_op() { return false; }
+   virtual RGWOp *op_get() { return NULL; }
+   virtual RGWOp *op_put() { return NULL; }
+   virtual RGWOp *op_delete() { return NULL; }
+   virtual RGWOp *op_head() { return NULL; }
+   virtual RGWOp *op_post() { return NULL; }
+   virtual RGWOp *op_copy() { return NULL; }
+   virtual int validate_bucket_name(const string& bucket);
+   virtual int validate_object_name(const string& object);
+   static int allocate_formatter(struct req_state *s, int default_formatter, bool configurable);
  public:
+   RGWHandler_ObjStore() {}
+   virtual ~RGWHandler_ObjStore() {}
    int read_permissions(RGWOp *op);
-   RGWOp *get_op();
-   void put_op(RGWOp *op);
  
-   static int preprocess(struct req_state *s, FCGX_Request *fcgx);
    virtual int authorize() = 0;
  };
  
- class RGWHandler_REST_SWIFT;
+ class RGWHandler_ObjStore_SWIFT;
  class RGWHandler_SWIFT_Auth;
- class RGWHandler_REST_S3;
+ class RGWHandler_ObjStore_S3;
  
  class RGWRESTMgr {
-   RGWHandler_REST_SWIFT *m_os_handler;
-   RGWHandler_SWIFT_Auth *m_os_auth_handler;
-   RGWHandler_REST_S3 *m_s3_handler;
+ protected:
+   map<string, RGWRESTMgr *> resource_mgrs;
+   multimap<size_t, string> resources_by_size;
+   RGWRESTMgr *default_mgr;
+ public:
+   RGWRESTMgr() : default_mgr(NULL) {}
+   virtual ~RGWRESTMgr();
+   void register_resource(string resource, RGWRESTMgr *mgr);
+   void register_default_mgr(RGWRESTMgr *mgr);
+   virtual RGWRESTMgr *get_resource_mgr(struct req_state *s, const string& uri);
+   virtual RGWHandler *get_handler(struct req_state *s) { return NULL; }
+   virtual void put_handler(RGWHandler *handler) { delete handler; }
+ };
+ class RGWREST {
+   RGWRESTMgr mgr;
  
+   static int preprocess(struct req_state *s, RGWClientIO *cio);
  public:
-   RGWRESTMgr();
-   ~RGWRESTMgr();
-   RGWHandler *get_handler(RGWRados *store, struct req_state *s, FCGX_Request *fcgx,
+   RGWREST() {}
 -  RGWHandler *get_handler(struct req_state *s, RGWClientIO *cio,
++  RGWHandler *get_handler(RGWRados *store, struct req_state *s, RGWClientIO *cio,
                          int *init_error);
+   void put_handler(RGWHandler *handler) {
+     mgr.put_handler(handler);
+   }
+   void register_resource(string resource, RGWRESTMgr *m, bool register_empty = false) {
+     if (!register_empty && resource.empty())
+       return;
+     mgr.register_resource(resource, m);
+   }
+   void register_default_mgr(RGWRESTMgr *m) {
+     mgr.register_default_mgr(m);
+   }
  };
  
  extern void set_req_state_err(struct req_state *s, int err_no);
index 33e02f6eabb2b895454d894985e357daff3cde59,1ec6c0891105c1dd6c89754584e7115c1dceeaa0..512c8cf6b54c4ba24a05a8a6bdf5f698e077d3ba
@@@ -707,43 -752,152 +752,152 @@@ RGWOp *RGWHandler_ObjStore_Obj_S3::op_d
  {
    string upload_id = s->args.get("uploadId");
  
-   if (s->object) {
-     if (upload_id.empty())
-       return new RGWDeleteObj_REST_S3;
-     else
-       return new RGWAbortMultipart_REST_S3;
-   } else if (s->bucket_name)
-     return new RGWDeleteBucket_REST_S3;
+   if (upload_id.empty())
+     return new RGWDeleteObj_ObjStore_S3;
+   else
+     return new RGWAbortMultipart_ObjStore_S3;
+ }
  
-   return NULL;
+ RGWOp *RGWHandler_ObjStore_Obj_S3::op_post()
+ {
+   if (s->args.exists("uploadId"))
+     return new RGWCompleteMultipart_ObjStore_S3;
+   else
+     return new RGWInitMultipart_ObjStore_S3;
  }
  
RGWOp *RGWHandler_REST_S3::get_post_op()
int RGWHandler_ObjStore_S3::init_from_header(struct req_state *s, int default_formatter, bool configurable_format)
  {
-   if (s->object) {
-     if (s->args.exists("uploadId"))
-       return new RGWCompleteMultipart_REST_S3;
-     else
-       return new RGWInitMultipart_REST_S3;
+   string req;
+   string first;
+   const char *req_name = s->decoded_uri.c_str();
+   const char *p;
+   if (*req_name == '?') {
+     p = req_name;
+   } else {
+     p = s->request_params.c_str();
    }
-   else if (s->args.sub_resource_exists("delete")) {
-     return new RGWDeleteMultiObj_REST_S3;
+   s->args.set(p);
+   s->args.parse();
+   /* must be called after the args parsing */
+   int ret = allocate_formatter(s, default_formatter, configurable_format);
+   if (ret < 0)
+     return ret;
+   if (*req_name != '/')
+     return 0;
+   req_name++;
+   if (!*req_name)
+     return 0;
+   req = req_name;
+   int pos = req.find('/');
+   if (pos >= 0) {
+     first = req.substr(0, pos);
+   } else {
+     first = req;
    }
  
-   return NULL;
+   if (!s->bucket_name) {
+     s->bucket_name_str = first;
+     s->bucket_name = strdup(s->bucket_name_str.c_str());
+     if (pos >= 0) {
+       string encoded_obj_str = req.substr(pos+1);
+       s->object_str = encoded_obj_str;
+       if (s->object_str.size() > 0) {
+         s->object = strdup(s->object_str.c_str());
+       }
+     }
+   } else {
+     s->object_str = req_name;
+     s->object = strdup(s->object_str.c_str());
+   }
+   return 0;
  }
  
int RGWHandler_REST_S3::init(RGWRados *store, struct req_state *state, FCGX_Request *fcgx)
static bool looks_like_ip_address(const char *bucket)
  {
-   const char *cacl = state->env->get("HTTP_X_AMZ_ACL");
+   int num_periods = 0;
+   bool expect_period = false;
+   for (const char *b = bucket; *b; ++b) {
+     if (*b == '.') {
+       if (!expect_period)
+       return false;
+       ++num_periods;
+       if (num_periods > 3)
+       return false;
+       expect_period = false;
+     }
+     else if (isdigit(*b)) {
+       expect_period = true;
+     }
+     else {
+       return false;
+     }
+   }
+   return (num_periods == 3);
+ }
+ int RGWHandler_ObjStore_S3::validate_bucket_name(const string& bucket)
+ {
+   int ret = RGWHandler_ObjStore::validate_bucket_name(bucket);
+   if (ret < 0)
+     return ret;
+   if (bucket.size() == 0)
+     return 0;
+   if (!(isalpha(bucket[0]) || isdigit(bucket[0]))) {
+     // bucket names must start with a number or letter
+     return -ERR_INVALID_BUCKET_NAME;
+   }
+   for (const char *s = bucket.c_str(); *s; ++s) {
+     char c = *s;
+     if (isdigit(c) || (c == '.'))
+       continue;
+     if (isalpha(c))
+       continue;
+     if ((c == '-') || (c == '_'))
+       continue;
+     // Invalid character
+     return -ERR_INVALID_BUCKET_NAME;
+   }
+   if (looks_like_ip_address(bucket.c_str()))
+     return -ERR_INVALID_BUCKET_NAME;
+   return 0;
+ }
 -int RGWHandler_ObjStore_S3::init(struct req_state *s, RGWClientIO *cio)
++int RGWHandler_ObjStore_S3::init(RGWRados *store, struct req_state *s, RGWClientIO *cio)
+ {
+   dout(10) << "s->object=" << (s->object ? s->object : "<NULL>") << " s->bucket=" << (s->bucket_name ? s->bucket_name : "<NULL>") << dendl;
+   int ret = validate_bucket_name(s->bucket_name_str);
+   if (ret)
+     return ret;
+   ret = validate_object_name(s->object_str);
+   if (ret)
+     return ret;
+   const char *cacl = s->env->get("HTTP_X_AMZ_ACL");
    if (cacl)
-     state->canned_acl = cacl;
+     s->canned_acl = cacl;
  
-   state->copy_source = state->env->get("HTTP_X_AMZ_COPY_SOURCE");
+   s->copy_source = s->env->get("HTTP_X_AMZ_COPY_SOURCE");
  
-   state->dialect = "s3";
+   s->dialect = "s3";
  
-   return RGWHandler_REST::init(store, state, fcgx);
 -  return RGWHandler_ObjStore::init(s, cio);
++  return RGWHandler_ObjStore::init(store, s, cio);
  }
  
  /*
@@@ -869,7 -1018,7 +1018,7 @@@ static bool get_auth_header(struct req_
   * verify that a signed request comes from the keyholder
   * by checking the signature against our locally-computed version
   */
- int RGWHandler_REST_S3::authorize()
 -int RGW_Auth_S3::authorize(struct req_state *s)
++int RGW_Auth_S3::authorize(RGWRados *store, struct req_state *s)
  {
    bool qsr = false;
    string auth_id;
    return  0;
  }
  
 -int RGWHandler_Auth_S3::init(struct req_state *state, RGWClientIO *cio)
++int RGWHandler_Auth_S3::init(RGWRados *store, struct req_state *state, RGWClientIO *cio)
+ {
+   int ret = RGWHandler_ObjStore_S3::init_from_header(state, RGW_FORMAT_JSON, true);
+   if (ret < 0)
+     return ret;
  
 -  return RGWHandler_ObjStore::init(state, cio);
++  return RGWHandler_ObjStore::init(store, state, cio);
+ }
+ RGWHandler *RGWRESTMgr_S3::get_handler(struct req_state *s)
+ {
+   int ret = RGWHandler_ObjStore_S3::init_from_header(s, RGW_FORMAT_XML, false);
+   if (ret < 0)
+     return NULL;
+   if (!s->bucket_name)
+     return new RGWHandler_ObjStore_Service_S3;
+   if (!s->object)
+     return new RGWHandler_ObjStore_Bucket_S3;
+   return new RGWHandler_ObjStore_Obj_S3;
+ }
index 7c76fd1166e167be6859d5ce8d0c9a09df68980d,8545e8df730829671cd34a41a4c657d00237b24d..e5625d257bc612bd41e0247834bdd4a2b87a1fb6
@@@ -163,8 -163,52 +163,52 @@@ public
    void end_response();
  };
  
 -  static int authorize(struct req_state *s);
+ class RGW_Auth_S3 {
+ public:
 -  virtual int init(struct req_state *state, RGWClientIO *cio);
++  static int authorize(RGWRados *store, struct req_state *s);
+ };
+ class RGWHandler_Auth_S3 : public RGWHandler_ObjStore {
+   friend class RGWRESTMgr_S3;
+ public:
+   RGWHandler_Auth_S3() : RGWHandler_ObjStore() {}
+   virtual ~RGWHandler_Auth_S3() {}
+   virtual int validate_bucket_name(const string& bucket) { return 0; }
+   virtual int validate_object_name(const string& bucket) { return 0; }
 -    return RGW_Auth_S3::authorize(s);
++  virtual int init(RGWRados *store, struct req_state *state, RGWClientIO *cio);
+   virtual int authorize() {
++    return RGW_Auth_S3::authorize(store, s);
+   }
+ };
+ class RGWHandler_ObjStore_S3 : public RGWHandler_ObjStore {
+   friend class RGWRESTMgr_S3;
+ public:
+   static int init_from_header(struct req_state *s, int default_formatter, bool configurable_format);
+   RGWHandler_ObjStore_S3() : RGWHandler_ObjStore() {}
+   virtual ~RGWHandler_ObjStore_S3() {}
+   int validate_bucket_name(const string& bucket);
  
- class RGWHandler_REST_S3 : public RGWHandler_REST {
 -  virtual int init(struct req_state *state, RGWClientIO *cio);
++  virtual int init(RGWRados *store, struct req_state *state, RGWClientIO *cio);
+   virtual int authorize() {
 -    return RGW_Auth_S3::authorize(s);
++    return RGW_Auth_S3::authorize(store, s);
+   }
+ };
+ class RGWHandler_ObjStore_Service_S3 : public RGWHandler_ObjStore_S3 {
+ protected:
+   RGWOp *op_get();
+   RGWOp *op_head();
+ public:
+   RGWHandler_ObjStore_Service_S3() {}
+   virtual ~RGWHandler_ObjStore_Service_S3() {}
+ };
+ class RGWHandler_ObjStore_Bucket_S3 : public RGWHandler_ObjStore_S3 {
  protected:
    bool is_acl_op() {
      return s->args.exists("acl");
index 55458cc0f006746d3fa971481c79dd3479cf247d,c06a7edaba1adbef27a96b352f83a09412d3ed3b..2255c86d7d5458aa67dc4dece10ffba7eb1403d8
@@@ -503,68 -502,101 +502,101 @@@ RGWOp *RGWHandler_ObjStore_Bucket_SWIFT
    }
  
    if (get_data)
-     return new RGWListBucket_REST_SWIFT;
+     return new RGWListBucket_ObjStore_SWIFT;
    else
-     return new RGWStatBucket_REST_SWIFT;
+     return new RGWStatBucket_ObjStore_SWIFT;
  }
  
- RGWOp *RGWHandler_REST_SWIFT::get_retrieve_op(bool get_data)
+ RGWOp *RGWHandler_ObjStore_Bucket_SWIFT::op_get()
  {
-   if (s->bucket_name) {
-     if (is_acl_op()) {
-       return new RGWGetACLs_REST_SWIFT;
-     }
-     return get_retrieve_obj_op(get_data);
+   if (is_acl_op()) {
+     return new RGWGetACLs_ObjStore_SWIFT;
    }
+   return get_obj_op(true);
+ }
  
-   if (get_data)
-     return new RGWListBuckets_REST_SWIFT;
-   else
-     return new RGWStatAccount_REST_SWIFT;
+ RGWOp *RGWHandler_ObjStore_Bucket_SWIFT::op_head()
+ {
+   if (is_acl_op()) {
+     return new RGWGetACLs_ObjStore_SWIFT;
+   }
+   return get_obj_op(false);
  }
  
- RGWOp *RGWHandler_REST_SWIFT::get_create_op()
+ RGWOp *RGWHandler_ObjStore_Bucket_SWIFT::op_put()
  {
    if (is_acl_op()) {
-     return new RGWPutACLs_REST_SWIFT;
-   } else if (s->object) {
-     if (!s->copy_source)
-       return new RGWPutObj_REST_SWIFT;
-     else
-       return new RGWCopyObj_REST_SWIFT;
-   } else if (s->bucket_name) {
-     return new RGWCreateBucket_REST_SWIFT;
+     return new RGWPutACLs_ObjStore_SWIFT;
    }
+   return new RGWCreateBucket_ObjStore_SWIFT;
+ }
+ RGWOp *RGWHandler_ObjStore_Bucket_SWIFT::op_delete()
+ {
+   return new RGWDeleteBucket_ObjStore_SWIFT;
+ }
  
-   return NULL;
+ RGWOp *RGWHandler_ObjStore_Bucket_SWIFT::op_post()
+ {
+   return new RGWPutMetadata_ObjStore_SWIFT;
  }
  
- RGWOp *RGWHandler_REST_SWIFT::get_delete_op()
+ RGWOp *RGWHandler_ObjStore_Obj_SWIFT::get_obj_op(bool get_data)
  {
-   if (s->object)
-     return new RGWDeleteObj_REST_SWIFT;
-   else if (s->bucket_name)
-     return new RGWDeleteBucket_REST_SWIFT;
+   if (is_acl_op()) {
+     return new RGWGetACLs_ObjStore_SWIFT;
+   }
  
-   return NULL;
+   RGWGetObj_ObjStore_SWIFT *get_obj_op = new RGWGetObj_ObjStore_SWIFT;
+   get_obj_op->set_get_data(get_data);
+   return get_obj_op;
  }
  
- RGWOp *RGWHandler_REST_SWIFT::get_post_op()
+ RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_get()
  {
-   return new RGWPutMetadata_REST_SWIFT;
+   if (is_acl_op()) {
+     return new RGWGetACLs_ObjStore_SWIFT;
+   }
+   return get_obj_op(true);
  }
  
- RGWOp *RGWHandler_REST_SWIFT::get_copy_op()
+ RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_head()
  {
-   if (s->object)
-     return new RGWCopyObj_REST_SWIFT;
+   if (is_acl_op()) {
+     return new RGWGetACLs_ObjStore_SWIFT;
+   }
+   return get_obj_op(false);
+ }
+ RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_put()
+ {
+   if (is_acl_op()) {
+     return new RGWPutACLs_ObjStore_SWIFT;
+   }
+   if (!s->copy_source)
+     return new RGWPutObj_ObjStore_SWIFT;
+   else
+     return new RGWCopyObj_ObjStore_SWIFT;
+ }
  
-   return NULL;
+ RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_delete()
+ {
+   return new RGWDeleteObj_ObjStore_SWIFT;
  }
  
- int RGWHandler_REST_SWIFT::authorize()
+ RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_post()
+ {
+   return new RGWPutMetadata_ObjStore_SWIFT;
+ }
+ RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_copy()
+ {
+   return new RGWCopyObj_ObjStore_SWIFT;
+ }
+ int RGWHandler_ObjStore_SWIFT::authorize()
  {
 -  bool authorized = rgw_verify_os_token(s);
 +  bool authorized = rgw_verify_swift_token(store, s);
    if (!authorized)
      return -EPERM;
  
    return 0;
  }
  
- int RGWHandler_REST_SWIFT::init(RGWRados *store, struct req_state *state, FCGX_Request *fcgx)
+ int RGWHandler_ObjStore_SWIFT::validate_bucket_name(const string& bucket)
+ {
+   int ret = RGWHandler_ObjStore::validate_bucket_name(bucket);
+   if (ret < 0)
+     return ret;
+   int len = bucket.size();
+   if (len == 0)
+     return 0;
+   if (bucket[0] == '.')
+     return -ERR_INVALID_BUCKET_NAME;
+   if (check_utf8(bucket.c_str(), len))
+     return -ERR_INVALID_UTF8;
+   const char *s = bucket.c_str();
+   for (int i = 0; i < len; ++i, ++s) {
+     if (*(unsigned char *)s == 0xff)
+       return -ERR_INVALID_BUCKET_NAME;
+   }
+   return 0;
+ }
+ static void next_tok(string& str, string& tok, char delim)
+ {
+   if (str.size() == 0) {
+     tok = "";
+     return;
+   }
+   tok = str;
+   int pos = str.find(delim);
+   if (pos > 0) {
+     tok = str.substr(0, pos);
+     str = str.substr(pos + 1);
+   } else {
+     str = "";
+   }
+ }
+ int RGWHandler_ObjStore_SWIFT::init_from_header(struct req_state *s)
  {
-   state->copy_source = state->env->get("HTTP_X_COPY_FROM");
+   string req;
+   string first;
+   s->prot_flags |= RGW_REST_SWIFT;
+   const char *req_name = s->decoded_uri.c_str();
+   const char *p;
+   if (*req_name == '?') {
+     p = req_name;
+   } else {
+     p = s->request_params.c_str();
+   }
+   s->args.set(p);
+   s->args.parse();
+   if (*req_name != '/')
+     return 0;
+   req_name++;
+   if (!*req_name)
+     return 0;
+   req = req_name;
+   int pos = req.find('/');
+   if (pos >= 0) {
+     bool cut_url = g_conf->rgw_swift_url_prefix.length();
+     first = req.substr(0, pos);
+     if (first.compare(g_conf->rgw_swift_url_prefix) == 0) {
+       if (cut_url) {
+         next_tok(req, first, '/');
+       }
+     }
+   } else {
+     if (req.compare(g_conf->rgw_swift_url_prefix) == 0) {
+       s->formatter = new RGWFormatter_Plain;
+       return -ERR_BAD_URL;
+     }
+     first = req;
+   }
+   /* verify that the request_uri conforms with what's expected */
+   char buf[g_conf->rgw_swift_url_prefix.length() + 16];
+   int blen = sprintf(buf, "/%s/v1", g_conf->rgw_swift_url_prefix.c_str());
+   if (s->decoded_uri[0] != '/' ||
+     s->decoded_uri.compare(0, blen, buf) !=  0) {
+     return -ENOENT;
+   }
+   int ret = allocate_formatter(s, RGW_FORMAT_PLAIN, true);
+   if (ret < 0)
+     return ret;
+   string ver;
+   next_tok(req, ver, '/');
+   s->os_auth_token = s->env->get("HTTP_X_AUTH_TOKEN");
+   next_tok(req, first, '/');
+   dout(10) << "ver=" << ver << " first=" << first << " req=" << req << dendl;
+   if (first.size() == 0)
+     return 0;
+   s->bucket_name_str = first;
+   s->bucket_name = strdup(s->bucket_name_str.c_str());
+    
+   if (req.size()) {
+     s->object_str = req;
+     s->object = strdup(s->object_str.c_str());
+   }
+   return 0;
+ }
 -int RGWHandler_ObjStore_SWIFT::init(struct req_state *s, RGWClientIO *cio)
++int RGWHandler_ObjStore_SWIFT::init(RGWRados *store, struct req_state *s, RGWClientIO *cio)
+ {
+   dout(10) << "s->object=" << (s->object ? s->object : "<NULL>") << " s->bucket=" << (s->bucket_name ? s->bucket_name : "<NULL>") << dendl;
+   int ret = validate_bucket_name(s->bucket_name_str.c_str());
+   if (ret)
+     return ret;
+   ret = validate_object_name(s->object_str.c_str());
+   if (ret)
+     return ret;
+   s->copy_source = s->env->get("HTTP_X_COPY_FROM");
+   s->dialect = "swift";
 -  return RGWHandler_ObjStore::init(s, cio);
++  return RGWHandler_ObjStore::init(store, s, cio);
+ }
+ RGWHandler *RGWRESTMgr_SWIFT::get_handler(struct req_state *s)
+ {
+   int ret = RGWHandler_ObjStore_SWIFT::init_from_header(s);
+   if (ret < 0)
+     return NULL;
  
-   state->dialect = "swift";
+   if (!s->bucket_name)
+     return new RGWHandler_ObjStore_Service_SWIFT;
+   if (!s->object)
+     return new RGWHandler_ObjStore_Bucket_SWIFT;
  
-   return RGWHandler_REST::init(store, state, fcgx);
+   return new RGWHandler_ObjStore_Obj_SWIFT;
  }
index 35c986f1b743e94942f3ae1e3d60cf5b9c0c0589,4b33fda57069804ee14eb2ac57092559f0ae5857..7051fee579e33afc00090af65f4fd4909ff93a4a
@@@ -126,12 -126,38 +126,38 @@@ public
    void send_response() {}
  };
  
- class RGWHandler_REST_SWIFT : public RGWHandler_REST {
+ class RGWHandler_ObjStore_SWIFT : public RGWHandler_ObjStore {
+   friend class RGWRESTMgr_SWIFT;
  protected:
-   bool is_acl_op() {
-     return false; // for now
+   virtual bool is_acl_op() {
+     return false;
    }
 -  int init(struct req_state *state, RGWClientIO *cio);
+   static int init_from_header(struct req_state *s);
+ public:
+   RGWHandler_ObjStore_SWIFT() {}
+   virtual ~RGWHandler_ObjStore_SWIFT() {}
+   int validate_bucket_name(const string& bucket);
++  int init(RGWRados *store, struct req_state *state, RGWClientIO *cio);
+   int authorize();
+   RGWAccessControlPolicy *alloc_policy() { return NULL; /* return new RGWAccessControlPolicy_SWIFT; */ }
+   void free_policy(RGWAccessControlPolicy *policy) { delete policy; }
+ };
+ class RGWHandler_ObjStore_Service_SWIFT : public RGWHandler_ObjStore_SWIFT {
+ protected:
+   RGWOp *op_get();
+   RGWOp *op_head();
+ public:
+   RGWHandler_ObjStore_Service_SWIFT() {}
+   virtual ~RGWHandler_ObjStore_Service_SWIFT() {}
+ };
+ class RGWHandler_ObjStore_Bucket_SWIFT : public RGWHandler_ObjStore_SWIFT {
+ protected:
    bool is_obj_update_op() {
      return s->op == OP_POST;
    }
index 0000000000000000000000000000000000000000,37641dba3424434c489340ee9b8100ba465f2f9f..428744538e582b26460dd4bc5f3dbcd7320648ea
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,84 +1,84 @@@
 -  http_ret = RGWUsage::show(rgwstore, uid, start, end, show_entries, show_summary, &categories, flusher);
+ #include "rgw_op.h"
+ #include "rgw_usage.h"
+ #include "rgw_rest_usage.h"
+ #define dout_subsys ceph_subsys_rgw
+ class RGWOp_Usage_Get : public RGWRESTOp {
+ public:
+   RGWOp_Usage_Get() {}
+   int check_caps(RGWUserCaps& caps) {
+     return caps.check_cap("usage", RGW_CAP_READ);
+   }
+   void execute();
+   virtual const char *name() { return "get_usage"; }
+ };
+ void RGWOp_Usage_Get::execute() {
+   map<std::string, bool> categories;
+   string uid;
+   uint64_t start, end;
+   bool show_entries;
+   bool show_summary;
+   RESTArgs::get_string(s, "uid", uid, &uid);
+   RESTArgs::get_epoch(s, "start", 0, &start);
+   RESTArgs::get_epoch(s, "end", (uint64_t)-1, &end);
+   RESTArgs::get_bool(s, "show-entries", true, &show_entries);
+   RESTArgs::get_bool(s, "show-summary", true, &show_summary);
 -  http_ret = RGWUsage::trim(rgwstore, uid, start, end);
++  http_ret = RGWUsage::show(store, uid, start, end, show_entries, show_summary, &categories, flusher);
+ }
+ class RGWOp_Usage_Delete : public RGWRESTOp {
+ public:
+   RGWOp_Usage_Delete() {}
+   int check_caps(RGWUserCaps& caps) {
+     return caps.check_cap("usage", RGW_CAP_WRITE);
+   }
+   void execute();
+   virtual const char *name() { return "trim_usage"; }
+ };
+ void RGWOp_Usage_Delete::execute() {
+   map<std::string, bool> categories;
+   string uid;
+   uint64_t start, end;
+   RESTArgs::get_string(s, "uid", uid, &uid);
+   RESTArgs::get_epoch(s, "start", 0, &start);
+   RESTArgs::get_epoch(s, "end", (uint64_t)-1, &end);
+   if (uid.empty() &&
+       !start &&
+       end == (uint64_t)-1) {
+     bool remove_all;
+     RESTArgs::get_bool(s, "remove-all", false, &remove_all);
+     if (!remove_all) {
+       http_ret = -EINVAL;
+       return;
+     }
+   }
++  http_ret = RGWUsage::trim(store, uid, start, end);
+ }
+ RGWOp *RGWHandler_Usage::op_get()
+ {
+   return new RGWOp_Usage_Get;
+ };
+ RGWOp *RGWHandler_Usage::op_delete()
+ {
+   return new RGWOp_Usage_Delete;
+ };
index 09d702a87a2360a97de675d052cb4f1fc4dea3eb,64be3318824991a20cb912c55e9e9602f88932ae..90990d957511a2e3e0d2fda2c91903a2628463a2
@@@ -224,11 -218,13 +218,13 @@@ done
    end_header(s);
  }
  
- int RGWHandler_SWIFT_Auth::init(RGWRados *store, struct req_state *state, FCGX_Request *fcgx)
 -int RGWHandler_SWIFT_Auth::init(struct req_state *state, RGWClientIO *cio)
++int RGWHandler_SWIFT_Auth::init(RGWRados *store, struct req_state *state, RGWClientIO *cio)
  {
    state->dialect = "swift-auth";
+   state->formatter = new JSONFormatter;
+   state->format = RGW_FORMAT_JSON;
  
-   return RGWHandler::init(store, state, fcgx);
 -  return RGWHandler::init(state, cio);
++  return RGWHandler::init(store, state, cio);
  }
  
  int RGWHandler_SWIFT_Auth::authorize()
index 15f0fa0fc30ad564fd71347b73434090e71794be,0747a40ab2d69fddb6479abe5f99627a086a5880..8a58b47649658d3a684cec83d599d900774eb2a4
@@@ -21,10 -22,9 +22,9 @@@ class RGWHandler_SWIFT_Auth : public RG
  public:
    RGWHandler_SWIFT_Auth() {}
    ~RGWHandler_SWIFT_Auth() {}
-   RGWOp *get_op();
-   void put_op(RGWOp *op);
+   RGWOp *op_get();
  
-   int init(RGWRados *store, struct req_state *state, FCGX_Request *fcgx);
 -  int init(struct req_state *state, RGWClientIO *cio);
++  int init(RGWRados *store, struct req_state *state, RGWClientIO *cio);
    int authorize();
    int read_permissions(RGWOp *op) { return 0; }
  
index 0000000000000000000000000000000000000000,38565457db1c1503d374f4bf5d8c9f6ba7df84da..054abc2c33496151affa725179ac293f5303e5be
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,140 +1,140 @@@
 -    int ret = rgwstore->read_usage(uid, start_epoch, end_epoch, max_entries,
 -                                   &is_truncated, usage_iter, usage);
+ #include <string>
+ #include <map>
+ #include "rgw_rados.h"
+ #include "rgw_usage.h"
+ #include "rgw_formats.h"
+ using namespace std;
+ static void dump_usage_categories_info(Formatter *formatter, const rgw_usage_log_entry& entry, map<string, bool> *categories)
+ {
+   formatter->open_array_section("categories");
+   map<string, rgw_usage_data>::const_iterator uiter;
+   for (uiter = entry.usage_map.begin(); uiter != entry.usage_map.end(); ++uiter) {
+     if (categories && categories->size() && !categories->count(uiter->first))
+       continue;
+     const rgw_usage_data& usage = uiter->second;
+     formatter->open_object_section("entry");
+     formatter->dump_string("category", uiter->first);
+     formatter->dump_int("bytes_sent", usage.bytes_sent);
+     formatter->dump_int("bytes_received", usage.bytes_received);
+     formatter->dump_int("ops", usage.ops);
+     formatter->dump_int("successful_ops", usage.successful_ops);
+     formatter->close_section(); // entry
+   }
+   formatter->close_section(); // categories
+ }
+ int RGWUsage::show(RGWRados *store, string& uid, uint64_t start_epoch,
+                  uint64_t end_epoch, bool show_log_entries, bool show_log_sum,
+                  map<string, bool> *categories,
+                  RGWFormatterFlusher& flusher)
+ {
+   uint32_t max_entries = 1000;
+   bool is_truncated = true;
+   RGWUsageIter usage_iter;
+   Formatter *formatter = flusher.get_formatter();
+   map<rgw_user_bucket, rgw_usage_log_entry> usage;
+   flusher.start(0);
+   formatter->open_object_section("usage");
+   if (show_log_entries) {
+     formatter->open_array_section("entries");
+   }
+   string last_owner;
+   bool user_section_open = false;
+   map<string, rgw_usage_log_entry> summary_map;
+   while (is_truncated) {
++    int ret = store->read_usage(uid, start_epoch, end_epoch, max_entries,
++                                &is_truncated, usage_iter, usage);
+     if (ret == -ENOENT) {
+       ret = 0;
+       is_truncated = false;
+     }
+     if (ret < 0) {
+       return ret;
+     }
+     map<rgw_user_bucket, rgw_usage_log_entry>::iterator iter;
+     for (iter = usage.begin(); iter != usage.end(); ++iter) {
+       const rgw_user_bucket& ub = iter->first;
+       const rgw_usage_log_entry& entry = iter->second;
+       if (show_log_entries) {
+         if (ub.user.compare(last_owner) != 0) {
+           if (user_section_open) {
+             formatter->close_section();
+             formatter->close_section();
+           }
+           formatter->open_object_section("user");
+           formatter->dump_string("owner", ub.user);
+           formatter->open_array_section("buckets");
+           user_section_open = true;
+           last_owner = ub.user;
+         }
+         formatter->open_object_section("bucket");
+         formatter->dump_string("bucket", ub.bucket);
+         utime_t ut(entry.epoch, 0);
+         ut.gmtime(formatter->dump_stream("time"));
+         formatter->dump_int("epoch", entry.epoch);
+         dump_usage_categories_info(formatter, entry, categories);
+         formatter->close_section(); // bucket
+         flusher.flush();
+       }
+       summary_map[ub.user].aggregate(entry, categories);
+     }
+   }
+   if (show_log_entries) {
+     if (user_section_open) {
+       formatter->close_section(); // buckets
+       formatter->close_section(); //user
+     }
+     formatter->close_section(); // entries
+   }
+   if (show_log_sum) {
+     formatter->open_array_section("summary");
+     map<string, rgw_usage_log_entry>::iterator siter;
+     for (siter = summary_map.begin(); siter != summary_map.end(); ++siter) {
+       const rgw_usage_log_entry& entry = siter->second;
+       formatter->open_object_section("user");
+       formatter->dump_string("user", siter->first);
+       dump_usage_categories_info(formatter, entry, categories);
+       rgw_usage_data total_usage;
+       entry.sum(total_usage, *categories);
+       formatter->open_object_section("total");
+       formatter->dump_int("bytes_sent", total_usage.bytes_sent);
+       formatter->dump_int("bytes_received", total_usage.bytes_received);
+       formatter->dump_int("ops", total_usage.ops);
+       formatter->dump_int("successful_ops", total_usage.successful_ops);
+       formatter->close_section(); // total
+       formatter->close_section(); // user
+       flusher.flush();
+     }
+     formatter->close_section(); // summary
+   }
+   formatter->close_section(); // usage
+   flusher.flush();
+   return 0;
+ }
+ int RGWUsage::trim(RGWRados *store, string& uid, uint64_t start_epoch,
+                  uint64_t end_epoch)
+ {
+   return store->trim_usage(uid, start_epoch, end_epoch);
+ }
Simple merge