//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ static void send_events(ErlDrvPort port, ErlDrvTermData pid, uint32_t events) { if ((ZMQ_POLLIN|ZMQ_POLLOUT) == events) { ErlDrvTermData spec[] = { ERL_DRV_ATOM, am_zmq_drv, ERL_DRV_ATOM, am_poll, ERL_DRV_ATOM, am_pollin, ERL_DRV_ATOM, am_pollout, ERL_DRV_NIL, ERL_DRV_LIST, 3, ERL_DRV_TUPLE, 3 }; driver_send_term(port, pid, spec, sizeof(spec)/sizeof(spec[0])); } else { ErlDrvTermData spec[] = { ERL_DRV_ATOM, am_zmq_drv, ERL_DRV_ATOM, am_poll, ERL_DRV_ATOM, am_pollerr, ERL_DRV_NIL, ERL_DRV_LIST, 2, ERL_DRV_TUPLE, 3 }; switch (events) { case ZMQ_POLLIN: spec[5] = am_pollin; break; case ZMQ_POLLOUT: spec[5] = am_pollout; break; } driver_send_term(port, pid, spec, sizeof(spec)/sizeof(spec[0])); } }
void reformat(ErlDrvPort port, char* buf, int len) { yajl_handle hand; /* generator config */ yajl_gen_config conf = { 1, " " }; yajl_gen g; yajl_status stat; /* allow comments */ yajl_parser_config cfg = { 1, 1 }; g = yajl_gen_alloc(&conf, NULL); /* ok. open file. let's read and parse */ hand = yajl_alloc(&callbacks, &cfg, NULL, (void *) g); /* read file data, pass to parser */ stat = yajl_parse(hand, (unsigned char*) buf, len); if (stat != yajl_status_ok && stat != yajl_status_insufficient_data) { char* err = (char*) yajl_get_error(hand, 1, (unsigned char*) buf, len); int len = strlen(err); ErlDrvTermData msg[] = { ERL_DRV_ATOM, driver_mk_atom("error"), ERL_DRV_BUF2BINARY, (ErlDrvTermData) err, (ErlDrvUInt) len, ERL_DRV_TUPLE, 2 }; driver_send_term(port, driver_caller(port), msg, sizeof(msg) / sizeof(msg[0])); } else { const unsigned char* json; unsigned int len; yajl_gen_get_buf(g, &json, &len); ErlDrvTermData msg[] = { ERL_DRV_ATOM, driver_mk_atom("ok"), ERL_DRV_BUF2BINARY, (ErlDrvTermData) json, (ErlDrvUInt) len, ERL_DRV_TUPLE, 2 }; driver_send_term(port, driver_caller(port), msg, sizeof(msg) / sizeof(msg[0])); yajl_gen_clear(g); } yajl_gen_free(g); yajl_free(hand); }
int wxeReturn::send() { if ((rt.GetCount() == 2 && isResult) || rt.GetCount() == 0) return 1; // not a call bail out if (isResult) { addTupleCount(2); } // rt to array unsigned int rtLength = rt.GetCount(); //signed int size_t size = sizeof(ErlDrvTermData)*(rtLength); ErlDrvTermData* rtData = (ErlDrvTermData *) driver_alloc(size); for (unsigned int i=0; i < rtLength; i++) { rtData[i] = rt[i]; } int res = driver_send_term(port, caller, rtData, rtLength); driver_free(rtData); if(res == -1) { wxString msg; msg.Printf(wxT("Failed to send return or event msg")); send_msg("internal_error", &msg); } reset(); return res; }
void es_peepEvents2(ErlDrvPort port, ErlDrvTermData caller, char *bp) { SDL_Event events[256]; int numevents, res, i, sz; Uint32 mask; char *start; ErlDrvBinary * bin; ErlDrvTermData rt[8]; mask = * (Uint32 *) bp; bp += sizeof(Uint32); numevents = *bp++; SDL_PumpEvents(); res = SDL_PeepEvents(events, numevents, SDL_GETEVENT, mask); bin = driver_alloc_binary(res*MAX_EVENT_SIZE); bp = start = bin->orig_bytes; for (i = 0; i < res; i++) { bp = encode_event(&(events[i]), bp); } sz = bp-start; rt[0] = ERL_DRV_ATOM; rt[1]=driver_mk_atom((char *) "_esdl_result_"); rt[2] = ERL_DRV_BINARY; rt[3] = (ErlDrvTermData) bin; rt[4] = sz; rt[5] = 0; rt[6] = ERL_DRV_TUPLE; rt[7] = 2; driver_send_term(port,caller,rt,8); driver_free_binary(bin); }
void gl_dispatch(int op, char *bp,ErlDrvTermData caller,WXEBinRef *bins[]){ if(caller != gl_active) { wxGLCanvas * current = glc[caller]; if(current) { gl_active = caller; current->SetCurrent();} else { ErlDrvTermData rt[] = // Error msg {ERL_DRV_ATOM, driver_mk_atom((char *) "_egl_error_"), ERL_DRV_INT, op, ERL_DRV_ATOM, driver_mk_atom((char *) "no_gl_context"), ERL_DRV_TUPLE,3}; driver_send_term(WXE_DRV_PORT,caller,rt,8); return ; } }; char * bs[3]; int bs_sz[3]; for(int i=0; i<3; i++) { if(bins[i]) { bs[i] = bins[i]->base; bs_sz[i] = bins[i]->size; } else bs[i] = NULL; } wxe_gl_dispatch(op, bp, WXE_DRV_PORT, caller, bs, bs_sz); }
static void handle_monitor(ErlDrvData drv_data, ErlDrvMonitor *monitor) { MyDrvData *data = (MyDrvData *) drv_data; OneMonitor *p,*o; for (p = data->first, o = NULL; p != NULL && driver_compare_monitors(&p->mon,monitor); o = p, p = p->next) ; if (!p) { fprintf(stderr,"Spooky Monitor executed!\r\n"); } else { ErlDrvTermData spec[] = { ERL_DRV_ATOM, driver_mk_atom("monitor_fired"), ERL_DRV_PORT, driver_mk_port(data->port), ERL_DRV_PID, p->pid, ERL_DRV_TUPLE, TERM_DATA(3) }; if (!o) { data->first = p->next; } else { o->next = p->next; } driver_free(p); driver_send_term(data->port, data->ipid, spec, sizeof(spec)/sizeof(ErlDrvTermData)); } return; }
static void async_cleanup_and_send_mutex_stats(PortData* d, DB_MUTEX_STAT *msp) { // Save the port and pid references -- we need copies independent from the PortData // structure. Once we release the port_lock after clearing the cmd, it's possible that // the port could go away without waiting on us to finish. This is acceptable, but we need // to be certain that there is no overlap of data between the two threads. driver_send_term // is safe to use from a thread, even if the port you're sending from has already expired. ErlDrvPort port = d->port; ErlDrvTermData pid = d->port_owner; bdberl_async_cleanup(d); ErlDrvTermData response[] = { ERL_DRV_ATOM, driver_mk_atom("ok"), // Start of list ST_STATS_TUPLE(msp, mutex_align), /* Mutex alignment */ ST_STATS_TUPLE(msp, mutex_tas_spins), /* Mutex test-and-set spins */ ST_STATS_TUPLE(msp, mutex_cnt), /* Mutex count */ ST_STATS_TUPLE(msp, mutex_free), /* Available mutexes */ ST_STATS_TUPLE(msp, mutex_inuse), /* Mutexes in use */ ST_STATS_TUPLE(msp, mutex_inuse_max), /* Maximum mutexes ever in use */ ST_STATS_TUPLE(msp, region_wait), /* Region lock granted after wait. */ ST_STATS_TUPLE(msp, region_nowait), /* Region lock granted without wait. */ ST_STATS_TUPLE(msp, regsize), /* Region size. */ // End of list ERL_DRV_NIL, ERL_DRV_LIST, 9+1, ERL_DRV_TUPLE, 2 }; driver_send_term(port, pid, response, sizeof(response) / sizeof(response[0])); }
static void zmqdrv_getsockopt(zmq_drv_t *drv, ErlIOVec *ev) { ErlDrvBinary* bin = ev->binv[1]; char* bytes = bin->orig_bytes; uint32_t idx = ntohl(*(uint32_t*)(bytes+1)); void* s = drv->get_zmq_socket(idx); uint32_t opt = ntohl (*(uint32_t*)(bytes+sizeof(idx)+1)); if (opt == ZMQ_RCVMORE) { int64_t val; size_t valsz = sizeof (val); if (zmq_getsockopt (s, opt, &val, &valsz) < 0) { zmqdrv_error_code(drv, zmq_errno()); return; } ErlDrvTermData spec[] = { ERL_DRV_ATOM, am_zok, ERL_DRV_ATOM, (val ? am_true : am_false), ERL_DRV_TUPLE, 2}; driver_send_term(drv->port, driver_caller(drv->port), spec, sizeof(spec)/sizeof(spec[0])); return; } zmqdrv_error(drv, "Not implemented"); }
int erl_tess_impl(char* buff, ErlDrvPort port, ErlDrvTermData caller) { ErlDrvBinary* bin; int i; int num_vertices; GLdouble *n; int AP; int a_max = 2; int i_max = 6; num_vertices = * (int *) buff; buff += 8; /* Align */ n = (double *) buff; buff += 8*3; egl_tess.alloc_max = a_max*num_vertices*3; bin = driver_alloc_binary(egl_tess.alloc_max*sizeof(GLdouble)); egl_tess.error = 0; egl_tess.tess_coords = (double *) bin->orig_bytes; memcpy(egl_tess.tess_coords,buff,num_vertices*3*sizeof(GLdouble)); egl_tess.index_max = i_max*3*num_vertices; egl_tess.tess_index_list = (int *) driver_alloc(sizeof(int) * egl_tess.index_max); egl_tess.tess_coords = (double *) bin->orig_bytes; egl_tess.index_n = 0; egl_tess.alloc_n = num_vertices*3; gluTessNormal(tess, n[0], n[1], n[2]); gluTessBeginPolygon(tess, 0); gluTessBeginContour(tess); for (i = 0; i < num_vertices; i++) { gluTessVertex(tess, egl_tess.tess_coords+3*i, egl_tess.tess_coords+3*i); } gluTessEndContour(tess); gluTessEndPolygon(tess); AP = 0; ErlDrvTermData *rt; rt = (ErlDrvTermData *) driver_alloc(sizeof(ErlDrvTermData) * (13+egl_tess.index_n*2)); rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_"); for(i=0; i < egl_tess.index_n; i++) { rt[AP++] = ERL_DRV_INT; rt[AP++] = (int) egl_tess.tess_index_list[i]; }; rt[AP++] = ERL_DRV_NIL; rt[AP++] = ERL_DRV_LIST; rt[AP++] = egl_tess.index_n+1; rt[AP++] = ERL_DRV_BINARY; rt[AP++] = (ErlDrvTermData) bin; rt[AP++] = egl_tess.alloc_n*sizeof(GLdouble); rt[AP++] = 0; rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2; // Return tuple {list, Bin} rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2; // Result tuple driver_send_term(port,caller,rt,AP); /* fprintf(stderr, "List %d: %d %d %d \r\n", */ /* res, */ /* n_pos, */ /* (tess_alloc_vertex-new_vertices)*sizeof(GLdouble), */ /* num_vertices*6*sizeof(GLdouble)); */ driver_free_binary(bin); driver_free(egl_tess.tess_index_list); driver_free(rt); return 0; }
/* This function is called after an asynchronous call has completed. The asynchronous call is started with driver_async. This function is called from the erlang emulator thread, as opposed to the asynchronous function, which is called in some thread (if multithreading is enabled). THIS IMPLEMENTATION of the callback, processes the supplied transform_result and sends it to the appropriate erlang process (e.g. the specified receiver). */ static void ready_async(ErlDrvData drv_data, ErlDrvThreadData data) { long response_len; ErlDrvTermData *term; DriverHandle *driver_handle = (DriverHandle*)drv_data; ErlDrvPort port = (ErlDrvPort)driver_handle->port; XslEngine *provider = (XslEngine*)driver_handle->engine; AsyncState *async_state = (AsyncState*)data; EngineState state = async_state->state; Command *command = async_state->command; ErlDrvTermData callee_pid = (ErlDrvTermData)(command->context)->caller_pid; ErlDrvTermData tag = (state == Ok) ? atom_result : atom_error; DriverIOVec* outv = command->result; if (state == OutOfMemoryError) { ERROR("Driver Out Of Memory!\n"); free_async_state(async_state); FAIL(port, "system_limit"); // this statement [above] will cause the driver to unload, so we may as well fail fast.... return; } switch (outv->type) { case Text: term = make_driver_term(&port, outv->payload.buffer, &tag, &response_len); break; case Binary: term = make_driver_term_bin(&port, ((ErlDrvBinary*)outv->payload.data), &tag, &response_len); break; default: term = make_driver_term(&port, (char*)unsupported_response_type, &tag, &response_len); break; } if (term == NULL) { ERROR("Driver Out Of Memory!\n"); // do a quick internal cleanup ? // free_async_state(asd); // give the XslEngine a chance to try and clean up!? // state = provider->after_transform(command); FAIL(port, "system_limit"); // this statement [above] will cause the driver to unload, so we may as well fail fast.... return; } INFO("Sending back response! \n"); // TODO: use driver_output_term instead, passing the origin-PID in the term and use gen_server:reply to forward driver_send_term(port, callee_pid, term, response_len); // now the engine needs the opportunity to free up any intermediate structures INFO("provider handoff: after_transform\n"); state = provider->after_transform(command); // internal cleanup time... free_async_state(async_state); };
static void zmqdrv_error(zmq_drv_t *drv, const char *errstr) { ErlDrvTermData spec[] = {ERL_DRV_ATOM, am_error, ERL_DRV_STRING, (ErlDrvTermData)errstr, strlen(errstr), ERL_DRV_TUPLE, 2}; driver_send_term(drv->port, driver_caller(drv->port), spec, sizeof(spec)/sizeof(spec[0])); }
static void zmqdrv_error_code(zmq_drv_t *drv, int err) { ErlDrvTermData spec[] = {ERL_DRV_ATOM, am_error, ERL_DRV_ATOM, error_atom(err), ERL_DRV_TUPLE, 2}; driver_send_term(drv->port, driver_caller(drv->port), spec, sizeof(spec)/sizeof(spec[0])); }
static void send_txn_tstat(ErlDrvPort port, ErlDrvTermData pid, DB_TXN_ACTIVE *tasp) { char *name = tasp->name ? tasp->name : "<null>"; int name_len = strlen(name); char tid_str[32]; char *status_str; switch (tasp->status) { case TXN_ABORTED: status_str = "aborted"; break; case TXN_COMMITTED: status_str = "committed"; break; case TXN_PREPARED: status_str = "prepared"; break; case TXN_RUNNING: status_str = "running"; break; default: status_str = "undefined"; break; } int tid_str_len = snprintf(tid_str, sizeof(tid_str), "%lu", (unsigned long) tasp->tid); ErlDrvTermData response[] = { ERL_DRV_ATOM, driver_mk_atom("txn"), STATS_TUPLE(tasp, txnid), /* Transaction ID */ STATS_TUPLE(tasp, parentid), /* Transaction ID of parent */ STATS_TUPLE(tasp, pid), /* Process owning txn ID - pid_t */ ERL_DRV_ATOM, driver_mk_atom("tid"),/* OSX has 32-bit ints in erlang, so return as */ ERL_DRV_STRING, (ErlDrvTermData) tid_str, tid_str_len, /* a string */ ERL_DRV_TUPLE, 2, STATS_LSN_TUPLE(tasp, lsn), /* LSN when transaction began */ STATS_LSN_TUPLE(tasp, read_lsn), /* Read LSN for MVCC */ STATS_TUPLE(tasp, mvcc_ref), /* MVCC reference count */ // Start of list ERL_DRV_ATOM, driver_mk_atom("status"), ERL_DRV_ATOM, driver_mk_atom(status_str), ERL_DRV_TUPLE, 2, ERL_DRV_ATOM, driver_mk_atom("name"), ERL_DRV_STRING, (ErlDrvTermData) name, name_len, ERL_DRV_TUPLE, 2, // End of list ERL_DRV_NIL, ERL_DRV_LIST, 9+1, ERL_DRV_TUPLE, 2 }; driver_send_term(port, pid, response, sizeof(response) / sizeof(response[0])); }
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ static void reply_ok(ErlDrvPort port, ErlDrvTermData pid) { ErlDrvTermData spec[] = { ERL_DRV_ATOM, am_zmq_drv, ERL_DRV_ATOM, am_ok, ERL_DRV_TUPLE, 2 }; driver_send_term(port, pid, spec, sizeof(spec)/sizeof(spec[0])); }
static void zmqdrv_ok_atom(zmq_drv_t *drv, ErlDrvTermData pid, ErlDrvTermData val) { ErlDrvTermData spec[] = { ERL_DRV_ATOM, am_zok, ERL_DRV_ATOM, val, ERL_DRV_TUPLE, 2 }; driver_send_term(drv->port, pid, spec, sizeof(spec)/sizeof(spec[0])); }
static void zmqdrv_ok_int64(zmq_drv_t *drv, ErlDrvTermData pid, int64_t val) { ErlDrvTermData spec[] = { ERL_DRV_ATOM, am_zok, ERL_DRV_INT64, TERM_DATA(&val), ERL_DRV_TUPLE, 2 }; driver_send_term(drv->port, pid, spec, sizeof(spec)/sizeof(spec[0])); }
static void zmqdrv_ok_bool(zmq_drv_t *drv, ErlDrvTermData pid, bool val) { ErlDrvTermData spec[] = { ERL_DRV_ATOM, am_zok, ERL_DRV_ATOM, (val ? am_true : am_false), ERL_DRV_TUPLE, 2 }; driver_send_term(drv->port, pid, spec, sizeof(spec)/sizeof(spec[0])); }
static void zmqdrv_ok_binary(zmq_drv_t *drv, ErlDrvTermData pid, void *data, size_t size) { /* Copy payload. */ ErlDrvTermData spec[] = {ERL_DRV_ATOM, am_zok, ERL_DRV_BUF2BINARY, (ErlDrvTermData)data, size, ERL_DRV_TUPLE, 2}; driver_send_term(drv->port, pid, spec, sizeof(spec)/sizeof(spec[0])); }
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ static void reply_ok_uint64(ErlDrvPort port, ErlDrvTermData pid, ErlDrvUInt64 num) { ErlDrvTermData spec[] = { ERL_DRV_ATOM, am_zmq_drv, ERL_DRV_ATOM, am_ok, ERL_DRV_UINT64, TERM_DATA(&num), ERL_DRV_TUPLE, 2, ERL_DRV_TUPLE, 2 }; driver_send_term(port, pid, spec, sizeof(spec)/sizeof(spec[0])); }
void es_showCursor2(ErlDrvPort port, ErlDrvTermData caller, char *bp) { Uint8 bool; ErlDrvTermData rt[8]; bool = (Uint8) *bp; bool = SDL_ShowCursor(bool); rt[0] = ERL_DRV_ATOM; rt[1]=driver_mk_atom((char *) "_esdl_result_"); rt[2] = ERL_DRV_INT; rt[3] = bool; rt[4] = ERL_DRV_TUPLE; rt[5] = 2; driver_send_term(port,caller,rt,6); }
void WxeApp::newMemEnv(wxeMetaCommand& Ecmd) { wxeMemEnv * memenv = new wxeMemEnv(); for(int i = 0; i < global_me->next; i++) { memenv->ref2ptr[i] = global_me->ref2ptr[i]; } memenv->next = global_me->next; refmap[(ErlDrvTermData) Ecmd.port] = memenv; memenv->owner = Ecmd.caller; ErlDrvTermData rt[] = {ERL_DRV_ATOM, driver_mk_atom((char *)"wx_port_initiated")}; driver_send_term(WXE_DRV_PORT,Ecmd.caller,rt,2); }
static void zmqdrv_socket_error(zmq_drv_t *drv, ErlDrvTermData pid, uint32_t idx, int err) { // Return {zmq, Socket::integer(), {error, Reason::atom()}} ErlDrvTermData spec[] = {ERL_DRV_ATOM, am_zmq, ERL_DRV_UINT, idx, ERL_DRV_ATOM, am_error, ERL_DRV_ATOM, error_atom(err), ERL_DRV_TUPLE, 2, ERL_DRV_TUPLE, 3}; driver_send_term(drv->port, pid, spec, sizeof(spec)/sizeof(spec[0])); }
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ static void reply_error(ErlDrvPort port, ErlDrvTermData pid, int err) { // Return {zmq, Socket::integer(), {error, Reason::atom()}} ErlDrvTermData spec[] = { ERL_DRV_ATOM, am_zmq_drv, ERL_DRV_ATOM, am_error, ERL_DRV_ATOM, error_atom(err), ERL_DRV_TUPLE, 2, ERL_DRV_TUPLE, 2 }; driver_send_term(port, pid, spec, sizeof(spec)/sizeof(spec[0])); }
/* send {P, ok} to caller */ static int driver_send_ok(t_iconvdrv *iv) { int i = 0; ErlDrvTermData to, spec[10]; to = driver_caller(iv->port); i = LOAD_PORT(spec, i, iv->dport); i = LOAD_ATOM(spec, i, am_ok); i = LOAD_TUPLE(spec, i, 2); return driver_send_term(iv->port, to, spec, i); }
/* send {P, value, Bin} to caller */ static int driver_send_bin(t_iconvdrv *iv, ErlDrvBinary *bin, int len) { int i = 0; ErlDrvTermData to, spec[10]; to = driver_caller(iv->port); i = LOAD_PORT(spec, i, iv->dport); i = LOAD_ATOM(spec, i, am_value); i = LOAD_BINARY(spec, i, bin, 0, len); i = LOAD_TUPLE(spec, i, 3); return driver_send_term(iv->port, to, spec, i); }
/* send {P, error, Error} to caller */ static int driver_send_error(t_iconvdrv *iv, ErlDrvTermData *am) { int i = 0; ErlDrvTermData to, spec[8]; to = driver_caller(iv->port); i = LOAD_PORT(spec, i, iv->dport); i = LOAD_ATOM(spec, i, am_error); i = LOAD_ATOM(spec, i, *am); i = LOAD_TUPLE(spec, i, 3); return driver_send_term(iv->port, to, spec, i); }
// NOTE: when SMP is enabled the messages go straight to the caller // This code is here to allow non SMP emulator with the same code base. static void uart_drv_ready_input(ErlDrvData d, ErlDrvEvent e) { drv_ctx_t* ctx = (drv_ctx_t*) d; DEBUGF("uart_drv: ready_input called"); if (ctx->self.iq_signal[0] == e) { // got input ! dmessage_t* mp; DEBUGF("uart_drv: ready_input handle=%d", DTHREAD_EVENT(ctx->self.iq_signal[0])); if ((mp = dthread_recv(&ctx->self, NULL)) == NULL) { DEBUGF("uart_drv: ready_input signaled with no event! handle=%d", DTHREAD_EVENT(ctx->self.iq_signal[0])); return; } switch(mp->cmd) { case DTHREAD_OUTPUT_TERM: DEBUGF("uart_drv: ready_input (OUTPUT_TERM)"); driver_output_term(ctx->self.port, (ErlDrvTermData*) mp->buffer, mp->used / sizeof(ErlDrvTermData)); break; case DTHREAD_SEND_TERM: DEBUGF("uart_drv: ready_input (SEND_TERM)"); // dterm_dump(stderr, (ErlDrvTermData*) mp->buffer, // mp->used / sizeof(ErlDrvTermData)); driver_send_term(ctx->self.port, mp->to, /* orignal from ! */ (ErlDrvTermData*) mp->buffer, mp->used / sizeof(ErlDrvTermData)); break; case DTHREAD_OUTPUT: DEBUGF("uart_drv: ready_input (OUTPUT)"); driver_output(ctx->self.port, mp->buffer, mp->used); break; default: DEBUGF("uart_drv: read_input cmd=%d not matched", mp->cmd); break; } dmessage_free(mp); } else { DEBUGF("uart_drv: ready_input (NO MATCH)"); } }
static void async_cleanup_and_send_log_stats(PortData* d, DB_LOG_STAT *lsp) { // Save the port and pid references -- we need copies independent from the PortData // structure. Once we release the port_lock after clearing the cmd, it's possible that // the port could go away without waiting on us to finish. This is acceptable, but we need // to be certain that there is no overlap of data between the two threads. driver_send_term // is safe to use from a thread, even if the port you're sending from has already expired. ErlDrvPort port = d->port; ErlDrvTermData pid = d->port_owner; bdberl_async_cleanup(d); ErlDrvTermData response[] = { ERL_DRV_ATOM, driver_mk_atom("ok"), // Start of list ST_STATS_TUPLE(lsp, magic), /* Log file magic number. */ ST_STATS_TUPLE(lsp, version), /* Log file version number. */ ST_STATS_INT_TUPLE(lsp, mode), /* Log file permissions mode. */ ST_STATS_TUPLE(lsp, lg_bsize), /* Log buffer size. */ ST_STATS_TUPLE(lsp, lg_size), /* Log file size. */ ST_STATS_TUPLE(lsp, wc_bytes), /* Bytes to log since checkpoint. */ ST_STATS_TUPLE(lsp, wc_mbytes), /* Megabytes to log since checkpoint. */ ST_STATS_TUPLE(lsp, record), /* Records entered into the log. */ ST_STATS_TUPLE(lsp, w_bytes), /* Bytes to log. */ ST_STATS_TUPLE(lsp, w_mbytes), /* Megabytes to log. */ ST_STATS_TUPLE(lsp, wcount), /* Total I/O writes to the log. */ ST_STATS_TUPLE(lsp, wcount_fill),/* Overflow writes to the log. */ ST_STATS_TUPLE(lsp, rcount), /* Total I/O reads from the log. */ ST_STATS_TUPLE(lsp, scount), /* Total syncs to the log. */ ST_STATS_TUPLE(lsp, region_wait), /* Region lock granted after wait. */ ST_STATS_TUPLE(lsp, region_nowait), /* Region lock granted without wait. */ ST_STATS_TUPLE(lsp, cur_file), /* Current log file number. */ ST_STATS_TUPLE(lsp, cur_offset),/* Current log file offset. */ ST_STATS_TUPLE(lsp, disk_file), /* Known on disk log file number. */ ST_STATS_TUPLE(lsp, disk_offset), /* Known on disk log file offset. */ ST_STATS_TUPLE(lsp, maxcommitperflush), /* Max number of commits in a flush. */ ST_STATS_TUPLE(lsp, mincommitperflush), /* Min number of commits in a flush. */ ST_STATS_TUPLE(lsp, regsize), /* Region size. */ // End of list ERL_DRV_NIL, ERL_DRV_LIST, 23+1, ERL_DRV_TUPLE, 2 }; driver_send_term(port, pid, response, sizeof(response) / sizeof(response[0])); }
static void async_cleanup_and_send_btree_stats(PortData* d, char *type, DB_BTREE_STAT *bsp) { // Save the port and pid references -- we need copies independent from the PortData // structure. Once we release the port_lock after clearing the cmd, it's possible that // the port could go away without waiting on us to finish. This is acceptable, but we need // to be certain that there is no overlap of data between the two threads. driver_send_term // is safe to use from a thread, even if the port you're sending from has already expired. ErlDrvPort port = d->port; ErlDrvTermData pid = d->port_owner; bdberl_async_cleanup(d); ErlDrvTermData response[] = { ERL_DRV_ATOM, driver_mk_atom("ok"), // Start of list ERL_DRV_ATOM, driver_mk_atom("type"), ERL_DRV_ATOM, driver_mk_atom(type), ERL_DRV_TUPLE, 2, BT_STATS_TUPLE(bsp, magic), /* Magic number. */ BT_STATS_TUPLE(bsp, version), /* Version number. */ BT_STATS_TUPLE(bsp, metaflags), /* Metadata flags. */ BT_STATS_TUPLE(bsp, nkeys), /* Number of unique keys. */ BT_STATS_TUPLE(bsp, ndata), /* Number of data items. */ BT_STATS_TUPLE(bsp, pagecnt), /* Page count. */ BT_STATS_TUPLE(bsp, pagesize), /* Page size. */ BT_STATS_TUPLE(bsp, minkey), /* Minkey value. */ BT_STATS_TUPLE(bsp, re_len), /* Fixed-length record length. */ BT_STATS_TUPLE(bsp, re_pad), /* Fixed-length record pad. */ BT_STATS_TUPLE(bsp, levels), /* Tree levels. */ BT_STATS_TUPLE(bsp, int_pg), /* Internal pages. */ BT_STATS_TUPLE(bsp, leaf_pg), /* Leaf pages. */ BT_STATS_TUPLE(bsp, dup_pg), /* Duplicate pages. */ BT_STATS_TUPLE(bsp, over_pg), /* Overflow pages. */ BT_STATS_TUPLE(bsp, empty_pg), /* Empty pages. */ BT_STATS_TUPLE(bsp, free), /* Pages on the free list. */ BT_STATS_TUPLE(bsp, int_pgfree), /* Bytes free in internal pages. */ BT_STATS_TUPLE(bsp, leaf_pgfree), /* Bytes free in leaf pages. */ BT_STATS_TUPLE(bsp, dup_pgfree), /* Bytes free in duplicate pages. */ BT_STATS_TUPLE(bsp, over_pgfree), /* Bytes free in overflow pages. */ // End of list ERL_DRV_NIL, ERL_DRV_LIST, 21+2, ERL_DRV_TUPLE, 2 }; driver_send_term(port, pid, response, sizeof(response) / sizeof(response[0])); }
static void async_cleanup_and_send_txn_stats(PortData* d, DB_TXN_STAT *tsp) { // Save the port and pid references -- we need copies independent from the PortData // structure. Once we release the port_lock after clearing the cmd, it's possible that // the port could go away without waiting on us to finish. This is acceptable, but we need // to be certain that there is no overlap of data between the two threads. driver_send_term // is safe to use from a thread, even if the port you're sending from has already expired. ErlDrvPort port = d->port; ErlDrvTermData pid = d->port_owner; bdberl_async_cleanup(d); // First send the array of active transactions */ int i; for (i = 0; i < tsp->st_nactive; i++) { send_txn_tstat(port, pid, tsp->st_txnarray+i); } // Then send the global stats ErlDrvTermData response[] = { ERL_DRV_ATOM, driver_mk_atom("ok"), // Start of list ST_STATS_TUPLE(tsp, nrestores), /* number of restored transactions after recovery. */ ST_STATS_LSN_TUPLE(tsp, last_ckp), /* lsn of the last checkpoint */ ST_STATS_TUPLE(tsp, time_ckp), /* time of last checkpoint (time_t to uint) */ ST_STATS_TUPLE(tsp, last_txnid), /* last transaction id given out */ ST_STATS_TUPLE(tsp, maxtxns), /* maximum txns possible */ ST_STATS_TUPLE(tsp, naborts), /* number of aborted transactions */ ST_STATS_TUPLE(tsp, nbegins), /* number of begun transactions */ ST_STATS_TUPLE(tsp, ncommits), /* number of committed transactions */ ST_STATS_TUPLE(tsp, nactive), /* number of active transactions */ ST_STATS_TUPLE(tsp, nsnapshot), /* number of snapshot transactions */ ST_STATS_TUPLE(tsp, maxnactive), /* maximum active transactions */ ST_STATS_TUPLE(tsp, maxnsnapshot), /* maximum snapshot transactions */ ST_STATS_TUPLE(tsp, region_wait), /* Region lock granted after wait. */ ST_STATS_TUPLE(tsp, region_nowait), /* Region lock granted without wait. */ ST_STATS_TUPLE(tsp, regsize), /* Region size. */ // End of list ERL_DRV_NIL, ERL_DRV_LIST, 15+1, ERL_DRV_TUPLE, 2 }; driver_send_term(port, pid, response, sizeof(response) / sizeof(response[0])); }