another bunch of erlang features: atoms are mapped to unicode

This commit is contained in:
roberto@maverick64
2011-02-09 12:32:26 +01:00
parent f8f9325cbc
commit e62679cc26
5 changed files with 246 additions and 20 deletions
+31 -1
View File
@@ -338,6 +338,9 @@ int erlang_init() {
char *host;
struct sockaddr_in sin;
socklen_t slen = sizeof(struct sockaddr_in);
char *ip = NULL;
char *nodename;
struct in_addr addr;
if (uerl.name) {
@@ -351,8 +354,35 @@ int erlang_init() {
exit(1);
}
}
else {
nodename = uwsgi_concat2n(uerl.name, host-uerl.name, "",0);
ip = uwsgi_resolve_ip(host+1);
if (ip) {
#ifdef UWSGI_DEBUG
uwsgi_log("ip: %s\n", ip);
#endif
addr.s_addr = inet_addr(ip);
if (ei_connect_xinit(&uerl.cnode, host+1, nodename, uerl.name, &addr, uerl.cookie, 0) < 0) {
uwsgi_log("unable to initialize erlang connection\n");
exit(1);
}
}
else {
if (ei_connect_init(&uerl.cnode, nodename, uerl.cookie, 0) < 0) {
uwsgi_log("unable to initialize erlang connection\n");
exit(1);
}
}
free(nodename);
}
if (ip) {
uerl.fd = bind_to_tcp(ip, uwsgi.listen_queue, NULL);
}
else {
uerl.fd = bind_to_tcp("", uwsgi.listen_queue, NULL);
}
uerl.fd = bind_to_tcp("", uwsgi.listen_queue, NULL);
if (uerl.fd < 0) {
exit(1);
}
+191 -8
View File
@@ -15,46 +15,224 @@ PyObject *pyerl_connect(PyObject * self, PyObject * args) {
int py_to_erl(PyObject *, ei_x_buff*);
PyObject *pyerl_simple_send(PyObject * self, PyObject * args) {
PyObject *erl_to_py(ei_x_buff* x) {
char *node;
int etype, esize, arity;
long long num;
double fnum;
char *atom, *binary;
long bin_size;
PyObject *pobj;
PyObject *zero;
erlang_pid epid;
int i;
ei_get_type(x->buff, &x->index, &etype, &esize);
switch(etype) {
case ERL_SMALL_INTEGER_EXT:
case ERL_INTEGER_EXT:
case ERL_SMALL_BIG_EXT:
case ERL_LARGE_BIG_EXT:
ei_decode_longlong(x->buff, &x->index, &num);
return PyLong_FromLong(num);
case ERL_FLOAT_EXT:
ei_decode_double(x->buff, &x->index, &fnum);
return PyFloat_FromDouble(fnum);
case ERL_STRING_EXT:
atom = uwsgi_malloc(esize+1);
ei_decode_string(x->buff, &x->index, atom);
pobj = PyString_FromString(atom);
free(atom);
return pobj;
case ERL_ATOM_EXT:
atom = uwsgi_malloc(esize+1);
ei_decode_atom(x->buff, &x->index, atom);
pobj = PyUnicode_FromString(atom);
free(atom);
return pobj;
case ERL_SMALL_TUPLE_EXT:
case ERL_LARGE_TUPLE_EXT:
ei_decode_tuple_header(x->buff, &x->index, &arity);
pobj = PyTuple_New(arity);
for(i=0;i<arity;i++) {
zero = erl_to_py(x);
PyTuple_SetItem(pobj, i, zero);
Py_DECREF(zero);
}
return pobj;
case ERL_LIST_EXT:
case ERL_NIL_EXT:
ei_decode_list_header(x->buff, &x->index, &arity);
if (!arity) {
Py_INCREF(Py_None);
return Py_None;
}
pobj = PyList_New(0);
for(i=0;i<arity+1;i++) {
zero = erl_to_py(x);
PyList_Append(pobj, zero);
Py_DECREF(zero);
}
return pobj;
case ERL_BINARY_EXT:
binary = uwsgi_malloc(esize);
ei_decode_binary(x->buff, &x->index, binary, &bin_size);
pobj = PyString_FromStringAndSize(binary, bin_size);
free(binary);
return pobj;
case ERL_PID_EXT:
ei_decode_pid(x->buff, &x->index, &epid);
pobj = PyTuple_New(3);
PyTuple_SetItem(pobj, 0, PyInt_FromLong(epid.num));
PyTuple_SetItem(pobj, 1, PyInt_FromLong(epid.serial));
PyTuple_SetItem(pobj, 2, PyInt_FromLong(epid.creation));
return pobj;
default:
ei_skip_term(x->buff, &x->index);
Py_INCREF(Py_None);
return Py_None;
}
Py_INCREF(Py_None);
return Py_None;
}
PyObject *pyerl_sr(PyObject * self, PyObject * args) {
PyObject *node;
char *reg;
char *cnode;
PyObject *pobj;
ei_x_buff x;
int fd;
int close_fd = 0;
erlang_msg em;
int eversion;
PyObject *res;
if (!PyArg_ParseTuple(args, "ssO:erlang_simple_send", &node, &reg, &pobj)) {
if (!PyArg_ParseTuple(args, "OsO:erlang_sr", &node, &reg, &pobj)) {
return NULL;
}
fd = ei_connect(pyerl_cnode, node);
if (PyString_Check(node)) {
cnode = PyString_AsString(node);
fd = ei_connect(pyerl_cnode, cnode);
close_fd = 1;
}
else if (PyInt_Check(node)) {
fd = PyInt_AsLong(node);
}
else {
return PyErr_Format(PyExc_ValueError, "invalid erlang node/descriptor");
}
if (fd < 0) {
return PyErr_Format(PyExc_ValueError, "Unable to connect to erlang node %s", node);
return PyErr_Format(PyExc_ValueError, "Unable to connect to erlang node");
}
ei_x_new_with_version(&x);
if (py_to_erl(pobj, &x) < 0) {
ei_x_free(&x);
if (close_fd) close(fd);
return PyErr_Format(PyExc_ValueError, "Unsupported object in Python->Erlang translation");
}
ei_reg_send(pyerl_cnode, fd, reg, x.buff, x.index);
close(fd);
ei_x_free(&x);
ei_x_new(&x);
if (ei_xreceive_msg(fd, &em, &x) == ERL_MSG) {
x.index = 0;
ei_decode_version(x.buff, &x.index, &eversion);
res = erl_to_py(&x);
ei_x_free(&x);
if (close_fd) close(fd);
return res;
}
ei_x_free(&x);
if (close_fd) close(fd);
Py_INCREF(Py_None);
return Py_None;
}
PyObject *pyerl_rpc(PyObject * self, PyObject * args) {
PyObject *node;
char *mod, *fun;
char *cnode;
PyObject *pobj;
ei_x_buff x;
ei_x_buff xr;
int fd;
int close_fd = 0;
int eversion;
PyObject *res;
if (!PyArg_ParseTuple(args, "OssO:erlang_rpc", &node, &mod, &fun, &pobj)) {
return NULL;
}
if (PyString_Check(node)) {
cnode = PyString_AsString(node);
fd = ei_connect(pyerl_cnode, cnode);
close_fd = 1;
}
else if (PyInt_Check(node)) {
fd = PyInt_AsLong(node);
}
else {
return PyErr_Format(PyExc_ValueError, "Invalid erlang node/descriptor");
}
if (fd < 0) {
return PyErr_Format(PyExc_ValueError, "Unable to connect to erlang node");
}
ei_x_new(&x);
if (py_to_erl(pobj, &x) < 0) {
ei_x_free(&x);
if (close_fd) close(fd);
return PyErr_Format(PyExc_ValueError, "Unsupported object in Python->Erlang translation");
}
ei_x_new(&xr);
if (ei_rpc(pyerl_cnode, fd, mod, fun, x.buff, x.index, &xr) < 0) {
if (close_fd) close(fd);
ei_x_free(&x);
ei_x_free(&xr);
return PyErr_Format(PyExc_ValueError, "Error in Erlang rpc");
}
xr.index = 0;
ei_decode_version(xr.buff, &xr.index, &eversion);
res = erl_to_py(&xr);
if (close_fd) close(fd);
ei_x_free(&x);
ei_x_free(&xr);
return res;
}
static PyMethodDef uwsgi_pyerl_methods[] = {
{"erlang_connect", pyerl_connect, METH_VARARGS, ""},
{"erlang_simple_send", pyerl_simple_send, METH_VARARGS, ""},
//{"erlang_send_message", pyerl_send, METH_VARARGS, ""},
//{"erlang_recv_message", pyerl_recv, METH_VARARGS, ""},
{"erlang_sr", pyerl_sr, METH_VARARGS, ""},
{"erlang_rpc", pyerl_rpc, METH_VARARGS, ""},
{NULL, NULL},
};
@@ -62,6 +240,8 @@ void py_erl_init_functions() {
PyMethodDef *uwsgi_function;
PyDict_SetItemString(up.embedded_dict, "erlang_node", PyString_FromString(ei_thisnodename(pyerl_cnode)));
for (uwsgi_function = uwsgi_pyerl_methods; uwsgi_function->ml_name != NULL; uwsgi_function++) {
PyObject *func = PyCFunction_New(uwsgi_function, NULL);
PyDict_SetItemString(up.embedded_dict, uwsgi_function->ml_name, func);
@@ -80,6 +260,9 @@ int py_to_erl(PyObject *pobj, ei_x_buff *x) {
else if (PyString_Check(pobj)) {
ei_x_encode_string(x, PyString_AsString(pobj));
}
else if (PyUnicode_Check(pobj)) {
ei_x_encode_atom(x, PyString_AsString(pobj));
}
else if (PyInt_Check(pobj)) {
ei_x_encode_long(x, PyInt_AsLong(pobj));
}
+10 -3
View File
@@ -83,14 +83,21 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
PyDict_SetItemString(up.embedded_dict, "env", wsgi_req->async_environ);
}
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", PyString_FromString(UWSGI_VERSION));
zero = PyString_FromString(UWSGI_VERSION);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", zero);
Py_DECREF(zero);
if (uwsgi.cores > 1) {
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", PyInt_FromLong(wsgi_req->async_id));
}
if (uwsgi.cluster_fd >= 0) {
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster", PyString_FromString(uwsgi.cluster));
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster_node", PyString_FromString(uwsgi.hostname));
zero = PyString_FromString(uwsgi.cluster);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster", zero);
Py_DECREF(zero);
zero = PyString_FromString(uwsgi.hostname);
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster_node", zero);
Py_DECREF(zero);
}
+12 -8
View File
@@ -1256,6 +1256,17 @@ char *uwsgi_cheap_string(char *buf, int len) {
return buf-1;
}
char *uwsgi_resolve_ip(char *domain) {
struct hostent *he;
he = gethostbyname(domain);
if (!he || !*he->h_addr_list || he->h_addrtype != AF_INET) {
return NULL;
}
return inet_ntoa( *( struct in_addr*) he->h_addr_list[0]);
}
char *uwsgi_open_and_read(char *url, int *size, int add_zero, char *magic_table[]) {
@@ -1267,7 +1278,6 @@ char *uwsgi_open_and_read(char *url, int *size, int add_zero, char *magic_table[
char *uri, *colon;
char *domain ;
char *ip ;
struct hostent *he;
int body = 0;
char *magic_buf;
@@ -1289,13 +1299,7 @@ char *uwsgi_open_and_read(char *url, int *size, int add_zero, char *magic_table[
}
he = gethostbyname(domain);
if (!he || !*he->h_addr_list || he->h_addrtype != AF_INET) {
uwsgi_log("unable to resolve address %s\n", domain);
exit(1);
}
ip = inet_ntoa( *( struct in_addr*) he->h_addr_list[0]);
ip = uwsgi_resolve_ip(domain);
if (!ip) {
uwsgi_log("unable to resolve address %s\n", domain);
exit(1);
+2
View File
@@ -1416,3 +1416,5 @@ int uwsgi_simple_send_string(char *, uint8_t, uint8_t, char *, uint16_t, int);
int is_unix(char *, int);
int is_a_number(char *);
char *uwsgi_resolve_ip(char *);