]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: dump content length for certain operations
authorYehuda Sadeh <yehuda@hq.newdream.net>
Thu, 17 Mar 2011 21:31:30 +0000 (14:31 -0700)
committerYehuda Sadeh <yehuda@hq.newdream.net>
Thu, 17 Mar 2011 21:32:21 +0000 (14:32 -0700)
src/rgw/rgw_common.cc
src/rgw/rgw_common.h
src/rgw/rgw_formats.cc
src/rgw/rgw_rest.cc
src/rgw/rgw_rest_os.cc
src/rgw/rgw_rest_s3.cc

index e5a9a42a695a64c935eb7dd87ebd6205e37e4e17..b41bfad5dbfc24f53b172ef975225185564b026a 100644 (file)
@@ -153,4 +153,75 @@ bool url_decode(string& src_str, string& dest_str)
   return true;
 }
 
+void RGWFormatter::write_data(const char *fmt, ...)
+{
+#define LARGE_ENOUGH_LEN 128
+  int n, size = LARGE_ENOUGH_LEN;
+  char s[size];
+  char *p, *np;
+  bool p_on_stack;
+  va_list ap;
+  int pos;
+
+  p = s;
+  p_on_stack = true;
+
+  while (1) {
+    va_start(ap, fmt);
+    n = vsnprintf(p, size, fmt, ap);
+    va_end(ap);
+
+    if (n > -1 && n < size)
+      goto done;
+    /* Else try again with more space. */
+    if (n > -1)    /* glibc 2.1 */
+      size = n+1; /* precisely what is needed */
+    else           /* glibc 2.0 */
+      size *= 2;  /* twice the old size */
+    if (p_on_stack)
+      np = (char *)malloc(size);
+    else
+      np = (char *)realloc(p, size);
+    if (!np)
+      goto done_free;
+    p = np;
+    p_on_stack = false;
+  }
+done:
+#define LARGE_ENOUGH_BUF 4096
+  if (!buf) {
+    max_len = max(LARGE_ENOUGH_BUF, size);
+    buf = (char *)malloc(max_len);
+  }
 
+  if (len + size > max_len) {
+    max_len = len + size + LARGE_ENOUGH_BUF;
+    buf = (char *)realloc(buf, max_len);
+  }
+  if (!buf) {
+    RGW_LOG(0) << "RGWFormatter::write_data: failed allocating " << max_len << " bytes" << std::endl;
+    goto done_free;
+  }
+  pos = len;
+  if (len)
+    pos--; // squash null termination
+  strcpy(buf + pos, p);
+  len = pos + strlen(p) + 1;
+  RGW_LOG(0) << "RGWFormatter::write_data: len= " << len << " bytes" << std::endl;
+done_free:
+  if (!p_on_stack)
+    free(p);
+}
+
+void RGWFormatter::flush()
+{
+  if (!buf)
+    return;
+
+  RGW_LOG(0) << "flush(): buf='" << buf << "'  strlen(buf)=" << strlen(buf) << std::endl;
+  FCGX_PutStr(buf, len - 1, s->fcgx->out);
+  free(buf);
+  buf = NULL;
+  len = 0;
+  max_len = 0;
+}
index 200606050f94361e4e93f5afa0455feea2cb193e..f23a7d15d0ad77b490a6ed234bf081aa6e2898dd 100644 (file)
@@ -172,16 +172,26 @@ struct req_state;
 class RGWFormatter {
 protected:
   struct req_state *s;
+  char *buf;
+  int len;
+  int max_len;
 
   virtual void formatter_init() = 0;
 public:
-  RGWFormatter() {}
+  RGWFormatter() : buf(NULL), len(0), max_len(0) {}
   virtual ~RGWFormatter() {}
   void init(struct req_state *_s) {
     s = _s;
+    if (buf)
+      free(buf);
+    buf = NULL;
+    len = 0;
+    max_len = 0;
     formatter_init();
   }
-
+  void write_data(const char *fmt, ...);
+  virtual void flush();
+  virtual int get_len() { return (len ? len - 1 : 0); } // don't include null termination in length
   virtual void open_array_section(const char *name) = 0;
   virtual void open_obj_section(const char *name) = 0;
   virtual void close_section(const char *name) = 0;
index 29db4d55377b46ea9da71a38c138a3287511b5d4..960c0a0e76445ec410df37ff1d8f3271ae9ac663 100644 (file)
@@ -50,7 +50,7 @@ void RGWFormatter_Plain::dump_value_int(const char *name, const char *fmt, ...)
   va_end(ap);
   if (n >= LARGE_SIZE)
     return;
-  CGI_PRINTF(s, "(%d %d) %s\n", (int)entry.is_array, entry.size, buf);
+  write_data("%s\n", buf);
 }
 
 void RGWFormatter_Plain::dump_value_str(const char *name, const char *fmt, ...)
@@ -74,7 +74,7 @@ void RGWFormatter_Plain::dump_value_str(const char *name, const char *fmt, ...)
   va_end(ap);
   if (n >= LARGE_SIZE)
     return;
-  CGI_PRINTF(s, "%s\n", buf);
+  write_data("%s\n", buf);
 }
 
 /* XML */
@@ -86,14 +86,14 @@ void RGWFormatter_XML::formatter_init()
 
 void RGWFormatter_XML::open_section(const char *name)
 {
-  CGI_PRINTF(s, "<%s>", name);
+  write_data("<%s>", name);
   ++indent;
 }
 
 void RGWFormatter_XML::close_section(const char *name)
 {
   --indent;
-  CGI_PRINTF(s, "</%s>", name);
+  write_data("</%s>", name);
 }
 
 void RGWFormatter_XML::dump_value_int(const char *name, const char *fmt, ...)
@@ -107,7 +107,7 @@ void RGWFormatter_XML::dump_value_int(const char *name, const char *fmt, ...)
   va_end(ap);
   if (n >= LARGE_SIZE)
     return;
-  CGI_PRINTF(s, "<%s>%s</%s>", name, buf, name);
+  write_data("<%s>%s</%s>", name, buf, name);
 }
 
 void RGWFormatter_XML::dump_value_str(const char *name, const char *fmt, ...)
@@ -120,7 +120,7 @@ void RGWFormatter_XML::dump_value_str(const char *name, const char *fmt, ...)
   va_end(ap);
   if (n >= LARGE_SIZE)
     return;
-  CGI_PRINTF(s, "<%s>%s</%s>", name, buf, name);
+  write_data("<%s>%s</%s>", name, buf, name);
 }
 
 /* JSON */
@@ -134,10 +134,10 @@ void RGWFormatter_JSON::open_section(bool is_array)
 {
   if (stack.size()) {
     struct json_stack_entry& entry = stack.back();
-    CGI_PRINTF(s, "%s\n", (entry.size ? "," : ""));
+    write_data("%s\n", (entry.size ? "," : ""));
     entry.size++;
   }
-  CGI_PRINTF(s, "%c", (is_array ? '[' : '{'));
+  write_data("%c", (is_array ? '[' : '{'));
 
   struct json_stack_entry new_entry;
   new_entry.is_array = is_array;
@@ -159,7 +159,7 @@ void RGWFormatter_JSON::close_section(const char *name)
 {
   struct json_stack_entry& entry = stack.back();
 
-  CGI_PRINTF(s, "%c", (entry.is_array ? ']' : '}'));
+  write_data("%c", (entry.is_array ? ']' : '}'));
 
   stack.pop_back();
 }
@@ -177,7 +177,7 @@ void RGWFormatter_JSON::dump_value_int(const char *name, const char *fmt, ...)
   va_end(ap);
   if (n >= LARGE_SIZE)
     return;
-  CGI_PRINTF(s, "%s\"%s\":%s", (entry.size ? ", " : ""), name, buf);
+  write_data("%s\"%s\":%s", (entry.size ? ", " : ""), name, buf);
   entry.size++;
 }
 
@@ -193,7 +193,7 @@ void RGWFormatter_JSON::dump_value_str(const char *name, const char *fmt, ...)
   va_end(ap);
   if (n >= LARGE_SIZE)
     return;
-  CGI_PRINTF(s, "%s\"%s\":\"%s\"", (entry.size ? ", " : ""), name, buf);
+  write_data("%s\"%s\":\"%s\"", (entry.size ? ", " : ""), name, buf);
   entry.size++;
 }
 
index fb3c09cd3497643568c29ece514eec0b0a62ce4c..f18c02d603411608707aed05322b2dc93b81af87 100644 (file)
@@ -115,7 +115,7 @@ void dump_last_modified(struct req_state *s, time_t t)
 
 static void dump_entry(struct req_state *s, const char *val)
 {
-  CGI_PRINTF(s, "<?%s?>", val);
+  s->formatter->write_data("<?%s?>", val);
 }
 
 
@@ -182,6 +182,7 @@ void abort_early(struct req_state *s, int err)
 {
   dump_errno(s, err);
   end_header(s);
+  s->formatter->flush();
 }
 
 void dump_continue(struct req_state *s)
index 9948c1e763c7129a1632bb8ccd0383d0b0147e64..0b0819b8593f54b1deec368ad26c66e3930b1c8f 100644 (file)
@@ -5,9 +5,14 @@
 void RGWListBuckets_REST_OS::send_response()
 {
   dump_errno(s, ret);
-  end_header(s);
+
   dump_start(s);
 
+  if (ret < 0) {
+    end_header(s);
+    return;
+  }
+
   s->formatter->open_array_section("account");
 
   // dump_owner(s, s->user.user_id, s->user.display_name);
@@ -35,16 +40,21 @@ void RGWListBuckets_REST_OS::send_response()
     s->formatter->close_section("container");
   }
   s->formatter->close_section("account");
+
+  dump_content_length(s, s->formatter->get_len());
+  end_header(s);
+  s->formatter->flush();
 }
 
 void RGWListBucket_REST_OS::send_response()
 {
   dump_errno(s, (ret < 0 ? ret : 0));
 
-  end_header(s);
   dump_start(s);
-  if (ret < 0)
+  if (ret < 0) {
+    end_header(s);
     return;
+  }
 
   vector<RGWObjEnt>::iterator iter = objs.begin();
 
@@ -74,6 +84,9 @@ void RGWListBucket_REST_OS::send_response()
     }
 #endif
   s->formatter->close_section("container");
+
+  end_header(s);
+  s->formatter->flush();
 }
 
 static void dump_container_metadata(struct req_state *s, RGWBucketEnt& bucket)
@@ -94,12 +107,14 @@ void RGWStatBucket_REST_OS::send_response()
 
   end_header(s);
   dump_start(s);
+  s->formatter->flush();
 }
 
 void RGWCreateBucket_REST_OS::send_response()
 {
   dump_errno(s, ret);
   end_header(s);
+  s->formatter->flush();
 }
 
 void RGWDeleteBucket_REST_OS::send_response()
@@ -110,6 +125,7 @@ void RGWDeleteBucket_REST_OS::send_response()
 
   dump_errno(s, r);
   end_header(s);
+  s->formatter->flush();
 }
 
 void RGWPutObj_REST_OS::send_response()
@@ -119,6 +135,7 @@ void RGWPutObj_REST_OS::send_response()
   dump_etag(s, etag.c_str());
   dump_errno(s, ret, &err);
   end_header(s);
+  s->formatter->flush();
 }
 
 void RGWDeleteObj_REST_OS::send_response()
@@ -129,6 +146,7 @@ void RGWDeleteObj_REST_OS::send_response()
 
   dump_errno(s, r);
   end_header(s);
+  s->formatter->flush();
 }
 
 int RGWGetObj_REST_OS::send_response(void *handle)
@@ -180,6 +198,7 @@ send_data:
   if (get_data && !orig_ret) {
     FCGX_PutStr(data, len, s->fcgx->out); 
   }
+  s->formatter->flush();
 
   return 0;
 }
index 3e54204e27c5c533a85917bed7b0b068d8ff9b92..51562494a1f136d7b04270900c12c61e2ca40ecd 100644 (file)
@@ -71,7 +71,8 @@ int RGWGetObj_REST_S3::send_response(void *handle)
   if (!content_type)
     content_type = "binary/octet-stream";
   end_header(s, content_type);
-
+  s->formatter->flush();
   sent_header = true;
 
 send_data:
@@ -85,7 +86,6 @@ send_data:
 void RGWListBuckets_REST_S3::send_response()
 {
   dump_errno(s, ret);
-  end_header(s, "application/xml");
   dump_start(s);
 
   list_all_buckets_start(s);
@@ -101,6 +101,9 @@ void RGWListBuckets_REST_S3::send_response()
   }
   s->formatter->close_section("Buckets");
   list_all_buckets_end(s);
+  dump_content_length(s, s->formatter->get_len());
+  end_header(s, "application/xml");
+  s->formatter->flush();
 }
 
 void RGWListBucket_REST_S3::send_response()
@@ -146,12 +149,14 @@ void RGWListBucket_REST_S3::send_response()
     }
   }
   s->formatter->close_section("ListBucketResult");
+  s->formatter->flush();
 }
 
 void RGWCreateBucket_REST_S3::send_response()
 {
   dump_errno(s, ret);
   end_header(s);
+  s->formatter->flush();
 }
 
 void RGWDeleteBucket_REST_S3::send_response()
@@ -162,6 +167,7 @@ void RGWDeleteBucket_REST_S3::send_response()
 
   dump_errno(s, r);
   end_header(s);
+  s->formatter->flush();
 }
 
 void RGWPutObj_REST_S3::send_response()
@@ -169,6 +175,7 @@ void RGWPutObj_REST_S3::send_response()
   dump_etag(s, etag.c_str());
   dump_errno(s, ret, &err);
   end_header(s);
+  s->formatter->flush();
 }
 
 void RGWDeleteObj_REST_S3::send_response()
@@ -179,6 +186,7 @@ void RGWDeleteObj_REST_S3::send_response()
 
   dump_errno(s, r);
   end_header(s);
+  s->formatter->flush();
 }
 
 void RGWCopyObj_REST_S3::send_response()
@@ -199,6 +207,7 @@ void RGWCopyObj_REST_S3::send_response()
     }
     s->formatter->close_section("CopyObjectResult");
   }
+  s->formatter->flush();
 }
 
 void RGWGetACLs_REST_S3::send_response()
@@ -206,6 +215,7 @@ void RGWGetACLs_REST_S3::send_response()
   dump_errno(s, ret);
   end_header(s, "application/xml");
   dump_start(s);
+  s->formatter->flush();
   FCGX_PutStr(acls.c_str(), acls.size(), s->fcgx->out); 
 }
 
@@ -214,6 +224,7 @@ void RGWPutACLs_REST_S3::send_response()
   dump_errno(s, ret);
   end_header(s, "application/xml");
   dump_start(s);
+  s->formatter->flush();
 }
 
 RGWOp *RGWHandler_REST_S3::get_retrieve_obj_op(struct req_state *s, bool get_data)