int ei_x_encode_empty_list(ei_x_buff* x) { int i = x->index; ei_encode_empty_list(NULL, &i); if (!x_fix_buff(x, i)) return -1; return ei_encode_empty_list(x->buff, &x->index); }
ETERM *erl_global_whereis(int fd, const char *name, char *node) { char buf[EISMALLBUF]; char *bufp=buf; char tmpbuf[64]; int index = 0; erlang_pid *self = erl_self(); erlang_pid epid; ETERM *opid; erlang_msg msg; int i; int version,arity,msglen; self->num = fd; /* FIXME looks strange to change something?! */ ei_encode_version(buf,&index); ei_encode_tuple_header(buf,&index,2); ei_encode_pid(buf,&index,self); /* PidFrom */ ei_encode_tuple_header(buf,&index,5); ei_encode_atom(buf,&index,"call"); /* call */ ei_encode_atom(buf,&index,"global"); /* Mod */ ei_encode_atom(buf,&index,"whereis_name"); /* Fun */ ei_encode_list_header(buf,&index,1); /* Args: [ name ] */ ei_encode_atom(buf,&index,name); ei_encode_empty_list(buf,&index); ei_encode_atom(buf,&index,"user"); /* user */ /* make the rpc call */ if (ei_send_reg_encoded(fd,self,"rex",buf,index)) return NULL; while (1) { index = EISMALLBUF; if (!(i = ei_recv_internal(fd,&bufp,&index,&msg,&msglen,1,0))) continue; else break; } if (i != ERL_SEND) return NULL; /* expecting { rex, pid } */ index = 0; if (ei_decode_version(buf,&index,&version) || ei_decode_tuple_header(buf,&index,&arity) || (arity != 2) || ei_decode_atom(buf,&index,tmpbuf) || strcmp(tmpbuf,"rex") || ei_decode_pid(buf,&index,&epid)) return NULL; /* bad response from other side */ /* put the pid into a format for the caller */ index = 0; ei_encode_pid(buf,&index,&epid); opid = erl_decode((unsigned char*)buf); /* extract the nodename for the caller */ if (node) strcpy(node,epid.node); return opid; }
static void handle_configuration(const char *req, int *req_index) { char resp[256]; int resp_index = sizeof(uint16_t); // Space for payload size resp[resp_index++] = response_id; ei_encode_version(resp, &resp_index); ei_encode_list_header(resp, &resp_index, 5); ei_encode_tuple_header(resp, &resp_index, 2); ei_encode_atom(resp, &resp_index, "speed"); ei_encode_long(resp, &resp_index, current_config.speed); ei_encode_tuple_header(resp, &resp_index, 2); ei_encode_atom(resp, &resp_index, "data_bits"); ei_encode_long(resp, &resp_index, current_config.data_bits); ei_encode_tuple_header(resp, &resp_index, 2); ei_encode_atom(resp, &resp_index, "stop_bits"); ei_encode_long(resp, &resp_index, current_config.stop_bits); ei_encode_tuple_header(resp, &resp_index, 2); ei_encode_atom(resp, &resp_index, "parity"); switch (current_config.parity) { default: case UART_PARITY_NONE: ei_encode_atom(resp, &resp_index, "none"); break; case UART_PARITY_EVEN: ei_encode_atom(resp, &resp_index, "even"); break; case UART_PARITY_ODD: ei_encode_atom(resp, &resp_index, "odd"); break; case UART_PARITY_SPACE: ei_encode_atom(resp, &resp_index, "space"); break; case UART_PARITY_MARK: ei_encode_atom(resp, &resp_index, "mark"); break; case UART_PARITY_IGNORE: ei_encode_atom(resp, &resp_index, "ignore"); break; } ei_encode_tuple_header(resp, &resp_index, 2); ei_encode_atom(resp, &resp_index, "flow_control"); switch (current_config.parity) { default: case UART_FLOWCONTROL_NONE: ei_encode_atom(resp, &resp_index, "none"); break; case UART_FLOWCONTROL_HARDWARE: ei_encode_atom(resp, &resp_index, "hardware"); break; case UART_FLOWCONTROL_SOFTWARE: ei_encode_atom(resp, &resp_index, "software"); break; } ei_encode_empty_list(resp, &resp_index); erlcmd_send(resp, resp_index); }
/*! * Return statistics (amount of calls) for the driver and the currently active * thread. This function does not send any arguments to the driver. * * \param[in] req Request * \param[in,out] res Result * \param[in,out] drv_state Driver state * \param[in,out] trd_state Thread state */ static void handle_stats(gd_req_t *req, gd_res_t *res, gdt_drv_t *drv, gdt_trd_t *trd) { /* Encode return tuple header */ ei_encode_tuple_header(res->buf, &res->index, 2); ei_encode_atom(res->buf, &res->index, "ok"); /* Encode proplist header */ ei_encode_list_header(res->buf, &res->index, 2); /* Encode driver calls */ ei_encode_tuple_header(res->buf, &res->index, 2); ei_encode_atom(res->buf, &res->index, "driver"); ei_encode_long(res->buf, &res->index, drv->count++); /* Encode thread calls */ ei_encode_tuple_header(res->buf, &res->index, 2); ei_encode_atom(res->buf, &res->index, "thread"); ei_encode_long(res->buf, &res->index, trd->count++); /* Encode empty list at the end */ ei_encode_empty_list(res->buf, &res->index); }
int erl_global_register(int fd, const char *name, ETERM *pid) { char buf[EISMALLBUF]; char *bufp=buf; char tmpbuf[64]; int index = 0; erlang_pid self; erlang_msg msg; int needlink, needatom, needmonitor; int arity; int version; int msglen; int i; /* get that pid into a better format */ if (!erl_encode(pid,(unsigned char*)buf)) return -1; if (ei_decode_version(buf,&index,&version) || ei_decode_pid(buf,&index,&self)) return -1; /* set up rpc arguments */ /* { PidFrom, { call, Mod, Fun, Args, user }} */ index = 0; ei_encode_version(buf,&index); ei_encode_tuple_header(buf,&index,2); ei_encode_pid(buf,&index,&self); /* PidFrom */ ei_encode_tuple_header(buf,&index,5); ei_encode_atom(buf,&index,"call"); /* call */ ei_encode_atom(buf,&index,"global"); /* Mod */ ei_encode_atom(buf,&index,"register_name_external"); /* Fun */ ei_encode_list_header(buf,&index,3); /* Args: [ name, self(), cnode ] */ ei_encode_atom(buf,&index,name); ei_encode_pid(buf,&index,&self); ei_encode_tuple_header(buf,&index,2); ei_encode_atom(buf,&index,"global"); /* special "resolve" treatment */ ei_encode_atom(buf,&index,"cnode"); /* i.e. we get a SEND when conflict */ ei_encode_empty_list(buf,&index); ei_encode_atom(buf,&index,"user"); /* user */ /* make the rpc call */ if (ei_send_reg_encoded(fd,&self,"rex",buf,index)) return -1; /* get the reply: expect link and an atom, or just an atom */ needlink = needatom = needmonitor = 1; while (1) { /* get message */ while (1) { index = EISMALLBUF; if (!(i = ei_recv_internal(fd,&bufp,&index,&msg,&msglen,1,0))) continue; else break; } switch (i) { case ERL_LINK: /* got link */ if (!needlink) return -1; needlink = 0; break; case ERL_MONITOR_P-10: /* got monitor */ if (!needmonitor) { return -1;} needmonitor = 0; break; case ERL_SEND: /* got message - does it contain our atom? */ if (!needatom) return -1; else { /* expecting { rex, yes } */ index = 0; if (ei_decode_version(buf,&index,&version) || ei_decode_tuple_header(buf,&index,&arity) || (arity != 2) || ei_decode_atom(buf,&index,tmpbuf) || strcmp(tmpbuf,"rex") || ei_decode_atom(buf,&index,tmpbuf) || strcmp(tmpbuf,"yes")) return -1; /* bad response from other side */ /* we're done */ return 0; } break; default: return -1; /* something else */ } } return 0; }
static int mn_start_restore(int fd, const erlang_pid *self, erlang_pid *mnesia, const char *mntab, long *count, long *maxkey,long *maxobj) { char buf[EISMALLBUF]; char *bufp=buf; char tmpbuf[64]; int index = 0; erlang_msg msg; int arity; int version; int i; int needlink; int needmsg; int msglen; /* set up rpc arguments */ /* { PidFrom, { call, Mod, Fun, Args, user }} */ ei_encode_version(buf,&index); ei_encode_tuple_header(buf,&index,2); ei_encode_pid(buf,&index,self); /* PidFrom */ ei_encode_tuple_header(buf,&index,5); ei_encode_atom(buf,&index,"call"); /* call */ ei_encode_atom(buf,&index,EI_MNESIA_MODULE); /* Mod */ ei_encode_atom(buf,&index,EI_MNESIA_RESTORE); /* Fun */ ei_encode_list_header(buf,&index,2); /* Args: [ table, self() ] */ ei_encode_atom(buf,&index,mntab); ei_encode_pid(buf,&index,self); ei_encode_empty_list(buf,&index); ei_encode_atom(buf,&index,"user"); /* user */ /* make the rpc call */ if (ei_send_reg_encoded(fd,self,"rex",buf,index)) return -1; /* get the reply: expect link and message (not sure which will come first though) */ needlink = needmsg = 1; while (needlink || needmsg) { /* get message */ index = EISMALLBUF; while (!(i = ei_recv_internal(fd,&bufp,&index,&msg,&msglen,1,0))) index = EISMALLBUF; switch (i) { case ERL_LINK: /* got link */ if (!needlink) return -1; needlink = 0; break; case ERL_SEND: /* got message - is it the right one? */ if (!needmsg) return -1; else { /* expecting { rex, { size, Pid, Count, MaxKey, MaxObj }} */ index = 0; if (ei_decode_version(buf,&index,&version) || ei_decode_tuple_header(buf,&index,&arity) || (arity != 2) || ei_decode_atom(buf,&index,tmpbuf) || strcmp(tmpbuf,"rex") || ei_decode_tuple_header(buf,&index,&arity) || (arity != 5) || ei_decode_atom(buf,&index,tmpbuf) || strcmp(tmpbuf,EI_MNESIA_SIZE) || ei_decode_pid(buf,&index,mnesia) || ei_decode_long(buf,&index,count) || ei_decode_long(buf,&index,maxkey) || ei_decode_long(buf,&index,maxobj)) return -1; /* bad response from other side */ /* got msg */ needmsg = 0; } break; default: return -1; /* wasn't link or pid */ } } return 0; }
static int mn_start_dump(int fd, const erlang_pid *self, erlang_pid *mnesia, const char *mntab) { char buf[EISMALLBUF]; char *bufp = buf; char tmpbuf[64]; int index = 0; erlang_msg msg; int type; int arity; int version; int msglen; int i; int needlink; int needpid; /* set up rpc arguments */ /* { PidFrom, { call, Mod, Fun, Args, user }} */ ei_encode_version(buf,&index); ei_encode_tuple_header(buf,&index,2); ei_encode_pid(buf,&index,self); /* PidFrom */ ei_encode_tuple_header(buf,&index,5); ei_encode_atom(buf,&index,"call"); /* call */ ei_encode_atom(buf,&index,EI_MNESIA_MODULE); /* Mod */ ei_encode_atom(buf,&index,EI_MNESIA_DUMP); /* Fun */ ei_encode_list_header(buf,&index,2); /* Args: [ table, self() ] */ ei_encode_atom(buf,&index,mntab); ei_encode_pid(buf,&index,self); ei_encode_empty_list(buf,&index); ei_encode_atom(buf,&index,"user"); /* user */ /* make the rpc call */ if (ei_send_reg_encoded(fd,self,"rex",buf,index)) return -1; /* get the reply: expect link and pid (not sure which will come first though) */ needlink = needpid = 1; while (needlink || needpid) { /* get message */ while (1) { index = EISMALLBUF; if (!(i = ei_recv_internal(fd,&bufp,&index,&msg,&msglen,1,0))) continue; else break; } switch (i) { case ERL_LINK: /* got link */ if (!needlink) return -1; needlink = 0; break; case ERL_SEND: /* got message - does it contain a pid? */ if (!needpid) return -1; else { /* expecting { rex, <pid> } */ index = 0; if (ei_decode_version(buf,&index,&version) || ei_decode_tuple_header(buf,&index,&arity) || (arity != 2) || ei_decode_atom(buf,&index,tmpbuf) || strcmp(tmpbuf,"rex") || ei_get_type_internal(buf,&index,&type,&arity) || (type != ERL_PID_EXT)) return -1; /* bad response from other side */ if (ei_decode_pid(buf,&index,mnesia)) return -1; /* got pid */ needpid = 0; } break; default: return -1; /* wasn't link or pid */ } } return 0; }
int my_encode_nil(char *buf, int *index, struct my_obj* dummy) { return ei_encode_empty_list(buf, index); }
/* global:unregister_name(name) -> ok */ int erl_global_unregister(int fd, const char *name) { char buf[EISMALLBUF]; char *bufp=buf; char tmpbuf[64]; int index = 0; erlang_pid *self = erl_self(); erlang_msg msg; int i; int version,arity,msglen; int needunlink, needatom, needdemonitor; /* make a self pid */ self->num = fd; ei_encode_version(buf,&index); ei_encode_tuple_header(buf,&index,2); ei_encode_pid(buf,&index,self); /* PidFrom */ ei_encode_tuple_header(buf,&index,5); ei_encode_atom(buf,&index,"call"); /* call */ ei_encode_atom(buf,&index,"global"); /* Mod */ ei_encode_atom(buf,&index,"unregister_name_external"); /* Fun */ ei_encode_list_header(buf,&index,1); /* Args: [ name ] */ ei_encode_atom(buf,&index,name); ei_encode_empty_list(buf,&index); ei_encode_atom(buf,&index,"user"); /* user */ /* make the rpc call */ if (ei_send_reg_encoded(fd,self,"rex",buf,index)) return -1; /* get the reply: expect unlink and an atom, or just an atom */ needunlink = needatom = needdemonitor = 1; while (1) { /* get message */ while (1) { index = EISMALLBUF; if (!(i = ei_recv_internal(fd,&bufp,&index,&msg,&msglen,1,0))) continue; else break; } switch (i) { case ERL_UNLINK: /* got unlink */ if (!needunlink) return -1; needunlink = 0; break; case ERL_DEMONITOR_P-10: /* got demonitor */ if (!needdemonitor) return -1; needdemonitor = 0; break; case ERL_SEND: /* got message - does it contain our atom? */ if (!needatom) return -1; else { /* expecting { rex, ok } */ index = 0; if (ei_decode_version(buf,&index,&version) || ei_decode_tuple_header(buf,&index,&arity) || (arity != 2) || ei_decode_atom(buf,&index,tmpbuf) || strcmp(tmpbuf,"rex") || ei_decode_atom(buf,&index,tmpbuf) || strcmp(tmpbuf,"ok")) return -1; /* bad response from other side */ /* we're done here */ return 0; } break; default: return -1; } } return 0; }
//Write the current contents of the values list to disk as a node //and add the resulting pointer to the pointers list. int flush_mr(couchfile_modify_result *res) { int nbufpos = 0; long long subtreesize = 0; eterm_buf reduce_value; //default reduce value [] reduce_value.buf = "\x6A"; //NIL_EXT reduce_value.size = 1; int reduced = 0; int errcode = 0; if(res->values_end == res->values || !res->modified) { //Empty return 0; } res->node_len += 19; //tuple header and node type tuple, list header and tail nif_writerq *wrq = nif_writerq_alloc(res->node_len); char *nodebuf = wrq->buf; //External term header; tuple header arity 2; ei_encode_version(nodebuf, &nbufpos); ei_encode_tuple_header(nodebuf, &nbufpos, 2); switch(res->node_type) { case KV_NODE: ei_encode_atom_len(nodebuf, &nbufpos, "kv_node", 7); if(res->rq->reduce) { (*res->rq->reduce)(&reduce_value, res->values->next, res->count); reduced = 1; } break; case KP_NODE: ei_encode_atom_len(nodebuf, &nbufpos, "kp_node", 7); if(res->rq->rereduce) { (*res->rq->rereduce)(&reduce_value, res->values->next, res->count); reduced = 1; } break; } ei_encode_list_header(nodebuf, &nbufpos, res->count); nodelist* i = res->values->next; eterm_buf last_key; while(i != NULL) { if(res->node_type == KV_NODE) //writing value in a kv_node { append_buf(nodebuf, &nbufpos, i->value.leaf->term.buf, i->value.leaf->term.size); if(i->next == NULL) { int pos = 0; term_to_buf(&last_key, i->value.leaf->term.buf+2, &pos); } } else if (res->node_type == KP_NODE) //writing value in a kp_node { if(wait_pointer(res->rq, i->value.pointer) < 0) { errcode = ERROR_WRITER_DEAD; goto cleanup; } subtreesize += i->value.pointer->subtreesize; ei_encode_tuple_header(nodebuf, &nbufpos, 2); //tuple arity 2 append_buf(nodebuf, &nbufpos, i->value.pointer->key.buf, i->value.pointer->key.size); ei_encode_tuple_header(nodebuf, &nbufpos, 3); //tuple arity 3 //pointer // v- between 2 and 10 bytes (ERL_SMALL_INTEGER_EXT to ERL_SMALL_BIG_EXT/8) ei_encode_ulonglong(nodebuf, &nbufpos, i->value.pointer->pointer); //reduce_value append_buf(nodebuf, &nbufpos, i->value.pointer->reduce_value.buf, i->value.pointer->reduce_value.size); //subtreesize // v- between 2 and 10 bytes (ERL_SMALL_INTEGER_EXT to ERL_SMALL_BIG_EXT/8) ei_encode_ulonglong(nodebuf, &nbufpos, i->value.pointer->subtreesize); if(i->next == NULL) { last_key = i->value.pointer->key; } } i = i->next; } //NIL_EXT (list tail) ei_encode_empty_list(nodebuf, &nbufpos); couchfile_pointer_info* ptr = malloc(sizeof(couchfile_pointer_info) + last_key.size + reduce_value.size); ptr->pointer = 0; nif_write(res->rq, ptr, wrq, nbufpos); ptr->key.buf = ((char*)ptr) + sizeof(couchfile_pointer_info); ptr->reduce_value.buf = ((char*)ptr) + sizeof(couchfile_pointer_info) + last_key.size; ptr->key.size = last_key.size; ptr->reduce_value.size = reduce_value.size; memcpy(ptr->key.buf, last_key.buf, last_key.size); memcpy(ptr->reduce_value.buf, reduce_value.buf, reduce_value.size); ptr->subtreesize = subtreesize; nodelist* pel = make_nodelist(); pel->value.pointer = ptr; res->pointers_end->next = pel; res->pointers_end = pel; res->node_len = 0; res->count = 0; res->values_end = res->values; free_nodelist(res->values->next); res->values->next = NULL; cleanup: if(errcode < 0) { enif_release_resource(wrq); } if(reduced) { free(reduce_value.buf); } return errcode; }