Exemplo n.º 1
0
void fcgi_send_file_revisions(void) {
    const sx_hashfs_volume_t *vol;
    const sx_hashfs_file_t *file;
    int comma = 0;
    rc_ty s;

    s = sx_hashfs_volume_by_name(hashfs, volume, &vol);
    if(s != OK)
	quit_errmsg(rc2http(s), msg_get_reason());

    s = sx_hashfs_revision_first(hashfs, vol, path, &file, 0);
    if(s != OK)
	quit_errmsg(rc2http(s), msg_get_reason());

    CGI_PUTS("Content-type: application/json\r\n\r\n{\"fileRevisions\":{");
    do {
	CGI_PRINTF("%s\"%s\":{\"blockSize\":%d,\"fileSize\":", comma ? "," : "", file->revision, file->block_size);
	CGI_PUTLL(file->file_size);
	CGI_PRINTF(",\"createdAt\":%u}", file->created_at);
	comma = 1;
	s = sx_hashfs_revision_next(hashfs, 0);
    } while(s == OK);
    if(s == ITER_NO_MORE)
	CGI_PUTS("}}");
}
Exemplo n.º 2
0
void fcgi_send_file(void) {
    sx_hashfs_file_t filedata;
    const sx_hash_t *hash;
    sx_nodelist_t *nodes;
    sx_hash_t etag;
    int comma = 0;
    rc_ty s = sx_hashfs_getfile_begin(hashfs, volume, path, get_arg("rev"), &filedata, &etag);

    if(s != OK)
	quit_errnum(s == ENOENT ? 404 : 500);

    if(is_object_fresh(&etag, 'F', filedata.created_at)) {
	sx_hashfs_getfile_end(hashfs);
	return;
    }

    CGI_PRINTF("Content-type: application/json\r\n\r\n{\"blockSize\":%d,\"fileSize\":", filedata.block_size);
    CGI_PUTLL(filedata.file_size);
    CGI_PRINTF(",\"createdAt\":%u,\"fileRevision\":\"%s\",\"fileData\":[", filedata.created_at, filedata.revision);

    while((s = sx_hashfs_getfile_block(hashfs, &hash, &nodes)) == OK) {
	if(comma)
	    CGI_PUTC(',');
	else
	    comma |= 1;
	CGI_PUTC('{');
	send_qstring_hash(hash);
	CGI_PUTC(':');
	/* Nodes are in NL_PREVNEXT order and MUST NOT be randomized
	 * (see comments in sx_hashfs_getfile_block) */
	send_nodes(nodes);
	CGI_PUTC('}');

	sx_nodelist_delete(nodes);
    }

    sx_hashfs_getfile_end(hashfs);
    CGI_PUTS("]");
    if(s != ITER_NO_MORE)
	quit_itererr("Failed to list file blocks", s);

    CGI_PUTS("}");
}
Exemplo n.º 3
0
static void print_html(int status, const char *title, int errnum, const char *errmsg)
{
    if (status)
	CGI_PRINTF("Status: %d\r\n", status);
    CGI_PRINTF("Content-Type: text/html\r\n\r\n");
    CGI_PRINTF(HTML_1, errmsg ? 653: 600);
    CGI_PUTS(HTML_2);
    CGI_PUTS(LOGO);
    CGI_PUTS(HTML_3);
    if (errmsg)
        CGI_PRINTF("<h2>Error %d: %s</h2>", errnum, errmsg);
    unsigned int version;
    const sx_uuid_t *cluster_uuid = sx_hashfs_uuid(hashfs);
    const sx_uuid_t *dist_uuid = sx_hashfs_distinfo(hashfs, &version, NULL);
    sx_uuid_t node_uuid;
    CGI_PRINTF(HTML_4,
               cluster_uuid->string,
               sx_hashfs_self_uuid(hashfs, &node_uuid) == OK ? node_uuid.string : "&lt;not assigned yet&gt;",
               dist_uuid ? dist_uuid->string : "&lt;not defined yet&gt;",
               dist_uuid ? version : 0
               );
}
Exemplo n.º 4
0
static void print_html(int status, const char *title, int errnum, const char *errmsg)
{
    if (status)
	CGI_PRINTF("Status: %d\r\n", status);
    CGI_PRINTF("Content-Type: text/html\r\n\r\n\
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n\
<html>\
    <head><title>%s</title></head>", title);
    CGI_PUTS("<body style='background-color:#9fcdea'>\
        <div style='position:absolute; top:50%; height:20em; margin-top: -10em; text-align:center; width: 90%;'>\
            <img src=\"");
    CGI_PUTS(LOGO1);/* too large to put into printf */
    CGI_PUTS(LOGO2);
    CGI_PUTS("\"/>");
    if (errmsg)
        CGI_PRINTF("<h2>Error %d</h2><pre>%s</pre>", errnum, errmsg);
    CGI_PUTS("\
            <h2>\
                This is an <a href=\"http://www.skylable.com/products/sx\">"SERVER_NAME" node</a>\
            </h2>\
        </div>\
        <div style=\"position: absolute; bottom:1em; right: 1em; border: #ddd 1px solid; font: 10px normal; color: #07c;\">");

    unsigned int version;
    const sx_uuid_t *cluster_uuid = sx_hashfs_uuid(hashfs);
    const sx_uuid_t *dist_uuid = sx_hashfs_distinfo(hashfs, &version, NULL);
    sx_uuid_t node_uuid;
    CGI_PRINTF("Cluster UUID: %s<br>Node UUID: %s<br>Distribution: ", cluster_uuid->string, sx_hashfs_self_uuid(hashfs, &node_uuid) == OK ? node_uuid.string : "&lt;not assigned yet&gt;");
    if(dist_uuid)
	CGI_PRINTF("%s(%u)", dist_uuid->string, version);
    else
	CGI_PUTS("&lt;not defined yet&gt;");
    CGI_PUTS("\
        </div>\
    </body>\
</html>");
}
Exemplo n.º 5
0
static void send_error_helper(const char sep, int errnum, const char *message) {
    sx_uuid_t node_uuid;
    CGI_PRINTF("%c\"ErrorMessage\":", sep);
    json_send_qstring(message ? message : "");
    if (errnum == 500 || errnum == 400) {
        if (message)
            WARN("HTTP %d: %s", errnum, message);
        CGI_PUTS(",\"ErrorDetails\":");
        json_send_qstring(msg_log_end());
    }
    CGI_PUTS(",\"NodeId\":");
    json_send_qstring(sx_hashfs_self_uuid(hashfs, &node_uuid)==OK ? node_uuid.string : "<UNKNOWN>");
    CGI_PUTS(",\"ErrorId\":");
    json_send_qstring(msg_get_id());
    CGI_PUTC('}');
}
Exemplo n.º 6
0
static void send_error_helper(const char sep, int errnum, const char *message) {
    CGI_PRINTF("%c\"ErrorMessage\":", sep);
    json_send_qstring(message);
    if (errnum == 500 || errnum == 400) {
        if (message)
            WARN("HTTP %d: %s", errnum, message);
        CGI_PUTS(",\"ErrorDetails\":");
        json_send_qstring(msg_log_end());
    }
    CGI_PUTS(",\"NodeId\":");
    const sx_node_t *me = sx_hashfs_self(hashfs);
    json_send_qstring(me ? sx_node_uuid(me)->string : "<UNKNOWN>");
    CGI_PUTS(",\"ErrorId\":");
    json_send_qstring(msg_get_id());
    CGI_PUTC('}');
}
Exemplo n.º 7
0
void send_error(int errnum, const char *message) {
    if(!message || !*message)
	message = http_err_str(errnum);

    if(!is_sky()) {
        print_html(errnum, "Error", errnum, message);
    } else {
	CGI_PRINTF("Status: %d\r\nContent-Type: application/json\r\n", errnum);
        if (verb == VERB_HEAD) {
            /* workaround for old curl: it would close (instead of reusing)
             * the connection if a HEAD doesn't have Content-Length/chunked
             * encoding. And then we run out of ports due to too many
             * TIME_WAIT connections */
            CGI_PUTS("Content-Length: 0\r\n\r\n");
        } else {
            CGI_PUTS("\r\n");
            send_error_helper('{',errnum,message);
        }
    }
}
Exemplo n.º 8
0
void send_server_info(void) {
    last_flush = time(NULL);
    CGI_PRINTF("Server: Skylable SX\r\nSX-Cluster: %s (%s)%s\r\nSX-API-Version: %u\r\nVary: Accept-Encoding\r\n", src_version(), sx_hashfs_uuid(hashfs)->string, sx_hashfs_uses_secure_proto(hashfs) ? " ssl" : "", SRC_API_VERSION);
}
Exemplo n.º 9
0
void send_server_info(void) {
    last_flush = time(NULL);
    CGI_PRINTF("Server: Skylable SX\r\nSX-Cluster: %s (%s)\r\nVary: Accept-Encoding\r\n", src_version(), sx_hashfs_uuid(hashfs)->string);
}
Exemplo n.º 10
0
static void create_or_extend_tempfile(const sx_hashfs_volume_t *vol, const char *filename, int extending) {
    const struct jparse_actions acts = {
	JPACTS_INT64(
		     JPACT(cb_newfile_size, JPKEY("fileSize")),
		     JPACT(cb_newfile_seq, JPKEY("extendSeq"))
		     ),
	JPACTS_STRING(
		      JPACT(cb_newfile_block, JPKEY("fileData"), JPANYITM),
		      JPACT(cb_newfile_addmeta, JPKEY("fileMeta"), JPANYKEY)
		      ),
	JPACTS_NULL(
		    JPACT(cb_newfile_delmeta, JPKEY("fileMeta"), JPANYKEY)
		    )
    };
    struct cb_newfile_ctx yctx;
    hash_presence_ctx_t ctx;
    const char *token;
    jparse_t *J;
    int len;
    rc_ty s;

    yctx.filesize = -1;
    yctx.seq = -1;
    yctx.rc = EINVAL;

    J = sxi_jparse_create(&acts, &yctx, 0);
    if(!J) {
	sx_hashfs_putfile_end(hashfs);
	quit_errmsg(503, "Cannot create JSON parser");
    }

    while((len = get_body_chunk(hashbuf, sizeof(hashbuf))) > 0)
	if(sxi_jparse_digest(J, hashbuf, len))
	    break;

    if(len || sxi_jparse_done(J)) {
	send_error(rc2http(yctx.rc), sxi_jparse_geterr(J));
	sx_hashfs_putfile_end(hashfs);
	sxi_jparse_destroy(J);
	return;
    }
    sxi_jparse_destroy(J);

    auth_complete();
    quit_unless_authed();

    s = sx_hashfs_putfile_gettoken(hashfs, user, yctx.filesize, yctx.seq, &token, hash_presence_callback, &ctx);
    if (s != OK) {
	sx_hashfs_putfile_end(hashfs);
	if(!*msg_get_reason())
	    msg_set_reason("Cannot obtain upload token: %s", rc2str(s));
	quit_errmsg((s == ENOSPC) ? 413 : rc2http(s), msg_get_reason());
    }

    CGI_PRINTF("Content-type: application/json\r\n\r\n{\"uploadToken\":");
    json_send_qstring(extending ? path : token);
    CGI_PUTS(",\"uploadData\":{");
    ctx.h = hashfs;
    ctx.comma = 0;
    while((s = sx_hashfs_putfile_getblock(hashfs)) == OK) {
	/* Nothing to do here, API does a little bit of work at a time by design
	 * We can stick keepalives in here if we ever need to */
    }
    sx_hashfs_putfile_end(hashfs);
    CGI_PUTS("}");
    if(s != ITER_NO_MORE) {
	quit_itererr("Failed to send file blocks", s);
    }

    CGI_PUTS("}");
}