static void send_response(wurfld_connection_context *ctx) { char *useragent = ctx->useragent; DEBUG1("Worker %p is looking up useragent : %s", pthread_self(), useragent); // this might be unnecessary if libwurfl is thread-safe // XXX - needs to be checked wurfld_get_capabilities(useragent, ctx->output); if (use_http) { char response_header[1024]; sprintf(response_header, "%s 200 OK\r\n" "Content-Type: application/json\r\n" "Content-length: %d\r\n" "Server: wurfld\r\n" "Connection: Close\r\n\r\n", ctx->is_http10 ? "HTTP/1.0" : "HTTP/1.1", fbuf_used(ctx->output)); int err = write_socket(ctx->fd, response_header, strlen(response_header)); if (err != 0) { ERROR("(%p) Can't write the response header : %s", pthread_self(), strerror(errno)); } } if (write_socket(ctx->fd, fbuf_data(ctx->output), fbuf_used(ctx->output)) != 0) { ERROR("(%p) Can't write the response data : %s", pthread_self(), strerror(errno)); } }
size_t shardcache_client_offset(shardcache_client_t *c, void *key, size_t klen, uint32_t offset, void *data, uint32_t dlen) { int fd = -1; char *addr = select_node(c, key, klen, &fd); if (fd < 0) { c->errno = SHARDCACHE_CLIENT_ERROR_NETWORK; snprintf(c->errstr, sizeof(c->errstr), "Can't connect to '%s'", addr); return 0; } fbuf_t value = FBUF_STATIC_INITIALIZER; int rc = offset_from_peer(addr, (char *)c->auth, SHC_HDR_SIGNATURE_SIP, key, klen, offset, dlen, &value, fd); if (rc == 0) { uint32_t to_copy = dlen > fbuf_used(&value) ? fbuf_used(&value) : dlen; if (data) memcpy(data, fbuf_data(&value), to_copy); c->errno = SHARDCACHE_CLIENT_OK; c->errstr[0] = 0; connections_pool_add(c->connections, addr, fd); fbuf_destroy(&value); return to_copy; } else { close(fd); c->errno = SHARDCACHE_CLIENT_ERROR_NODE; snprintf(c->errstr, sizeof(c->errstr), "Can't fetch data from node '%s'", addr); } fbuf_destroy(&value); return 0; }
static void wurfld_input_handler(iomux_t *iomux, int fd, void *data, int len, void *priv) { wurfld_connection_context *ctx = (wurfld_connection_context *)priv; if (!ctx) return; DEBUG1("New data on fd %d", fd); fbuf_add_binary(ctx->input, data, len); if (fbuf_used(ctx->input) < 4) return; // check if we have a complete requset char *current_data = fbuf_end(ctx->input) - (use_http ? 4 : 1); char *request_terminator = use_http ? strstr(current_data, "\r\n\r\n") : strstr(current_data, "\n"); if (!request_terminator && use_http) { // support some broken clients/requests request_terminator = strstr(current_data, "\n\n"); } if (request_terminator) { // we have a complete request so we can now start // background worker to handle it pthread_t worker_thread; ctx->fd = fd; // let the worker take care of the fd from now on iomux_remove(iomux, fd); if (single_thread) { worker(ctx); } else { pthread_create(&worker_thread, NULL, worker, ctx); pthread_detach(worker_thread); } } }
size_t shardcache_client_get(shardcache_client_t *c, void *key, size_t klen, void **data) { int fd = -1; char *addr = select_node(c, key, klen, &fd); if (fd < 0) { c->errno = SHARDCACHE_CLIENT_ERROR_NETWORK; snprintf(c->errstr, sizeof(c->errstr), "Can't connect to '%s'", addr); return 0; } fbuf_t value = FBUF_STATIC_INITIALIZER; int rc = fetch_from_peer(addr, (char *)c->auth, SHC_HDR_SIGNATURE_SIP, key, klen, &value, fd); if (rc == 0) { size_t size = fbuf_used(&value); if (data) *data = fbuf_data(&value); else fbuf_destroy(&value); c->errno = SHARDCACHE_CLIENT_OK; c->errstr[0] = 0; connections_pool_add(c->connections, addr, fd); return size; } else { close(fd); c->errno = SHARDCACHE_CLIENT_ERROR_NODE; snprintf(c->errstr, sizeof(c->errstr), "Can't fetch data from node '%s'", addr); return 0; } return 0; }
int shardcache_client_migration_begin(shardcache_client_t *c, shardcache_node_t **nodes, int num_nodes) { fbuf_t mgb_message = FBUF_STATIC_INITIALIZER; int i; for (i = 0; i < num_nodes; i++) { if (i > 0) fbuf_add(&mgb_message, ","); fbuf_printf(&mgb_message, "%s:%s", shardcache_node_get_string(nodes[i])); } for (i = 0; i < c->num_shards; i++) { char *addr = shardcache_node_get_address(c->shards[i]); int fd = connections_pool_get(c->connections, addr); if (fd < 0) { c->errno = SHARDCACHE_CLIENT_ERROR_NETWORK; snprintf(c->errstr, sizeof(c->errstr), "Can't connect to '%s'", addr); fbuf_destroy(&mgb_message); return -1; } int rc = migrate_peer(addr, (char *)c->auth, SHC_HDR_SIGNATURE_SIP, fbuf_data(&mgb_message), fbuf_used(&mgb_message), fd); if (rc != 0) { close(fd); c->errno = SHARDCACHE_CLIENT_ERROR_NODE; snprintf(c->errstr, sizeof(c->errstr), "Node '%s' (%s) didn't aknowledge the migration\n", shardcache_node_get_label(c->shards[i]), addr); fbuf_destroy(&mgb_message); // XXX - should we abort migration on peers that have been notified (if any)? return -1; } connections_pool_add(c->connections, addr, fd); } fbuf_destroy(&mgb_message); c->errno = SHARDCACHE_CLIENT_OK; c->errstr[0] = 0; return 0; }