Example #1
0
int map_join(lua_State *L) {
   int rc = 0;
   int err_rc = -1;
   map_t *map = (map_t *)lua_touserdata(L, 1);
   for (uint32_t i = 0; i < map->num_threads; i++) {
      if (map->threads[i].rb) {
         int ret = pthread_join(map->threads[i].thread, NULL);
         if (ret) return LUA_HANDLE_ERROR(L, ret);
         if (map->threads[i].ret) {
            err_rc = rc;
         }
         while (ringbuffer_peek(map->threads[i].rb)) {
            rb_load(L, map->threads[i].rb);
            rc++;
         }
         ringbuffer_destroy(map->threads[i].rb);
      }
   }
   free(map->threads);
   map->threads = NULL;
   map->num_threads = 0;
   if (err_rc >= 0) {
      return LUA_HANDLE_ERROR_STR(L, lua_tostring(L, err_rc - rc));
   }
   return rc;
}
Example #2
0
static int transport_bio_buffered_write(BIO* bio, const char* buf, int num)
{
	int i, ret;
	int status;
	int nchunks;
	int committedBytes;
	DataChunk chunks[2];
	WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*) bio->ptr;

	ret = num;
	ptr->writeBlocked = FALSE;
	BIO_clear_flags(bio, BIO_FLAGS_WRITE);

	/* we directly append extra bytes in the xmit buffer, this could be prevented
	 * but for now it makes the code more simple.
	 */
	if (buf && num && !ringbuffer_write(&ptr->xmitBuffer, (const BYTE*) buf, num))
	{
		WLog_ERR(TAG, "an error occured when writing (num: %d)", num);
		return -1;
	}

	committedBytes = 0;
	nchunks = ringbuffer_peek(&ptr->xmitBuffer, chunks, ringbuffer_used(&ptr->xmitBuffer));

	for (i = 0; i < nchunks; i++)
	{
		while (chunks[i].size)
		{
			status = BIO_write(bio->next_bio, chunks[i].data, chunks[i].size);

			if (status <= 0)
			{
				if (!BIO_should_retry(bio->next_bio))
				{
					BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
					ret = -1; /* fatal error */
					goto out;
				}

				if (BIO_should_write(bio->next_bio))
				{
					BIO_set_flags(bio, BIO_FLAGS_WRITE);
					ptr->writeBlocked = TRUE;
					goto out; /* EWOULDBLOCK */
				}
			}

			committedBytes += status;
			chunks[i].size -= status;
			chunks[i].data += status;
		}
	}

out:
	ringbuffer_commit_read_bytes(&ptr->xmitBuffer, committedBytes);

	return ret;
}
Example #3
0
int16_t cereal_peek()
{
	if (!ringbuffer_isempty(&cereal_incoming)) {
		return ringbuffer_peek(&cereal_incoming);
	}
	else {
		return -1;
	}
}
Example #4
0
static int transport_bio_buffered_write(BIO* bio, const char* buf, int num)
{
	int status, ret;
	rdpTcp* tcp = (rdpTcp*) bio->ptr;
	int nchunks, committedBytes, i;
	DataChunk chunks[2];

	ret = num;
	tcp->writeBlocked = FALSE;
	BIO_clear_flags(bio, BIO_FLAGS_WRITE);

	/* we directly append extra bytes in the xmit buffer, this could be prevented
	 * but for now it makes the code more simple.
	 */
	if (buf && num && !ringbuffer_write(&tcp->xmitBuffer, (const BYTE*) buf, num))
	{
		fprintf(stderr, "%s: an error occured when writing(toWrite=%d)\n", __FUNCTION__, num);
		return -1;
	}

	committedBytes = 0;
	nchunks = ringbuffer_peek(&tcp->xmitBuffer, chunks, ringbuffer_used(&tcp->xmitBuffer));

	for (i = 0; i < nchunks; i++)
	{
		while (chunks[i].size)
		{
			status = BIO_write(bio->next_bio, chunks[i].data, chunks[i].size);

			if (status <= 0)
			{
				if (!BIO_should_retry(bio->next_bio))
				{
					BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
					ret = -1; /* fatal error */
					goto out;
				}

				if (BIO_should_write(bio->next_bio))
				{
					BIO_set_flags(bio, BIO_FLAGS_WRITE);
					tcp->writeBlocked = TRUE;
					goto out; /* EWOULDBLOCK */
				}
			}

			committedBytes += status;
			chunks[i].size -= status;
			chunks[i].data += status;
		}
	}

out:
	ringbuffer_commit_read_bytes(&tcp->xmitBuffer, committedBytes);
	return ret;
}
Example #5
0
/**
 * Get a pointer to the key. If the buffer isn't continous we need to
 * allocate a temporary chunk of memory and copy the packet over there.
 * packet will return the pointer to the newly allocated packet or
 * NULL if we didn't have to allocate anything.
 *
 * @param server the server owning the key
 * @param nkey the number of bytes in the key
 * @param packet where to store the result
 * @return pointer to the key
 */
static const char *get_key(lcb_server_t *server, lcb_uint16_t *nkey,
                           char **packet)
{
    protocol_binary_request_header req;
    lcb_size_t nr = ringbuffer_peek(&server->cmd_log,
                                    req.bytes, sizeof(req));
    lcb_size_t packetsize = ntohl(req.request.bodylen) + (lcb_uint32_t)sizeof(req);
    char *keyptr;
    *packet = server->cmd_log.read_head;
    lcb_assert(nr == sizeof(req));

    *nkey = ntohs(req.request.keylen);
    keyptr = *packet + sizeof(req) + req.request.extlen;
    *packet = NULL;

    if (!ringbuffer_is_continous(&server->cmd_log,
                                 RINGBUFFER_READ,
                                 packetsize)) {
        *packet = malloc(packetsize);
        if (*packet == NULL) {
            lcb_error_handler(server->instance, LCB_CLIENT_ENOMEM,
                              NULL);
            return NULL;
        }

        nr = ringbuffer_peek(&server->cmd_log, *packet, packetsize);
        if (nr != packetsize) {
            lcb_error_handler(server->instance, LCB_EINTERNAL,
                              NULL);
            free(*packet);
            return NULL;
        }
        keyptr = *packet + sizeof(req) + req.request.extlen;
    }

    return keyptr;
}
Example #6
0
int map_check_errors(lua_State *L) {
   map_t *map = (map_t *)lua_touserdata(L, 1);
   for (uint32_t i = 0; i < map->num_threads; i++) {
      if (map->threads[i].ret) {
         pthread_join(map->threads[i].thread, NULL);
         while (ringbuffer_peek(map->threads[i].rb)) {
            rb_load(L, map->threads[i].rb);
         }
         ringbuffer_destroy(map->threads[i].rb);
         map->threads[i].rb = NULL;
         return LUA_HANDLE_ERROR_STR(L, lua_tostring(L, -1));
      }
   }
   return 0;
}
Example #7
0
static int sock_send_msg(lua_State *L, int index, int sock, ringbuffer_t *rb, copy_context_t *copy_context) {
   ringbuffer_push_write_pos(rb);
   int ret = rb_save(L, index, rb, 1);
   if (ret) return LUA_HANDLE_ERROR(L, ret);
   size_t len = ringbuffer_peek(rb);
   ringbuffer_pop_write_pos(rb);
   if (ret) return ret;
   ret = sock_send(sock, &len, sizeof(len), copy_context);
   if (ret < 0) return LUA_HANDLE_ERROR(L, errno);
   if (ret != sizeof(len)) return LUA_HANDLE_ERROR_STR(L, "failed to send the correct number of bytes");
   ret = sock_send(sock, ringbuffer_buf_ptr(rb), len, copy_context);
   if (ret < 0) return LUA_HANDLE_ERROR(L, errno);
   if ((size_t)ret != len) return LUA_HANDLE_ERROR_STR(L, "failed to send the correct number of bytes");
   return 0;
}
Example #8
0
static void* thread_func(void *arg) {
#ifdef _OPENMP
   // prevent MKL/BLAS from crashing on the reader threads
   // its use of open-mp eats up way too many threads
   omp_set_num_threads(1);
#endif
   map_thread_t *map_thread = (map_thread_t *)arg;
   lua_State *L = luaL_newstate();
   if (_ipc_static_init_thread) {
      _ipc_static_init_thread(L);
   } else {
      luaL_openlibs(L);
   }
   // in order to deserialize arguments we need torch and libipc
   // TODO: detect these on the main thread when serializing arguments
   int top = lua_gettop(L);
   if (luaL_loadstring(L, "require 'torch'; require 'libipc'; pcall(require, 'twutil')")) {
      lua_close(L);
      return NULL;
   }
   map_thread->ret = lua_pcall(L, 0, 0, 0);
   if (map_thread->ret) {
      fprintf(stderr, "WARN: ipc.map thread pcall failed: %s\n", lua_tostring(L, -1));
   } else {
      top = lua_gettop(L);
      int i = 0;
      while (ringbuffer_peek(map_thread->rb)) {
         rb_load(L, map_thread->rb);
         i++;
      }
      map_thread->ret = lua_pcall(L, i - 1, LUA_MULTRET, 0);
      if (map_thread->ret) {
         fprintf(stderr, "WARN: ipc.map thread pcall failed: %s\n", lua_tostring(L, -1));
      }
   }
   int k = lua_gettop(L) - top;
   for (int i = 1; i <= k; i++) {
      int ret = rb_save_with_growth(L, top + i, map_thread->rb);
      if (ret) {
         fprintf(stderr, "WARN: ipc.map thread failed to write results: %s\n", strerror(-ret));
         map_thread->ret = ret;
         break;
      }
   }
   lua_close(L);
   return 0;
}
Example #9
0
APULSE_EXPORT
int
pa_stream_peek(pa_stream *s, const void **data, size_t *nbytes)
{
    trace_info_f("F %s s=%p\n", __func__, s);

    if (!s)
        return -1;

    size_t len = ringbuffer_readable_size(s->rb);
    s->peek_buffer_data_len = ringbuffer_peek(s->rb, s->peek_buffer, len);

    if (nbytes)
        *nbytes = s->peek_buffer_data_len;
    if (data)
        *data = s->peek_buffer;
    return 0;
}
Example #10
0
static int workqueue_queue_write(lua_State *L, int index, queue_t *queue) {
   pthread_mutex_lock(&queue->mutex);
   int ret = 0;
   while (1) {
      ringbuffer_push_write_pos(queue->rb);
      ret = rb_save(L, index, queue->rb, 0);
      if (ret) {
         ringbuffer_pop_write_pos(queue->rb);
         if (ringbuffer_peek(queue->rb)) {
            pthread_cond_wait(&queue->write_avail_cond, &queue->mutex);
         } else {
            return LUA_HANDLE_ERROR_STR(L, "workqueue.write message is too big for the ring buffer.");
         }
      } else {
         break;
      }
   }
   queue->num_items++;
   pthread_cond_signal(&queue->read_avail_cond);
   pthread_mutex_unlock(&queue->mutex);
   return ret;
}
Example #11
0
static void observe_response_handler(lcb_server_t *server,
                                     packet_info *info)
{
    lcb_t root = server->instance;
    lcb_error_t rc = map_error(root, PACKET_STATUS(info));
    lcb_uint32_t ttp;
    lcb_uint32_t ttr;
    lcb_size_t pos;

    VBUCKET_CONFIG_HANDLE config;
    const char *end, *ptr;

    /**
     * If we have an error we must decode the request instead
     */
    if (rc != LCB_SUCCESS) {
        protocol_binary_request_header req;
        lcb_size_t nr;

        nr = ringbuffer_peek(&server->cmd_log, req.bytes, sizeof(req.bytes));
        if (nr != sizeof(req.bytes)) {
            lcb_error_handler(server->instance, LCB_EINTERNAL, NULL);
            abort();
        }

        if (req.request.bodylen) {
            lcb_size_t npacket = sizeof(req.bytes) + ntohl(req.request.bodylen);
            char *packet = server->cmd_log.read_head;
            int allocated = 0;

            if (!ringbuffer_is_continous(&server->cmd_log, RINGBUFFER_READ, npacket)) {
                packet = malloc(npacket);
                if (packet == NULL) {
                    lcb_error_handler(root, LCB_CLIENT_ENOMEM, NULL);
                    abort();
                }
                nr = ringbuffer_peek(&server->cmd_log, packet, npacket);
                if (nr != npacket) {
                    lcb_error_handler(root, LCB_EINTERNAL, NULL);
                    free(packet);
                    abort();
                }
                allocated = 1;
            }
            lcb_failout_observe_request(server, &info->ct, packet, npacket, rc);
            if (allocated) {
                free(packet);
            }
        }
        return;
    }

    /** The CAS field is split into TTP/TTR values */
    ptr = (char *)&info->res.response.cas;
    memcpy(&ttp, ptr, sizeof(ttp));
    memcpy(&ttr, ptr + sizeof(ttp), sizeof(ttp));

    ttp = ntohl(ttp);
    ttr = ntohl(ttr);

    /** Actual payload sequence of (vb, nkey, key). Repeats multiple times */
    ptr = info->payload;
    end = (char *)ptr + PACKET_NBODY(info);
    config = root->vbucket_config;

    for (pos = 0; ptr < end; pos++) {
        lcb_cas_t cas;
        lcb_uint8_t obs;
        lcb_uint16_t nkey, vb;
        const char *key;
        lcb_observe_resp_t resp;

        memcpy(&vb, ptr, sizeof(vb));
        vb = ntohs(vb);
        ptr += sizeof(vb);
        memcpy(&nkey, ptr, sizeof(nkey));
        nkey = ntohs(nkey);
        ptr += sizeof(nkey);
        key = (const char *)ptr;
        ptr += nkey;
        obs = *((lcb_uint8_t *)ptr);
        ptr += sizeof(obs);
        memcpy(&cas, ptr, sizeof(cas));
        ptr += sizeof(cas);

        setup_lcb_observe_resp_t(&resp, key, nkey, cas, obs,
                                 server->index == vbucket_get_master(config, vb),
                                 ttp, ttr);
        PACKET_TRACE(TRACE_OBSERVE_PROGRESS, info, rc, &resp);
        lcb_observe_invoke_callback(root, &info->ct, rc, &resp);
    }

    /* run callback with null-null-null to signal the end of transfer */
    if ((info->ct.flags & LCB_CMD_F_OBS_BCAST) &&
            lcb_lookup_server_with_command(root, CMD_OBSERVE,
                                           PACKET_OPAQUE(info), server) < 0) {

        lcb_observe_resp_t resp;
        memset(&resp, 0, sizeof(resp));
        PACKET_TRACE_NORES(TRACE_OBSERVE_END, info, rc);
        lcb_observe_invoke_callback(root, &info->ct, LCB_SUCCESS, &resp);
    }
}
Example #12
0
int lcb_proto_parse_single(lcb_server_t *c, hrtime_t stop)
{
    int rv;
    packet_info info;
    protocol_binary_request_header req;
    lcb_size_t nr;
    lcb_connection_t conn = &c->connection;

    rv = lcb_packet_read_ringbuffer(&info, conn->input);
    if (rv == -1) {
        return -1;
    } else if (rv == 0) {
        return 0;
    }

    /* Is it already timed out? */
    nr = ringbuffer_peek(&c->cmd_log, req.bytes, sizeof(req));
    if (nr < sizeof(req) || /* the command log doesn't know about it */
            (PACKET_OPAQUE(&info) < req.request.opaque &&
             PACKET_OPAQUE(&info) > 0)) { /* sasl comes with zero opaque */
        /* already processed. */
        lcb_packet_release_ringbuffer(&info, conn->input);
        return 1;
    }


    nr = ringbuffer_peek(&c->output_cookies, &info.ct, sizeof(info.ct));
    if (nr != sizeof(info.ct)) {
        lcb_error_handler(c->instance, LCB_EINTERNAL, NULL);
        lcb_packet_release_ringbuffer(&info, conn->input);
        return -1;
    }
    info.ct.vbucket = ntohs(req.request.vbucket);

    switch (info.res.response.magic) {
    case PROTOCOL_BINARY_REQ:
        /*
         * The only way to get request packets is if someone started
         * to send us TAP requests, and we don't support that anymore
         */
        lcb_error_handler(c->instance, LCB_EINTERNAL,
                          "Protocol error. someone sent us a command!");
        return -1;
    case PROTOCOL_BINARY_RES: {
        int was_connected = c->connection_ready;
        rv = lcb_server_purge_implicit_responses(c,
                PACKET_OPAQUE(&info),
                stop, 0);
        if (rv != 0) {
            lcb_packet_release_ringbuffer(&info, conn->input);
            return -1;
        }

        if (c->instance->histogram) {
            lcb_record_metrics(c->instance, stop - info.ct.start,
                               PACKET_OPCODE(&info));
        }

        if (PACKET_STATUS(&info) != PROTOCOL_BINARY_RESPONSE_NOT_MY_VBUCKET
                || PACKET_OPCODE(&info) == CMD_GET_REPLICA
                || PACKET_OPCODE(&info) == CMD_OBSERVE) {
            rv = lcb_dispatch_response(c, &info);
            if (rv == -1) {
                lcb_error_handler(c->instance, LCB_EINTERNAL,
                                  "Received unknown command response");
                abort();
                return -1;
            }

            /* keep command and cookie until we get complete STAT response */
            swallow_command(c, &info.res, was_connected);

        } else {
            rv = handle_not_my_vbucket(c, &info, &req, &info.ct);

            if (rv == -1) {
                return -1;

            } else if (rv == 0) {
                lcb_dispatch_response(c, &info);
                swallow_command(c, &info.res, was_connected);
            }

        }
        break;
    }

    default:
        lcb_error_handler(c->instance, LCB_PROTOCOL_ERROR, NULL);
        lcb_packet_release_ringbuffer(&info, conn->input);
        return -1;
    }

    lcb_packet_release_ringbuffer(&info, conn->input);
    return 1;
}
Example #13
0
static void observe_response_handler(lcb_server_t *server,
                                     struct lcb_command_data_st *command_data,
                                     protocol_binary_response_header *res)
{
    lcb_t root = server->instance;
    lcb_uint16_t status = ntohs(res->response.status);
    lcb_error_t rc = map_error(root, status);
    lcb_uint32_t ttp;
    lcb_uint32_t ttr;
    lcb_size_t pos;

    VBUCKET_CONFIG_HANDLE config;
    const char *end, *ptr = (const char *)&res->response.cas;

    /**
     * If we have an error we must decode the request instead
     */
    if (rc != LCB_SUCCESS) {
        protocol_binary_request_header req;
        lcb_size_t nr;

        nr = ringbuffer_peek(&server->cmd_log, req.bytes, sizeof(req.bytes));
        if (nr != sizeof(req.bytes)) {
            lcb_error_handler(server->instance, LCB_EINTERNAL, NULL);
            abort();
        }
        if (req.request.bodylen) {
            lcb_size_t npacket = sizeof(req.bytes) + ntohl(req.request.bodylen);
            char *packet = server->cmd_log.read_head;
            int allocated = 0;

            if (!ringbuffer_is_continous(&server->cmd_log, RINGBUFFER_READ, npacket)) {
                packet = malloc(npacket);
                if (packet == NULL) {
                    lcb_error_handler(root, LCB_CLIENT_ENOMEM, NULL);
                    abort();
                }
                nr = ringbuffer_peek(&server->cmd_log, packet, npacket);
                if (nr != npacket) {
                    lcb_error_handler(root, LCB_EINTERNAL, NULL);
                    free(packet);
                    abort();
                }
                allocated = 1;
            }
            lcb_failout_observe_request(server, command_data, packet, npacket, rc);
            if (allocated) {
                free(packet);
            }
        }
        return;
    }


    memcpy(&ttp, ptr, sizeof(ttp));
    ttp = ntohl(ttp);
    memcpy(&ttr, ptr + sizeof(ttp), sizeof(ttr));
    ttr = ntohl(ttr);


    ptr = (const char *)res + sizeof(res->bytes);
    end = ptr + ntohl(res->response.bodylen);
    config = root->vbucket_config;
    for (pos = 0; ptr < end; pos++) {
        lcb_cas_t cas;
        lcb_uint8_t obs;
        lcb_uint16_t nkey, vb;
        const char *key;
        lcb_observe_resp_t resp;

        memcpy(&vb, ptr, sizeof(vb));
        vb = ntohs(vb);
        ptr += sizeof(vb);
        memcpy(&nkey, ptr, sizeof(nkey));
        nkey = ntohs(nkey);
        ptr += sizeof(nkey);
        key = (const char *)ptr;
        ptr += nkey;
        obs = *((lcb_uint8_t *)ptr);
        ptr += sizeof(obs);
        memcpy(&cas, ptr, sizeof(cas));
        ptr += sizeof(cas);

        setup_lcb_observe_resp_t(&resp, key, nkey, cas, obs,
                                 server->index == vbucket_get_master(config, vb),
                                 ttp, ttr);
        TRACE_OBSERVE_PROGRESS(res->response.opaque, command_data->vbucket,
                               res->response.opcode, rc, &resp);
        lcb_observe_invoke_callback(root, command_data, rc, &resp);
    }

    /* run callback with null-null-null to signal the end of transfer */
    if ((command_data->flags & LCB_CMD_F_OBS_BCAST) &&
            lcb_lookup_server_with_command(root, CMD_OBSERVE,
                                           res->response.opaque, server) < 0) {

        lcb_observe_resp_t resp;
        memset(&resp, 0, sizeof(resp));
        TRACE_OBSERVE_END(res->response.opaque, command_data->vbucket,
                          res->response.opcode, rc);
        lcb_observe_invoke_callback(root, command_data, LCB_SUCCESS, &resp);
    }
}
Example #14
0
static int parse_single(libcouchbase_server_t *c, hrtime_t stop)
{
    protocol_binary_request_header req;
    protocol_binary_response_header header;
    libcouchbase_size_t nr;
    char *packet;
    libcouchbase_size_t packetsize;
    struct libcouchbase_command_data_st ct;

    nr = ringbuffer_peek(&c->input, header.bytes, sizeof(header));
    if (nr < sizeof(header)) {
        return 0;
    }

    packetsize = ntohl(header.response.bodylen) + (libcouchbase_uint32_t)sizeof(header);
    if (c->input.nbytes < packetsize) {
        return 0;
    }

    /* Is it already timed out? */
    nr = ringbuffer_peek(&c->cmd_log, req.bytes, sizeof(req));
    if (nr < sizeof(req) || /* the command log doesn't know about it */
            (header.response.opaque < req.request.opaque &&
             header.response.opaque > 0)) { /* sasl comes with zero opaque */
        /* already processed. */
        ringbuffer_consumed(&c->input, packetsize);
        return 1;
    }

    packet = c->input.read_head;
    /* we have everything! */

    if (!ringbuffer_is_continous(&c->input, RINGBUFFER_READ,
                                 packetsize)) {
        /* The buffer isn't continous.. for now just copy it out and
        ** operate on the copy ;)
        */
        if ((packet = malloc(packetsize)) == NULL) {
            libcouchbase_error_handler(c->instance, LIBCOUCHBASE_CLIENT_ENOMEM, NULL);
            return -1;
        }
        nr = ringbuffer_read(&c->input, packet, packetsize);
        if (nr != packetsize) {
            libcouchbase_error_handler(c->instance, LIBCOUCHBASE_EINTERNAL,
                                       NULL);
            free(packet);
            return -1;
        }
    }

    nr = ringbuffer_peek(&c->output_cookies, &ct, sizeof(ct));
    if (nr != sizeof(ct)) {
        libcouchbase_error_handler(c->instance, LIBCOUCHBASE_EINTERNAL,
                                   NULL);
        if (packet != c->input.read_head) {
            free(packet);
        }
        return -1;
    }
    ct.vbucket = ntohs(req.request.vbucket);

    switch (header.response.magic) {
    case PROTOCOL_BINARY_REQ:
        c->instance->request_handler[header.response.opcode](c, &ct, (void *)packet);
        break;
    case PROTOCOL_BINARY_RES: {
        int was_connected = c->connected;
        if (libcouchbase_server_purge_implicit_responses(c, header.response.opaque, stop) != 0) {
            if (packet != c->input.read_head) {
                free(packet);
            }
            return -1;
        }

        if (c->instance->histogram) {
            libcouchbase_record_metrics(c->instance, stop - ct.start,
                                        header.response.opcode);
        }

        if (ntohs(header.response.status) != PROTOCOL_BINARY_RESPONSE_NOT_MY_VBUCKET
            || header.response.opcode == CMD_GET_REPLICA) {
            c->instance->response_handler[header.response.opcode](c, &ct, (void *)packet);
            /* keep command and cookie until we get complete STAT response */
            if (was_connected &&
                    (header.response.opcode != PROTOCOL_BINARY_CMD_STAT || header.response.keylen == 0)) {
                nr = ringbuffer_read(&c->cmd_log, req.bytes, sizeof(req));
                assert(nr == sizeof(req));
                ringbuffer_consumed(&c->cmd_log, ntohl(req.request.bodylen));
                ringbuffer_consumed(&c->output_cookies, sizeof(ct));
            }
        } else {
            int idx;
            char *body;
            libcouchbase_size_t nbody;
            libcouchbase_server_t *new_srv;
            /* re-schedule command to new server */
            nr = ringbuffer_read(&c->cmd_log, req.bytes, sizeof(req));
            assert(nr == sizeof(req));
            idx = vbucket_found_incorrect_master(c->instance->vbucket_config,
                                                 ntohs(req.request.vbucket),
                                                 (int)c->index);
            assert((libcouchbase_size_t)idx < c->instance->nservers);
            new_srv = c->instance->servers + idx;
            req.request.opaque = ++c->instance->seqno;
            nbody = ntohl(req.request.bodylen);
            body = malloc(nbody);
            if (body == NULL) {
                libcouchbase_error_handler(c->instance, LIBCOUCHBASE_CLIENT_ENOMEM, NULL);
                return -1;
            }
            nr = ringbuffer_read(&c->cmd_log, body, nbody);
            assert(nr == nbody);
            nr = ringbuffer_read(&c->output_cookies, &ct, sizeof(ct));
            assert(nr == sizeof(ct));
            /* Preserve the cookie and timestamp for the command. This means
             * that the library will retry the command until its time will
             * out and the client will get LIBCOUCHBASE_ETIMEDOUT error in
             * command callback */
            libcouchbase_server_retry_packet(new_srv, &ct, &req, sizeof(req));
            libcouchbase_server_write_packet(new_srv, body, nbody);
            libcouchbase_server_end_packet(new_srv);
            libcouchbase_server_send_packets(new_srv);
            free(body);
        }
        break;
    }

    default:
        libcouchbase_error_handler(c->instance,
                                   LIBCOUCHBASE_PROTOCOL_ERROR,
                                   NULL);
        if (packet != c->input.read_head) {
            free(packet);
        }
        return -1;
    }

    if (packet != c->input.read_head) {
        free(packet);
    } else {
        ringbuffer_consumed(&c->input, packetsize);
    }
    return 1;
}
Example #15
0
int tls_write_all(rdpTls* tls, const BYTE* data, int length)
{
	int status, nchunks, commitedBytes;
	rdpTcp *tcp;
#ifdef HAVE_POLL_H
	struct pollfd pollfds;
#else
	fd_set rset, wset;
	fd_set *rsetPtr, *wsetPtr;
	struct timeval tv;
#endif
	BIO* bio = tls->bio;
	DataChunk chunks[2];

	BIO* bufferedBio = findBufferedBio(bio);

	if (!bufferedBio)
	{
		DEBUG_WARN( "%s: error unable to retrieve the bufferedBio in the BIO chain\n", __FUNCTION__);
		return -1;
	}

	tcp = (rdpTcp*) bufferedBio->ptr;

	do
	{
		status = BIO_write(bio, data, length);

		if (status > 0)
			break;

		if (!BIO_should_retry(bio))
			return -1;
#ifdef HAVE_POLL_H
		pollfds.fd = tcp->sockfd;
		pollfds.revents = 0;
		pollfds.events = 0;

		if (tcp->writeBlocked)
		{
			pollfds.events |= POLLOUT;
		}
		else if (tcp->readBlocked)
		{
			pollfds.events |= POLLIN;
		}
		else
		{
			DEBUG_WARN( "%s: weird we're blocked but the underlying is not read or write blocked !\n", __FUNCTION__);
			USleep(10);
			continue;
		}

		do
		{
			status = poll(&pollfds, 1, 100);
		}
		while ((status < 0) && (errno == EINTR));
#else
		/* we try to handle SSL want_read and want_write nicely */
		rsetPtr = wsetPtr = NULL;

		if (tcp->writeBlocked)
		{
			wsetPtr = &wset;
			FD_ZERO(&wset);
			FD_SET(tcp->sockfd, &wset);
		}
		else if (tcp->readBlocked)
		{
			rsetPtr = &rset;
			FD_ZERO(&rset);
			FD_SET(tcp->sockfd, &rset);
		}
		else
		{
			DEBUG_WARN( "%s: weird we're blocked but the underlying is not read or write blocked !\n", __FUNCTION__);
			USleep(10);
			continue;
		}

		tv.tv_sec = 0;
		tv.tv_usec = 100 * 1000;

		status = _select(tcp->sockfd + 1, rsetPtr, wsetPtr, NULL, &tv);
#endif
		if (status < 0)
			return -1;
	}
	while (TRUE);

	/* make sure the output buffer is empty */
	commitedBytes = 0;
	while ((nchunks = ringbuffer_peek(&tcp->xmitBuffer, chunks, ringbuffer_used(&tcp->xmitBuffer))))
	{
		int i;

		for (i = 0; i < nchunks; i++)
		{
			while (chunks[i].size)
			{
				status = BIO_write(tcp->socketBio, chunks[i].data, chunks[i].size);

				if (status > 0)
				{
					chunks[i].size -= status;
					chunks[i].data += status;
					commitedBytes += status;
					continue;
				}

				if (!BIO_should_retry(tcp->socketBio))
					goto out_fail;

#ifdef HAVE_POLL_H
				pollfds.fd = tcp->sockfd;
				pollfds.events = POLLIN;
				pollfds.revents = 0;

				do
				{
					status = poll(&pollfds, 1, 100);
				}
				while ((status < 0) && (errno == EINTR));
#else
				FD_ZERO(&rset);
				FD_SET(tcp->sockfd, &rset);
				tv.tv_sec = 0;
				tv.tv_usec = 100 * 1000;

				status = _select(tcp->sockfd + 1, &rset, NULL, NULL, &tv);
#endif
				if (status < 0)
					goto out_fail;
			}

		}
	}

	ringbuffer_commit_read_bytes(&tcp->xmitBuffer, commitedBytes);
	return length;

out_fail:
	ringbuffer_commit_read_bytes(&tcp->xmitBuffer, commitedBytes);
	return -1;
}
Example #16
0
bool unittest_ringbuffer(void) {
    uint8_t byteBuffer[128];
    unsigned length;
    ringbuffer_t rb = {
        byteBuffer,
        sizeof(byteBuffer),
        0,
        0
    };


    log_logMessage(LOGLEVEL_INFO, "Testing ringbuffer");

    // Initialize the buffer.
    ringbuffer_init(&rb);

    // Write bytes to the buffer, then read them.
    for (length = 0;length <= sizeof(byteBuffer) + 1;length ++) {
        ringbuffer_status_t rs;
        unsigned rl, wl;


        // Write 0..length bytes to the ringbuffer.
        for (wl = 0;wl < length;wl ++) {
            rs = ringbuffer_put(&rb, (length + wl) & 0xff);
            if (wl < sizeof(byteBuffer)) {
                expectTrue(ring_ok == rs);
                expectTrue(ringbuffer_length(&rb) == (wl + 1));
            } else {
                expectTrue(ring_full == rs);
                expectTrue(ringbuffer_length(&rb) == sizeof(byteBuffer));
            }
        } // for wl

        if (wl > sizeof(byteBuffer)) {
            wl = sizeof(byteBuffer);
        }

        // Read 1..length+1 bytes from the ringbuffer.
        for (rl = 0;rl <= length;rl ++) {
            int c = ringbuffer_get(&rb);

            if (rl < wl) {
                expectTrue(c >= 0);
                expectTrue(((length + rl) & 0xff) == c);
                expectTrue(ringbuffer_length(&rb) == (wl - rl - 1));
            } else {
                expectTrue(c < 0);
                expectTrue(ringbuffer_length(&rb) == 0);
            }

            c = ringbuffer_peek(&rb);
            if (rl + 1 < wl) {
                expectTrue(c >= 0);
                expectTrue(((length + rl + 1) & 0xff) == c);
            } else {
                expectTrue(c < 0);
            }
        } // for rl
    } // for length

    return true;
} // unittest_ringbuffer()
Example #17
0
/*
 * Drop all packets with sequence number less than specified.
 *
 * The packets are considered as stale and the caller will receive
 * appropriate error code in the operation callback.
 *
 * Returns 0 on success
 */
int lcb_server_purge_implicit_responses(lcb_server_t *c,
                                        lcb_uint32_t seqno,
                                        hrtime_t end,
                                        int all)
{
    protocol_binary_request_header req;

    /** Instance level allocated buffers */
    ringbuffer_t *cmdlog, *cookies;

    lcb_size_t nr = ringbuffer_peek(&c->cmd_log, req.bytes, sizeof(req));

    /* There should at _LEAST_ be _ONE_ message in here if we're not
     * trying to purge _ALL_ of the messages in the queue
     */
    if (all && nr == 0) {
        return 0;
    }


    /**
     * Reading the command log is not re-entrant safe, as an additional
     * command to the same server may result in the command log being modified.
     * To this end, we must first buffer all the commands in a separate
     * ringbuffer (or simple buffer) for that matter, and only *then*
     * invoke the callbacks
     */
    lcb_assert(nr == sizeof(req));

    if (req.request.opaque >= seqno) {
        return 0;
    }

    cmdlog = &c->instance->purged_buf;
    cookies = &c->instance->purged_cookies;
    ringbuffer_reset(cmdlog);
    ringbuffer_reset(cookies);

    /**
     * Move all the commands we want to purge into the relevant ("local") buffers.
     * We will later read from these local buffers
     */
    while (req.request.opaque < seqno) {
        lcb_size_t packetsize = ntohl(req.request.bodylen) + (lcb_uint32_t)sizeof(req);

        ringbuffer_memcpy(cmdlog, &c->cmd_log, packetsize);
        ringbuffer_consumed(&c->cmd_log, packetsize);


        ringbuffer_memcpy(cookies, &c->output_cookies, sizeof(struct lcb_command_data_st));
        ringbuffer_consumed(&c->output_cookies, sizeof(struct lcb_command_data_st));

        nr = ringbuffer_peek(&c->cmd_log, req.bytes, sizeof(req.bytes));

        if (!nr) {
            break;
        }

        lcb_assert(nr == sizeof(req));
    }

    nr = ringbuffer_peek(cmdlog, req.bytes, sizeof(req));
    lcb_assert(nr == sizeof(req));

    if (!all) {
        lcb_assert(c->cmd_log.nbytes);
    }

    do {
        struct lcb_command_data_st ct;
        char *packet = cmdlog->read_head;
        lcb_size_t packetsize = ntohl(req.request.bodylen) + (lcb_uint32_t)sizeof(req);
        char *keyptr;

        union {
            lcb_get_resp_t get;
            lcb_store_resp_t store;
            lcb_remove_resp_t remove;
            lcb_touch_resp_t touch;
            lcb_unlock_resp_t unlock;
            lcb_arithmetic_resp_t arithmetic;
            lcb_observe_resp_t observe;
        } resp;

        nr = ringbuffer_read(cookies, &ct, sizeof(ct));
        lcb_assert(nr == sizeof(ct));

        if (c->instance->histogram) {
            lcb_record_metrics(c->instance, end - ct.start, req.request.opcode);
        }

        if (!ringbuffer_is_continous(cmdlog, RINGBUFFER_READ, packetsize)) {
            packet = malloc(packetsize);
            if (packet == NULL) {
                lcb_error_handler(c->instance, LCB_CLIENT_ENOMEM, NULL);
                return -1;
            }

            nr = ringbuffer_peek(cmdlog, packet, packetsize);
            if (nr != packetsize) {
                lcb_error_handler(c->instance, LCB_EINTERNAL, NULL);
                free(packet);
                return -1;
            }
        }

        switch (req.request.opcode) {
        case PROTOCOL_BINARY_CMD_GATQ:
        case PROTOCOL_BINARY_CMD_GETQ:
            keyptr = packet + sizeof(req) + req.request.extlen;
            setup_lcb_get_resp_t(&resp.get, keyptr, ntohs(req.request.keylen),
                                 NULL, 0, 0, 0, 0);
            TRACE_GET_END(req.request.opaque, ntohs(req.request.vbucket),
                          req.request.opcode, LCB_KEY_ENOENT, &resp.get);
            c->instance->callbacks.get(c->instance, ct.cookie, LCB_KEY_ENOENT, &resp.get);
            break;
        case CMD_OBSERVE:
            lcb_failout_observe_request(c, &ct, packet,
                                        sizeof(req.bytes) + ntohl(req.request.bodylen),
                                        LCB_SERVER_BUG);
            break;
        case PROTOCOL_BINARY_CMD_NOOP:
            break;
        default: {
            char errinfo[128] = { '\0' };
            snprintf(errinfo, 128, "Unknown implicit send message op=%0x", req.request.opcode);
            lcb_error_handler(c->instance, LCB_EINTERNAL, errinfo);
            return -1;
        }
        }

        if (packet != cmdlog->read_head) {
            free(packet);
        }

        ringbuffer_consumed(cmdlog, packetsize);
        nr = ringbuffer_peek(cmdlog, req.bytes, sizeof(req));

        if (nr == 0) {
            return 0;
        }

        lcb_assert(nr == sizeof(req));
    } while (1); /* CONSTCOND */

    return 0;
}
Example #18
0
static void purge_single_server(lcb_server_t *server, lcb_error_t error,
                                hrtime_t min_nonstale,
                                hrtime_t *tmo_next)
{
    protocol_binary_request_header req;
    struct lcb_command_data_st ct;
    lcb_size_t nr;
    char *packet;
    lcb_size_t packetsize;
    char *keyptr;
    ringbuffer_t rest;
    ringbuffer_t *stream = &server->cmd_log;
    ringbuffer_t *cookies;
    ringbuffer_t *mirror = NULL; /* mirror buffer should be purged with main stream */
    lcb_connection_t conn = &server->connection;
    lcb_size_t send_size = 0;
    lcb_size_t stream_size = ringbuffer_get_nbytes(stream);
    hrtime_t now = gethrtime();

    if (server->connection_ready) {
        cookies = &server->output_cookies;
    } else {
        cookies = &server->pending_cookies;
        mirror = &server->pending;
    }

    if (conn->output) {
        /* This will usually be false for v1 */
        send_size = ringbuffer_get_nbytes(conn->output);
    }

    lcb_assert(ringbuffer_initialize(&rest, 1024));


    do {
        int allocated = 0;
        lcb_uint32_t headersize;
        lcb_uint16_t nkey;

        nr = ringbuffer_peek(cookies, &ct, sizeof(ct));
        if (nr != sizeof(ct)) {
            break;
        }
        nr = ringbuffer_peek(stream, req.bytes, sizeof(req));
        if (nr != sizeof(req)) {
            break;
        }
        packetsize = (lcb_uint32_t)sizeof(req) + ntohl(req.request.bodylen);
        if (stream->nbytes < packetsize) {
            break;
        }
        if (min_nonstale && ct.start >= min_nonstale) {
            lcb_log(LOGARGS(server, INFO),
                    "Still have %d ms remaining for command",
                    (ct.start - min_nonstale) / 1000000);

            if (tmo_next) {
                *tmo_next = (ct.start - min_nonstale) + 1;
            }
            break;
        }

        lcb_log(LOGARGS(server, INFO),
                "Command with cookie=%p timed out from server %s:%s",
                ct.cookie,
                server->curhost.host,
                server->curhost.port);

        ringbuffer_consumed(cookies, sizeof(ct));

        lcb_assert(nr == sizeof(req));
        packet = stream->read_head;

        if (server->instance->histogram) {
            lcb_record_metrics(server->instance, now - ct.start,
                               req.request.opcode);
        }

        if (server->connection_ready &&
                stream_size > send_size && (stream_size - packetsize) < send_size) {
            /* Copy the rest of the current packet into the
               temporary stream */

            /* I do believe I have some IOV functions to do that? */
            lcb_size_t nbytes = packetsize - (stream_size - send_size);
            lcb_assert(ringbuffer_memcpy(&rest,
                                         conn->output,
                                         nbytes) == 0);
            ringbuffer_consumed(conn->output, nbytes);
            send_size -= nbytes;
        }
        stream_size -= packetsize;
        headersize = (lcb_uint32_t)sizeof(req) + req.request.extlen + htons(req.request.keylen);
        if (!ringbuffer_is_continous(stream, RINGBUFFER_READ, headersize)) {
            packet = malloc(headersize);
            if (packet == NULL) {
                lcb_error_handler(server->instance, LCB_CLIENT_ENOMEM, NULL);
                abort();
            }

            nr = ringbuffer_peek(stream, packet, headersize);
            if (nr != headersize) {
                lcb_error_handler(server->instance, LCB_EINTERNAL, NULL);
                free(packet);
                abort();
            }
            allocated = 1;
        }

        keyptr = packet + sizeof(req) + req.request.extlen;
        nkey = ntohs(req.request.keylen);

        failout_single_request(server, &req, &ct, error, keyptr, nkey, packet);

        if (allocated) {
            free(packet);
        }
        ringbuffer_consumed(stream, packetsize);
        if (mirror) {
            ringbuffer_consumed(mirror, packetsize);
        }
    } while (1); /* CONSTCOND */

    if (server->connection_ready && conn->output) {
        /* Preserve the rest of the stream */
        lcb_size_t nbytes = ringbuffer_get_nbytes(stream);
        send_size = ringbuffer_get_nbytes(conn->output);

        if (send_size >= nbytes) {
            ringbuffer_consumed(conn->output, send_size - nbytes);
            lcb_assert(ringbuffer_memcpy(&rest, conn->output, nbytes) == 0);
        }
        ringbuffer_reset(conn->output);
        ringbuffer_append(&rest, conn->output);
    }

    ringbuffer_destruct(&rest);
    lcb_maybe_breakout(server->instance);
}