void cb_http_complete_callback(lcb_http_request_t request, lcb_t handle, const void *cookie, lcb_error_t error, const lcb_http_resp_t *resp) { struct cb_context_st *ctx = (struct cb_context_st *)cookie; struct cb_bucket_st *bucket = ctx->bucket; VALUE key, val, res, exc; lcb_http_status_t status; ctx->request->completed = 1; if (bucket->destroying) { cb_context_free(ctx); return; } key = STR_NEW((const char*)resp->v.v0.path, resp->v.v0.npath); val = resp->v.v0.nbytes ? STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes) : Qnil; exc = ctx->exception; if (!RTEST(exc)) { exc = cb_check_error_with_status(error, "failed to execute HTTP request", key, resp->v.v0.status); if (exc != Qnil && val != Qnil) { rb_ivar_set(exc, cb_id_iv_body, val); } } if (RTEST(exc)) { if (rb_obj_is_kind_of(exc, cb_eHTTPError)) { rb_funcall(exc, cb_id_parse_body_bang, 0); } ctx->exception = exc; } status = resp->v.v0.status; if (resp->v.v0.headers) { cb_build_headers(ctx, resp->v.v0.headers); ctx->headers_val = Qnil; } if (ctx->extended) { res = rb_class_new_instance(0, NULL, cb_cResult); rb_ivar_set(res, cb_id_iv_error, ctx->exception); rb_ivar_set(res, cb_id_iv_status, status ? INT2FIX(status) : Qnil); rb_ivar_set(res, cb_id_iv_operation, cb_sym_http_request); rb_ivar_set(res, cb_id_iv_key, key); rb_ivar_set(res, cb_id_iv_value, val); rb_ivar_set(res, cb_id_iv_completed, Qtrue); rb_ivar_set(res, cb_id_iv_headers, ctx->headers_val); } else { res = val; } if (ctx->proc != Qnil) { cb_proc_call(bucket, ctx->proc, 1, res); ctx->proc = Qnil; } if (!bucket->async && ctx->exception == Qnil) { ctx->rv = res; } if (bucket->async) { cb_context_free(ctx); } (void)handle; (void)request; }
void http_data_callback(lcb_http_request_t request, lcb_t handle, const void *cookie, lcb_error_t error, const lcb_http_resp_t *resp) { struct context_st *ctx = (struct context_st *)cookie; struct bucket_st *bucket = ctx->bucket; VALUE key, val, res; key = STR_NEW((const char*)resp->v.v0.path, resp->v.v0.npath); ctx->exception = cb_check_error_with_status(error, "failed to execute HTTP request", key, resp->v.v0.status); val = resp->v.v0.nbytes ? STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes) : Qnil; if (ctx->exception != Qnil) { cb_gc_protect(bucket, ctx->exception); lcb_cancel_http_request(bucket->handle, request); } if (resp->v.v0.headers) { cb_build_headers(ctx, resp->v.v0.headers); } if (ctx->proc != Qnil) { if (ctx->extended) { res = rb_class_new_instance(0, NULL, cResult); rb_ivar_set(res, id_iv_error, ctx->exception); rb_ivar_set(res, id_iv_operation, sym_http_request); rb_ivar_set(res, id_iv_key, key); rb_ivar_set(res, id_iv_value, val); rb_ivar_set(res, id_iv_completed, Qfalse); rb_ivar_set(res, id_iv_headers, ctx->headers_val); } else { res = val; } cb_proc_call(ctx->proc, 1, res); } (void)handle; }
void observe_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_observe_resp_t *resp) { struct context_st *ctx = (struct context_st *)cookie; struct bucket_st *bucket = ctx->bucket; VALUE key, res, *rv = ctx->rv; if (resp->v.v0.key) { key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey); ctx->exception = cb_check_error(error, "failed to execute observe request", key); if (ctx->exception) { cb_gc_protect(bucket, ctx->exception); } res = rb_class_new_instance(0, NULL, cResult); rb_ivar_set(res, id_iv_completed, Qfalse); rb_ivar_set(res, id_iv_error, ctx->exception); rb_ivar_set(res, id_iv_operation, sym_observe); rb_ivar_set(res, id_iv_key, key); rb_ivar_set(res, id_iv_cas, ULL2NUM(resp->v.v0.cas)); rb_ivar_set(res, id_iv_from_master, resp->v.v0.from_master ? Qtrue : Qfalse); rb_ivar_set(res, id_iv_time_to_persist, ULONG2NUM(resp->v.v0.ttp)); rb_ivar_set(res, id_iv_time_to_replicate, ULONG2NUM(resp->v.v0.ttr)); switch (resp->v.v0.status) { case LCB_OBSERVE_FOUND: rb_ivar_set(res, id_iv_status, sym_found); break; case LCB_OBSERVE_PERSISTED: rb_ivar_set(res, id_iv_status, sym_persisted); break; case LCB_OBSERVE_NOT_FOUND: rb_ivar_set(res, id_iv_status, sym_not_found); break; default: rb_ivar_set(res, id_iv_status, Qnil); } if (bucket->async) { /* asynchronous */ if (ctx->proc != Qnil) { cb_proc_call(ctx->proc, 1, res); } } else { /* synchronous */ if (NIL_P(ctx->exception)) { VALUE stats = rb_hash_aref(*rv, key); if (NIL_P(stats)) { stats = rb_ary_new(); rb_hash_aset(*rv, key, stats); } rb_ary_push(stats, res); } } } else { if (bucket->async && ctx->proc != Qnil) { res = rb_class_new_instance(0, NULL, cResult); rb_ivar_set(res, id_iv_completed, Qtrue); cb_proc_call(ctx->proc, 1, res); } ctx->nqueries--; cb_gc_unprotect(bucket, ctx->proc); } (void)handle; }
void cb_http_data_callback(lcb_http_request_t request, lcb_t handle, const void *cookie, lcb_error_t error, const lcb_http_resp_t *resp) { struct cb_context_st *ctx = (struct cb_context_st *)cookie; struct cb_bucket_st *bucket = ctx->bucket; VALUE key, val, res; lcb_http_status_t status; key = STR_NEW((const char*)resp->v.v0.path, resp->v.v0.npath); val = resp->v.v0.nbytes ? STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes) : Qnil; status = resp->v.v0.status; if (NIL_P(ctx->exception)) { ctx->exception = cb_check_error_with_status(error, "failed to execute HTTP request", key, resp->v.v0.status); if (ctx->exception != Qnil) { VALUE body_str = rb_ivar_get(ctx->exception, cb_id_iv_body); if (NIL_P(body_str)) { rb_ivar_set(ctx->exception, cb_id_iv_body, val); } else { rb_str_concat(body_str, val); } return; } } if (resp->v.v0.headers) { cb_build_headers(ctx, resp->v.v0.headers); } if (ctx->proc != Qnil) { if (ctx->extended) { res = rb_class_new_instance(0, NULL, cb_cResult); rb_ivar_set(res, cb_id_iv_error, Qnil); rb_ivar_set(res, cb_id_iv_status, status ? INT2FIX(status) : Qnil); rb_ivar_set(res, cb_id_iv_operation, cb_sym_http_request); rb_ivar_set(res, cb_id_iv_key, key); rb_ivar_set(res, cb_id_iv_value, val); rb_ivar_set(res, cb_id_iv_completed, Qfalse); rb_ivar_set(res, cb_id_iv_headers, ctx->headers_val); } else { res = val; } cb_proc_call(bucket, ctx->proc, 1, res); } (void)handle; }
void arithmetic_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_arithmetic_resp_t *resp) { struct context_st *ctx = (struct context_st *)cookie; struct bucket_st *bucket = ctx->bucket; VALUE cas, key, val, *rv = ctx->rv, exc, res; ID o; ctx->nqueries--; key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey); strip_key_prefix(bucket, key); cas = resp->v.v0.cas > 0 ? ULL2NUM(resp->v.v0.cas) : Qnil; o = ctx->arith > 0 ? sym_increment : sym_decrement; exc = cb_check_error(error, "failed to perform arithmetic operation", key); if (exc != Qnil) { rb_ivar_set(exc, id_iv_cas, cas); rb_ivar_set(exc, id_iv_operation, o); if (bucket->async) { if (bucket->on_error_proc != Qnil) { cb_proc_call(bucket->on_error_proc, 3, o, key, exc); } else { if (NIL_P(bucket->exception)) { bucket->exception = exc; } } } if (NIL_P(ctx->exception)) { ctx->exception = cb_gc_protect(bucket, exc); } } val = ULL2NUM(resp->v.v0.value); if (bucket->async) { /* asynchronous */ if (ctx->proc != Qnil) { res = rb_class_new_instance(0, NULL, cResult); rb_ivar_set(res, id_iv_error, exc); rb_ivar_set(res, id_iv_operation, o); rb_ivar_set(res, id_iv_key, key); rb_ivar_set(res, id_iv_value, val); rb_ivar_set(res, id_iv_cas, cas); cb_proc_call(ctx->proc, 1, res); } } else { /* synchronous */ if (NIL_P(exc)) { if (ctx->extended) { rb_hash_aset(*rv, key, rb_ary_new3(2, val, cas)); } else { rb_hash_aset(*rv, key, val); } } } if (ctx->nqueries == 0) { cb_gc_unprotect(bucket, ctx->proc); } (void)handle; }
void cb_storage_callback(lcb_t handle, const void *cookie, lcb_storage_t operation, lcb_error_t error, const lcb_store_resp_t *resp) { struct cb_context_st *ctx = (struct cb_context_st *)cookie; struct cb_bucket_st *bucket = ctx->bucket; VALUE key, cas, exc, res; key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey); cb_strip_key_prefix(bucket, key); cas = resp->v.v0.cas > 0 ? ULL2NUM(resp->v.v0.cas) : Qnil; ctx->operation = storage_opcode_to_sym(operation); exc = cb_check_error(error, "failed to store value", key); if (exc != Qnil) { rb_ivar_set(exc, cb_id_iv_cas, cas); rb_ivar_set(exc, cb_id_iv_operation, ctx->operation); ctx->exception = exc; } if (bucket->async) { /* asynchronous */ if (RTEST(ctx->observe_options)) { VALUE args[2]; /* it's ok to pass pointer to stack struct here */ args[0] = rb_hash_new(); rb_hash_aset(args[0], key, cas); args[1] = ctx->observe_options; rb_block_call(bucket->self, cb_id_observe_and_wait, 2, args, storage_observe_callback, (VALUE)ctx); ctx->observe_options = Qnil; } else if (ctx->proc != Qnil) { res = rb_class_new_instance(0, NULL, cb_cResult); rb_ivar_set(res, cb_id_iv_error, exc); rb_ivar_set(res, cb_id_iv_key, key); rb_ivar_set(res, cb_id_iv_operation, ctx->operation); rb_ivar_set(res, cb_id_iv_cas, cas); cb_proc_call(bucket, ctx->proc, 1, res); } } else { /* synchronous */ rb_hash_aset(ctx->rv, key, cas); } if (!RTEST(ctx->observe_options)) { ctx->nqueries--; if (ctx->nqueries == 0) { ctx->proc = Qnil; if (bucket->async) { cb_context_free(ctx); } } } (void)handle; }
static VALUE elements_to_hash(const char* buffer, int max) { VALUE hash = rb_class_new_instance(0, NULL, OrderedHash); int position = 0; while (position < max) { int type = (int)buffer[position++]; int name_length = (int)strlen(buffer + position); VALUE name = STR_NEW(buffer + position, name_length); VALUE value; position += name_length + 1; value = get_value(buffer, &position, type); rb_funcall(hash, element_assignment_method, 2, name, value); } return hash; }
/* * Execute {Bucket::CouchRequest} * * @since 1.2.0 */ VALUE cb_http_request_perform(VALUE self) { struct http_request_st *req = DATA_PTR(self); struct context_st *ctx; VALUE rv, exc; lcb_error_t err; struct bucket_st *bucket; ctx = xcalloc(1, sizeof(struct context_st)); if (ctx == NULL) { rb_raise(eClientNoMemoryError, "failed to allocate memory"); } rv = Qnil; ctx->rv = &rv; ctx->bucket = bucket = req->bucket; ctx->proc = rb_block_given_p() ? rb_block_proc() : req->on_body_callback; ctx->extended = req->extended; ctx->request = req; ctx->headers_val = cb_gc_protect(bucket, rb_hash_new()); err = lcb_make_http_request(bucket->handle, (const void *)ctx, req->type, &req->cmd, &req->request); exc = cb_check_error(err, "failed to schedule document request", STR_NEW(req->cmd.v.v0.path, req->cmd.v.v0.npath)); if (exc != Qnil) { xfree(ctx); rb_exc_raise(exc); } req->running = 1; req->ctx = ctx; if (bucket->async) { return Qnil; } else { lcb_wait(bucket->handle); if (req->completed) { exc = ctx->exception; xfree(ctx); if (exc != Qnil) { cb_gc_unprotect(bucket, exc); rb_exc_raise(exc); } return rv; } else { return Qnil; } } return Qnil; }
/* * Execute {Bucket::CouchRequest} * * @since 1.2.0 */ VALUE cb_http_request_perform(VALUE self) { struct cb_http_request_st *req = DATA_PTR(self); struct cb_context_st *ctx; VALUE rv, exc; lcb_error_t err; struct cb_bucket_st *bucket = req->bucket; if (bucket->handle == NULL) { rb_raise(cb_eConnectError, "closed connection"); } ctx = cb_context_alloc(bucket); ctx->rv = Qnil; ctx->proc = rb_block_given_p() ? rb_block_proc() : req->on_body_callback; ctx->extended = req->extended; ctx->request = req; ctx->headers_val = rb_hash_new(); err = lcb_make_http_request(bucket->handle, (const void *)ctx, req->type, &req->cmd, &req->request); exc = cb_check_error(err, "failed to schedule document request", STR_NEW(req->cmd.v.v0.path, req->cmd.v.v0.npath)); if (exc != Qnil) { lcb_cancel_http_request(bucket->handle, req->request); rb_exc_raise(exc); } req->running = 1; req->ctx = ctx; if (bucket->async) { return Qnil; } else { lcb_wait(bucket->handle); if (req->completed) { rv = ctx->rv; exc = ctx->exception; cb_context_free(ctx); if (exc != Qnil) { rb_exc_raise(exc); } return rv; } else { return Qnil; } } return Qnil; }
void cb_version_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_server_version_resp_t *resp) { struct cb_context_st *ctx = (struct cb_context_st *)cookie; struct cb_bucket_st *bucket = ctx->bucket; VALUE node, val, exc, res; node = resp->v.v0.server_endpoint ? STR_NEW_CSTR(resp->v.v0.server_endpoint) : Qnil; exc = cb_check_error(error, "failed to get version", node); if (exc != Qnil) { rb_ivar_set(exc, cb_id_iv_operation, cb_sym_version); ctx->exception = exc; } if (node != Qnil) { val = STR_NEW((const char*)resp->v.v0.vstring, resp->v.v0.nvstring); if (bucket->async) { /* asynchronous */ if (ctx->proc != Qnil) { res = rb_class_new_instance(0, NULL, cb_cResult); rb_ivar_set(res, cb_id_iv_error, exc); rb_ivar_set(res, cb_id_iv_operation, cb_sym_version); rb_ivar_set(res, cb_id_iv_node, node); rb_ivar_set(res, cb_id_iv_value, val); cb_proc_call(bucket, ctx->proc, 1, res); } } else { /* synchronous */ if (NIL_P(exc)) { rb_hash_aset(ctx->rv, node, val); } } } else { ctx->nqueries--; ctx->proc = Qnil; if (bucket->async) { cb_context_free(ctx); } } (void)handle; }
static VALUE elements_to_hash(const char* buffer, int max, int symbolize_keys) { VALUE hash = rb_class_new_instance(0, NULL, OrderedHash); int position = 0; while (position < max) { int type = (int)buffer[position++]; int name_length = strlen(buffer + position); VALUE name; if (symbolize_keys) { char buf[name_length+1]; memcpy(buf, buffer + position, name_length); buf[name_length] = 0; name = ID2SYM(rb_intern(buf)); } else { name = STR_NEW(buffer + position, name_length); } VALUE value; position += name_length + 1; value = get_value(buffer, &position, type); rb_funcall(hash, rb_intern("[]="), 2, name, value); } return hash; }
void cb_unlock_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_unlock_resp_t *resp) { struct cb_context_st *ctx = (struct cb_context_st *)cookie; struct cb_bucket_st *bucket = ctx->bucket; VALUE key, exc = Qnil, res; ctx->nqueries--; key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey); cb_strip_key_prefix(bucket, key); if (error != LCB_KEY_ENOENT || !ctx->quiet) { exc = cb_check_error(error, "failed to unlock value", key); if (exc != Qnil) { rb_ivar_set(exc, cb_id_iv_operation, cb_sym_unlock); ctx->exception = exc; } } if (bucket->async) { /* asynchronous */ if (ctx->proc != Qnil) { res = rb_class_new_instance(0, NULL, cb_cResult); rb_ivar_set(res, cb_id_iv_error, exc); rb_ivar_set(res, cb_id_iv_operation, cb_sym_unlock); rb_ivar_set(res, cb_id_iv_key, key); cb_proc_call(bucket, ctx->proc, 1, res); } } else { /* synchronous */ rb_hash_aset(ctx->rv, key, (error == LCB_SUCCESS) ? Qtrue : Qfalse); } if (ctx->nqueries == 0) { ctx->proc = Qnil; if (bucket->async) { cb_context_free(ctx); } } (void)handle; }
static VALUE get_value(const char* buffer, int* position, int type) { VALUE value; switch (type) { case -1: { value = rb_class_new_instance(0, NULL, MinKey); break; } case 1: { double d; memcpy(&d, buffer + *position, 8); value = rb_float_new(d); *position += 8; break; } case 2: case 13: { int value_length; value_length = *(int*)(buffer + *position) - 1; *position += 4; value = STR_NEW(buffer + *position, value_length); *position += value_length + 1; break; } case 3: { int size; memcpy(&size, buffer + *position, 4); if (strcmp(buffer + *position + 5, "$ref") == 0) { // DBRef int offset = *position + 10; VALUE argv[2]; int collection_length = *(int*)(buffer + offset) - 1; char id_type; offset += 4; argv[0] = STR_NEW(buffer + offset, collection_length); offset += collection_length + 1; id_type = buffer[offset]; offset += 5; argv[1] = get_value(buffer, &offset, (int)id_type); value = rb_class_new_instance(2, argv, DBRef); } else { value = elements_to_hash(buffer + *position + 4, size - 5); } *position += size; break; } case 4: { int size, end; memcpy(&size, buffer + *position, 4); end = *position + size - 1; *position += 4; value = rb_ary_new(); while (*position < end) { int type = (int)buffer[(*position)++]; int key_size = (int)strlen(buffer + *position); VALUE to_append; *position += key_size + 1; // just skip the key, they're in order. to_append = get_value(buffer, position, type); rb_ary_push(value, to_append); } (*position)++; break; } case 5: { int length, subtype; VALUE data, st; VALUE argv[2]; memcpy(&length, buffer + *position, 4); subtype = (unsigned char)buffer[*position + 4]; if (subtype == 2) { data = rb_str_new(buffer + *position + 9, length - 4); } else { data = rb_str_new(buffer + *position + 5, length); } st = INT2FIX(subtype); argv[0] = data; argv[1] = st; value = rb_class_new_instance(2, argv, Binary); *position += length + 5; break; } case 6: { value = Qnil; break; } case 7: { VALUE str = rb_str_new(buffer + *position, 12); VALUE oid = rb_funcall(str, unpack_method, 1, rb_str_new2("C*")); value = rb_class_new_instance(1, &oid, ObjectId); *position += 12; break; } case 8: { value = buffer[(*position)++] ? Qtrue : Qfalse; break; } case 9: { long long millis; memcpy(&millis, buffer + *position, 8); value = rb_time_new(millis / 1000, (millis % 1000) * 1000); value = rb_funcall(value, utc_method, 0); *position += 8; break; } case 10: { value = Qnil; break; } case 11: { int pattern_length = (int)strlen(buffer + *position); VALUE pattern = STR_NEW(buffer + *position, pattern_length); int flags_length, flags = 0, i = 0; VALUE argv[3]; *position += pattern_length + 1; flags_length = (int)strlen(buffer + *position); for (i = 0; i < flags_length; i++) { char flag = buffer[*position + i]; if (flag == 'i') { flags |= IGNORECASE; } else if (flag == 'm') { flags |= MULTILINE; } else if (flag == 's') { flags |= MULTILINE; } else if (flag == 'x') { flags |= EXTENDED; } } argv[0] = pattern; argv[1] = INT2FIX(flags); value = rb_class_new_instance(2, argv, Regexp); *position += flags_length + 1; break; } case 12: { int collection_length; VALUE collection, str, oid, id, argv[2]; collection_length = *(int*)(buffer + *position) - 1; *position += 4; collection = STR_NEW(buffer + *position, collection_length); *position += collection_length + 1; str = rb_str_new(buffer + *position, 12); oid = rb_funcall(str, unpack_method, 1, rb_str_new2("C*")); id = rb_class_new_instance(1, &oid, ObjectId); *position += 12; argv[0] = collection; argv[1] = id; value = rb_class_new_instance(2, argv, DBRef); break; } case 14: { int value_length; memcpy(&value_length, buffer + *position, 4); value = ID2SYM(rb_intern(buffer + *position + 4)); *position += value_length + 4; break; } case 15: { int code_length, scope_size; VALUE code, scope, argv[2]; *position += 4; code_length = *(int*)(buffer + *position) - 1; *position += 4; code = STR_NEW(buffer + *position, code_length); *position += code_length + 1; memcpy(&scope_size, buffer + *position, 4); scope = elements_to_hash(buffer + *position + 4, scope_size - 5); *position += scope_size; argv[0] = code; argv[1] = scope; value = rb_class_new_instance(2, argv, Code); break; } case 16: { int i; memcpy(&i, buffer + *position, 4); value = LL2NUM(i); *position += 4; break; } case 17: { int sec, inc; VALUE argv[2]; memcpy(&inc, buffer + *position, 4); memcpy(&sec, buffer + *position + 4, 4); argv[0] = INT2FIX(sec); argv[1] = INT2FIX(inc); value = rb_class_new_instance(2, argv, Timestamp); *position += 8; break; } case 18: { long long ll; memcpy(&ll, buffer + *position, 8); value = LL2NUM(ll); *position += 8; break; } case 127: { value = rb_class_new_instance(0, NULL, MaxKey); break; } default: { rb_raise(rb_eTypeError, "no c decoder for this type yet (%d)", type); break; } } return value; }
void cb_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_get_resp_t *resp) { struct cb_context_st *ctx = (struct cb_context_st *)cookie; struct cb_bucket_st *bucket = ctx->bucket; VALUE key, val, flags, cas, exc = Qnil, res, raw; ctx->nqueries--; key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey); cb_strip_key_prefix(bucket, key); if (error != LCB_KEY_ENOENT || !ctx->quiet) { exc = cb_check_error(error, "failed to get value", key); if (exc != Qnil) { rb_ivar_set(exc, cb_id_iv_operation, cb_sym_get); ctx->exception = exc; } } flags = ULONG2NUM(resp->v.v0.flags); cas = ULL2NUM(resp->v.v0.cas); raw = STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes); val = cb_decode_value(ctx->transcoder, raw, resp->v.v0.flags, ctx->transcoder_opts); if (rb_obj_is_kind_of(val, rb_eStandardError)) { VALUE exc_str = rb_funcall(val, cb_id_to_s, 0); VALUE msg = rb_funcall(rb_mKernel, cb_id_sprintf, 3, rb_str_new2("unable to convert value for key \"%s\": %s"), key, exc_str); ctx->exception = rb_exc_new3(cb_eValueFormatError, msg); rb_ivar_set(ctx->exception, cb_id_iv_operation, cb_sym_get); rb_ivar_set(ctx->exception, cb_id_iv_key, key); rb_ivar_set(ctx->exception, cb_id_iv_inner_exception, val); val = Qnil; } if (bucket->async) { /* asynchronous */ if (ctx->proc != Qnil) { res = rb_class_new_instance(0, NULL, cb_cResult); rb_ivar_set(res, cb_id_iv_error, exc); rb_ivar_set(res, cb_id_iv_operation, cb_sym_get); rb_ivar_set(res, cb_id_iv_key, key); rb_ivar_set(res, cb_id_iv_value, val); rb_ivar_set(res, cb_id_iv_flags, flags); rb_ivar_set(res, cb_id_iv_cas, cas); cb_proc_call(bucket, ctx->proc, 1, res); } } else { /* synchronous */ if (NIL_P(exc) && error != LCB_KEY_ENOENT) { if (ctx->extended) { val = rb_ary_new3(3, val, flags, cas); } if (ctx->all_replicas) { VALUE ary = rb_hash_aref(ctx->rv, key); if (NIL_P(ary)) { ary = rb_ary_new(); rb_hash_aset(ctx->rv, key, ary); } rb_ary_push(ary, val); } else { rb_hash_aset(ctx->rv, key, val); } } } if (ctx->nqueries == 0) { ctx->proc = Qnil; if (bucket->async) { cb_context_free(ctx); } } (void)handle; }
void Main (Closure_clp self) { FB_st *st; IOEntryMod_clp emod; int i; TRC(printf("FB/MGA: entered\n")); st = (FB_st *)Heap$Malloc(Pvs(heap), sizeof(FB_st)); if (st == NULL) RAISE_Heap$NoMemory(); memset(st, 0, sizeof(FB_st)); CL_INIT(st->cl, &fb_ms, st); /* Before we do anything, see if we can find a framebuffer device that we understand. */ st->cardbase = (Pixel_t *) MGAInit(FB_WIDTH, FB_HEIGHT, FB_DEPTH, FB_MODE); TRC(printf("st->cardbase = %p\n", st->cardbase)); if(!st->cardbase) { fprintf(stderr, "Failed to initialise MGA device\n"); Heap$Free(Pvs(heap), st); return; } #ifdef TEST_CARD test_card16a( (uint16_t *) st->cardbase ); #else memset((uchar_t *) st->cardbase, 0, FB_WIDTH * FB_HEIGHT * (FB_DEPTH/8) ); #endif /* Init state */ st->qosleft = 100; st->cursched = 0; st->schedndx = 0; for (i = 0; i < FB_SCHEDLEN; i++) { st->sched[0][i] = st->sched[1][i] = 0; } /* Initialise window DS */ for (i = 0 ; i < FB_MAX_WINDOWS; i++) { FB_Window *w = &st->window[i]; w->wid = i; w->free = True; w->tagword = w->tag = w->wid; /* extend the tag to be a full word (32 or 64 bits) wide */ w->tagword |= (w->tagword<<8); w->tagword |= (w->tagword<<16); /* Generates harmless overflow warning on 32bit architectures */ w->tagword |= (w->tagword<<32); } /* Initialise stream DS */ for (i = 0 ; i < FB_MAX_STREAMS; i++) { FB_Stream *s = &st->stream[i]; s->sid = i; s->free = True; s->qos = 0; } TRC(printf("About to create an entry...\n")); /* Create an entry*/ emod = NAME_FIND ("modules>IOEntryMod", IOEntryMod_clp); st->fbentry = IOEntryMod$New (emod, Pvs(actf), Pvs(vp), VP$NumChannels (Pvs(vp))); TRC(printf("About to grab stretches for FB and CLIP\n")); /* Grab stretches for FB and CLIP */ { Stretch_clp str; Stretch_Size size; /* Get a stretch for clip RAM. Allocate a spare line of tiles at the start and end in case we need to blit over the edges */ str = STR_NEW(sizeof(tag_t)*FB_WIDTH*(FB_HEIGHT+16)); if (!str) { fprintf(stderr,"Couldn't get stretch"); } st->clipstr = str; st->clipbase = (tag_t *) STR_RANGE(str, &size); st->clip = st->clipbase + (FB_WIDTH * 8); if (!st->clip || size < (FB_WIDTH*(FB_HEIGHT+16))) { fprintf(stderr,"Stretch bogus\n"); } TRC(fprintf(stderr,"FB: Clip RAM at %p size %lx\n", st->clip, size)); } TRC(printf("About to init clip RAM\n")); /* Initialise the clip RAM */ InitClipRAM(&st->cl); TRC(printf("About to add dev>fblite to namespace\n")); CX_ADD("dev>fblite", st->cardbase, addr_t); TRC(printf("About to init blitting code\n")); /* Init the blitting code */ blit_init(st); /* Turn on cursor */ TRC(printf("About to turn on cursor\n")); MGALoadCursor(st->cardbase, CURSOR_IDX, CURSOR_BITS); MGAMoveCursor(st->cardbase, CURSOR_IDX, CURSOR_INITX, CURSOR_INITY); /* Export management interface */ TRC(printf("About to export management interface\n")); IDC_EXPORT ("dev>FB", FB_clp, &st->cl); /* Go into a loop to service all the clients */ /* Launch WSSvr */ TRC(printf("Trying to launch wssvr\n")); TRY { Closure_clp wssvr; wssvr = NAME_FIND("modules>WSSvr", Closure_clp); Threads$Fork(Pvs(thds), wssvr->op->Apply, wssvr->st, 0); st->wssvr_shares_domain = True; } CATCH_ALL { printf("Couldn't launch WSSvr - exception %s\n", exn_ctx.cur_exception); } ENDTRY; TRC(printf("FB/MGA: Init Done. (%ix%i %ibpp mode %i)\n", FB_WIDTH,FB_HEIGHT,FB_DEPTH,FB_MODE)); blit_loop(st); }
void boot(Rd_clp rd, bool_t verbose, string_t cmdline) { #ifdef INTEL uint32_t NOCLOBBER length; uint32_t start, slen; uint8_t * NOCLOBBER buff; Stretch_clp stretch; length=Rd$Length(rd); /* Read the header of the file to try to work out what it is */ buff=Heap$Malloc(Pvs(heap), 512); Rd$GetChars(rd, buff, 512); if (buff[510]==0x55 && buff[511]==0xaa) { if (verbose) printf( "Traditional bootable Nemesis image with %d setup blocks.\n", buff[497]); start=512*(buff[497]+1); } else if (buff[0]==0xfa && buff[1]==0xfc ) { if (verbose) printf("Hmm... looks like a bare Nemesis image.\n"); start=0; } else { printf("This does not look like a Nemesis image.\n"); return; } Heap$Free(Pvs(heap), buff); length-=start; /* Get a stretch of the appropriate size */ stretch = STR_NEW(length); buff = STR_RANGE(stretch, &slen); /* Read the image */ Rd$Seek(rd, start); #define PKTSIZE 8192 { char *bufptr = buff; int n; int togo = length; while (togo) { n = Rd$GetChars(rd, bufptr, PKTSIZE); togo -= n; bufptr += n; printf("."); fflush(stdout); } } printf("\n"); /* now shut down any Ethernet cards, so we don't get anything DMAed * over the image while it boots */ /* XXX AND This is a privileged operation. And we shouldn't really * dive at the Netif interface directly. */ /* XXX SDE we might be in a UDPnash at the moment, so there should be * NO OUTPUT after this point */ verbose=False; { Type_Any any; Netif_clp netif; const char * const downlist[] = {"de4x5-0", "de4x5-1", /* don't need 3c509, since no DMA */ "eth0", NULL}; /* HACK: need to lose the "const", since Context$Get() doesn't * have it. */ char ** NOCLOBBER eth = (char**)downlist; char buf[32]; while(*eth) { sprintf(buf, "dev>%s>control", *eth); if (Context$Get(Pvs(root), buf, &any)) { if (verbose) { printf("Shutting down %s... ", *eth); fflush(stdout); } TRY { netif = IDC_OPEN(buf, Netif_clp); } CATCH_ALL { if (verbose) printf("failed: caught exception\n"); netif = NULL; } ENDTRY; if (netif && !Netif$Down(netif) && verbose) { printf("failed: Netif$Down() error\n"); netif = NULL; } if (netif && verbose) printf("ok\n"); } eth++; } } if (verbose) { printf("Starting image...\n"); PAUSE(MILLISECS(1000)); } /* Chain to the new image */ ENTER_KERNEL_CRITICAL_SECTION(); ntsc_chain(buff, length, cmdline); LEAVE_KERNEL_CRITICAL_SECTION(); printf("Bogosity: the new image was not started\n"); printf("bogosity: (n) (slang); the degree of unusallness and brokenness of some item or event\n"); #else printf("Boot chaining not supported\n"); #endif }
static VALUE get_value(const char* buffer, int* position, unsigned char type, struct deserialize_opts * opts) { VALUE value; switch (type) { case 255: { value = rb_class_new_instance(0, NULL, MinKey); break; } case 1: { double d; memcpy(&d, buffer + *position, 8); value = rb_float_new(d); *position += 8; break; } case 2: case 13: { int value_length; value_length = *(int*)(buffer + *position) - 1; *position += 4; value = STR_NEW(buffer + *position, value_length); *position += value_length + 1; break; } case 3: { int size; memcpy(&size, buffer + *position, 4); if (strcmp(buffer + *position + 5, "$ref") == 0) { // DBRef VALUE argv[2]; unsigned char id_type; int offset = *position + 10; int collection_length = *(int*)(buffer + offset) - 1; offset += 4; argv[0] = STR_NEW(buffer + offset, collection_length); offset += collection_length + 1; id_type = (unsigned char)buffer[offset]; offset += 5; argv[1] = get_value(buffer, &offset, id_type, opts); value = rb_class_new_instance(2, argv, DBRef); } else { value = elements_to_hash(buffer + *position + 4, size - 5, opts); } *position += size; break; } case 4: { int size, end; memcpy(&size, buffer + *position, 4); end = *position + size - 1; *position += 4; value = rb_ary_new(); while (*position < end) { VALUE to_append; unsigned char type = (unsigned char)buffer[(*position)++]; int key_size = (int)strlen(buffer + *position); *position += key_size + 1; // just skip the key, they're in order. to_append = get_value(buffer, position, type, opts); rb_ary_push(value, to_append); } (*position)++; break; } case 5: { int length, subtype; VALUE data, st; VALUE argv[2]; memcpy(&length, buffer + *position, 4); subtype = (unsigned char)buffer[*position + 4]; if (subtype == 2) { data = rb_str_new(buffer + *position + 9, length - 4); } else { data = rb_str_new(buffer + *position + 5, length); } st = INT2FIX(subtype); argv[0] = data; argv[1] = st; value = rb_class_new_instance(2, argv, Binary); *position += length + 5; break; } case 6: { value = Qnil; break; } case 7: { VALUE str = rb_str_new(buffer + *position, 12); VALUE oid = rb_funcall(str, unpack_method, 1, rb_str_new2("C*")); value = rb_class_new_instance(1, &oid, ObjectId); *position += 12; break; } case 8: { value = buffer[(*position)++] ? Qtrue : Qfalse; break; } case 9: { int64_t millis; memcpy(&millis, buffer + *position, 8); // Support 64-bit time values in 32 bit environments in Ruby > 1.9 // Note: rb_time_num_new is not available pre Ruby 1.9 #if RUBY_API_VERSION_CODE >= 10900 #define add(x,y) (rb_funcall((x), '+', 1, (y))) #define mul(x,y) (rb_funcall((x), '*', 1, (y))) #define quo(x,y) (rb_funcall((x), rb_intern("quo"), 1, (y))) VALUE d, timev; d = LL2NUM(1000LL); timev = add(LL2NUM(millis / 1000), quo(LL2NUM(millis % 1000), d)); value = rb_time_num_new(timev, Qnil); #else value = rb_time_new(millis / 1000, (millis % 1000) * 1000); #endif value = rb_funcall(value, utc_method, 0); *position += 8; break; } case 10: { value = Qnil; break; } case 11: { int pattern_length = (int)strlen(buffer + *position); VALUE pattern = STR_NEW(buffer + *position, pattern_length); int flags_length; VALUE argv[3], flags_str; *position += pattern_length + 1; flags_length = (int)strlen(buffer + *position); flags_str = STR_NEW(buffer + *position, flags_length); argv[0] = pattern; argv[1] = flags_str; value = rb_class_new_instance(2, argv, BSONRegex); if (opts->compile_regex == 1) { value = rb_funcall(value, rb_intern("try_compile"), 0); } *position += flags_length + 1; break; } case 12: { int collection_length; VALUE collection, str, oid, id, argv[2]; collection_length = *(int*)(buffer + *position) - 1; *position += 4; collection = STR_NEW(buffer + *position, collection_length); *position += collection_length + 1; str = rb_str_new(buffer + *position, 12); oid = rb_funcall(str, unpack_method, 1, rb_str_new2("C*")); id = rb_class_new_instance(1, &oid, ObjectId); *position += 12; argv[0] = collection; argv[1] = id; value = rb_class_new_instance(2, argv, DBRef); break; } case 14: { int value_length; memcpy(&value_length, buffer + *position, 4); value = ID2SYM(rb_intern(buffer + *position + 4)); *position += value_length + 4; break; } case 15: { int code_length, scope_size; VALUE code, scope, argv[2]; *position += 4; code_length = *(int*)(buffer + *position) - 1; *position += 4; code = STR_NEW(buffer + *position, code_length); *position += code_length + 1; memcpy(&scope_size, buffer + *position, 4); scope = elements_to_hash(buffer + *position + 4, scope_size - 5, opts); *position += scope_size; argv[0] = code; argv[1] = scope; value = rb_class_new_instance(2, argv, Code); break; } case 16: { int i; memcpy(&i, buffer + *position, 4); value = LL2NUM(i); *position += 4; break; } case 17: { unsigned int sec, inc; VALUE argv[2]; memcpy(&inc, buffer + *position, 4); memcpy(&sec, buffer + *position + 4, 4); argv[0] = UINT2NUM(sec); argv[1] = UINT2NUM(inc); value = rb_class_new_instance(2, argv, Timestamp); *position += 8; break; } case 18: { long long ll; memcpy(&ll, buffer + *position, 8); value = LL2NUM(ll); *position += 8; break; } case 127: { value = rb_class_new_instance(0, NULL, MaxKey); break; } default: { rb_raise(rb_eTypeError, "no c decoder for this type yet (%d)", type); break; } } return value; }