/** finalize the context, if not already finalized */ static int ub_ctx_finalize(struct ub_ctx* ctx) { int res = 0; lock_basic_lock(&ctx->cfglock); if (!ctx->finalized) { res = context_finalize(ctx); } lock_basic_unlock(&ctx->cfglock); return res; }
void writer_run(const reader_t* reader) { context_t context; context_initialize(&context); calc_work(&context, reader); allocate_work(&context); read(&context, &reader); context_finalize(&context); }
int ub_resolve(struct ub_ctx* ctx, char* name, int rrtype, int rrclass, struct ub_result** result) { struct ctx_query* q; int r; *result = NULL; lock_basic_lock(&ctx->cfglock); if(!ctx->finalized) { r = context_finalize(ctx); if(r) { lock_basic_unlock(&ctx->cfglock); return r; } } /* create new ctx_query and attempt to add to the list */ lock_basic_unlock(&ctx->cfglock); q = context_new(ctx, name, rrtype, rrclass, NULL, NULL); if(!q) return UB_NOMEM; /* become a resolver thread for a bit */ r = libworker_fg(ctx, q); if(r) { lock_basic_lock(&ctx->cfglock); (void)rbtree_delete(&ctx->queries, q->node.key); context_query_delete(q); lock_basic_unlock(&ctx->cfglock); return r; } q->res->answer_packet = q->msg; q->res->answer_len = (int)q->msg_len; q->msg = NULL; *result = q->res; q->res = NULL; lock_basic_lock(&ctx->cfglock); (void)rbtree_delete(&ctx->queries, q->node.key); context_query_delete(q); lock_basic_unlock(&ctx->cfglock); return UB_NOERROR; }
int ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype, int rrclass, void* mydata, ub_event_callback_type callback, int* async_id) { struct ctx_query* q; int r; if(async_id) *async_id = 0; lock_basic_lock(&ctx->cfglock); if(!ctx->finalized) { r = context_finalize(ctx); if(r) { lock_basic_unlock(&ctx->cfglock); return r; } } lock_basic_unlock(&ctx->cfglock); if(!ctx->event_worker) { ctx->event_worker = libworker_create_event(ctx, ctx->event_base); if(!ctx->event_worker) { return UB_INITFAIL; } } /* set time in case answer comes from cache */ ub_comm_base_now(ctx->event_worker->base); /* create new ctx_query and attempt to add to the list */ q = context_new(ctx, name, rrtype, rrclass, NULL, callback, mydata); if(!q) return UB_NOMEM; /* attach to mesh */ if((r=libworker_attach_mesh(ctx, q, async_id)) != 0) return r; return UB_NOERROR; }
int ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype, int rrclass, void* mydata, ub_callback_t callback, int* async_id) { struct ctx_query* q; uint8_t* msg = NULL; uint32_t len = 0; if(async_id) *async_id = 0; lock_basic_lock(&ctx->cfglock); if(!ctx->finalized) { int r = context_finalize(ctx); if(r) { lock_basic_unlock(&ctx->cfglock); return r; } } if(!ctx->created_bg) { int r; ctx->created_bg = 1; lock_basic_unlock(&ctx->cfglock); r = libworker_bg(ctx); if(r) { lock_basic_lock(&ctx->cfglock); ctx->created_bg = 0; lock_basic_unlock(&ctx->cfglock); return r; } } else { lock_basic_unlock(&ctx->cfglock); } /* create new ctx_query and attempt to add to the list */ q = context_new(ctx, name, rrtype, rrclass, callback, mydata); if(!q) return UB_NOMEM; /* write over pipe to background worker */ lock_basic_lock(&ctx->cfglock); msg = context_serialize_new_query(q, &len); if(!msg) { (void)rbtree_delete(&ctx->queries, q->node.key); ctx->num_async--; context_query_delete(q); lock_basic_unlock(&ctx->cfglock); return UB_NOMEM; } if(async_id) *async_id = q->querynum; lock_basic_unlock(&ctx->cfglock); lock_basic_lock(&ctx->qqpipe_lock); if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) { lock_basic_unlock(&ctx->qqpipe_lock); free(msg); return UB_PIPE; } lock_basic_unlock(&ctx->qqpipe_lock); free(msg); return UB_NOERROR; }