[sheepdog] [PATCH v3 2/3] sheep/http: implement HEAD for object opeation

Liu Yuan namei.unix at gmail.com
Thu Dec 26 07:23:13 CET 2013


Signed-off-by: Liu Yuan <namei.unix at gmail.com>
---
 sheep/http/http.c  |  2 +-
 sheep/http/http.h  |  2 ++
 sheep/http/kv.c    | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
 sheep/http/swift.c | 16 +++++++++++++++-
 4 files changed, 64 insertions(+), 7 deletions(-)

diff --git a/sheep/http/http.c b/sheep/http/http.c
index 0081707..4a2ae35 100644
--- a/sheep/http/http.c
+++ b/sheep/http/http.c
@@ -193,7 +193,7 @@ void http_response_header(struct http_request *req, enum http_status status)
 
 	req->status = status;
 	http_request_writef(req, "Status: %s\r\n", strstatus(status));
-	if (req->opcode == HTTP_GET && req->data_length > 0)
+	if (req->opcode == HTTP_GET || req->opcode == HTTP_HEAD)
 		http_request_writef(req, "Content-Length: %lu\r\n",
 				    req->data_length);
 	http_request_writes(req, "Content-type: text/plain;\r\n\r\n");
diff --git a/sheep/http/http.h b/sheep/http/http.h
index 40ff307..52f5b36 100644
--- a/sheep/http/http.h
+++ b/sheep/http/http.h
@@ -139,6 +139,8 @@ int kv_create_object(struct http_request *req, const char *account,
 		     const char *bucket, const char *object);
 int kv_read_object(struct http_request *req, const char *account,
 		   const char *bucket, const char *object);
+int kv_read_object_meta(struct http_request *req, const char *account,
+			const char *bucket, const char *object);
 int kv_delete_object(const char *account, const char *bucket, const char *);
 int kv_iterate_object(const char *account, const char *bucket,
 		      void (*cb)(const char *object, void *opaque),
diff --git a/sheep/http/kv.c b/sheep/http/kv.c
index a58310f..d04230d 100644
--- a/sheep/http/kv.c
+++ b/sheep/http/kv.c
@@ -35,7 +35,6 @@ struct kv_onode {
 			/* a hash value for etag */
 			uint8_t sha1[round_up(SHA1_DIGEST_SIZE, 8)];
 			uint64_t size;
-			uint64_t ctime;
 			uint64_t mtime;
 			uint32_t data_vid;
 			uint32_t nr_extent;
@@ -690,10 +689,19 @@ out:
 	return ret;
 }
 
+static uint64_t get_seconds(void)
+{
+	struct timeval tv;
+	uint64_t seconds;
+
+	gettimeofday(&tv, NULL);
+	seconds = (uint64_t)tv.tv_sec;
+	return seconds;
+}
+
 static int onode_populate_data(struct kv_onode *onode, struct http_request *req)
 {
 	ssize_t size;
-	struct timeval tv;
 	int ret;
 
 	if (req->data_length <= KV_ONODE_INLINE_SIZE) {
@@ -711,9 +719,7 @@ static int onode_populate_data(struct kv_onode *onode, struct http_request *req)
 			goto out;
 	}
 
-	gettimeofday(&tv, NULL);
-	onode->ctime = (uint64_t) tv.tv_sec << 32 | tv.tv_usec * 1000;
-	onode->mtime = onode->ctime;
+	onode->mtime = get_seconds();
 	onode->size = req->data_length;
 out:
 	return ret;
@@ -1093,3 +1099,38 @@ int kv_iterate_object(const char *account, const char *bucket,
 
 	return ret;
 }
+
+static char *http_time(uint64_t time)
+{
+	static __thread char time_str[128];
+
+	strftime(time_str, sizeof(time_str), "%a, %d %b %Y %H:%M:%S GMT",
+		 gmtime((time_t *)&time));
+	return time_str;
+}
+
+int kv_read_object_meta(struct http_request *req, const char *account,
+			const char *bucket, const char *name)
+{
+	struct kv_onode *onode = NULL;
+	char vdi_name[SD_MAX_VDI_LEN];
+	uint32_t bucket_vid;
+	int ret;
+
+	snprintf(vdi_name, SD_MAX_VDI_LEN, "%s/%s", account, bucket);
+	ret = sd_lookup_vdi(vdi_name, &bucket_vid);
+	if (ret != SD_RES_SUCCESS)
+		return ret;
+
+	onode = xzalloc(sizeof(*onode));
+	ret = onode_lookup(onode, bucket_vid, name);
+	if (ret != SD_RES_SUCCESS)
+		goto out;
+
+	req->data_length = onode->size;
+	http_request_writef(req, "Last-Modified: %s\n",
+			    http_time(onode->mtime));
+out:
+	free(onode);
+	return ret;
+}
diff --git a/sheep/http/swift.c b/sheep/http/swift.c
index c3985be..a2b2e89 100644
--- a/sheep/http/swift.c
+++ b/sheep/http/swift.c
@@ -171,7 +171,21 @@ static void swift_delete_container(struct http_request *req,
 static void swift_head_object(struct http_request *req, const char *account,
 			      const char *container, const char *object)
 {
-	http_response_header(req, NOT_IMPLEMENTED);
+	int ret;
+
+	ret = kv_read_object_meta(req, account, container, object);
+	switch (ret) {
+	case SD_RES_SUCCESS:
+		http_response_header(req, OK);
+		break;
+	case SD_RES_NO_VDI:
+	case SD_RES_NO_OBJ:
+		http_response_header(req, NOT_FOUND);
+		break;
+	default:
+		http_response_header(req, INTERNAL_SERVER_ERROR);
+		break;
+	}
 }
 
 static void swift_get_object(struct http_request *req, const char *account,
-- 
1.8.1.2




More information about the sheepdog mailing list