Пример #1
0
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
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]));
    }
}
Пример #2
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);
}
Пример #3
0
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;
}
Пример #4
0
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);
}
Пример #5
0
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);
}
Пример #6
0
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;
}
Пример #7
0
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]));
}
Пример #8
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");
}
Пример #9
0
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;
}
Пример #10
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);
};
Пример #11
0
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]));
}
Пример #12
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]));
}
Пример #13
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]));
}
Пример #14
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]));
}
Пример #15
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]));
}
Пример #16
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]));
}
Пример #17
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]));
}
Пример #18
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]));
}
Пример #19
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]));
}
Пример #20
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);
}
Пример #21
0
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);
}
Пример #22
0
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]));
}
Пример #23
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]));
}
Пример #24
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);
}
Пример #25
0
/* 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);
}
Пример #26
0
/* 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);
}
Пример #27
0
// 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)");
    }
}
Пример #28
0
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]));
}
Пример #29
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]));
}
Пример #30
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]));
}