void network_conn_available_handle(int G_GNUC_UNUSED event_fd, short G_GNUC_UNUSED events, void* user_data) { int err = 0; char ping[1]; network_mysqld_con_lua_t *st; injection *inj; GString *packet; chassis *chas = user_data; guint index = chassis_event_thread_index_get(); chassis_event_thread_t *thread = g_ptr_array_index(chas->threads, index); if (read(thread->con_read_fd, ping, 1) != 1) g_message("%s:pipes - read error,error message:%s", G_STRLOC, g_strerror(errno)); network_mysqld_con *con = g_queue_pop_head(thread->block_con_queue); if(con == NULL) return; network_socket* sock = network_connection_pool_lua_swap(con, con->backend_ndx, 0, &err); if(sock == NULL) { g_queue_push_tail(thread->block_con_queue, con); return; } con->server = sock; st = con->plugin_con_state; inj = g_queue_peek_head(st->injected.queries); con->resultset_is_needed = inj->resultset_is_needed; /* let the lua-layer decide if we want to buffer the result or not */ network_mysqld_queue_reset(con->server); network_mysqld_queue_append(con->server, con->server->send_queue, S(inj->query)); while ((packet = g_queue_pop_head(con->client->recv_queue->chunks))) g_string_free(packet, TRUE); con->state = CON_STATE_SEND_QUERY; network_mysqld_con_reset_command_response_state(con); network_mysqld_con_handle(-1, 0, con); }
/** * Handle the proxy.response to con. * proxy.response * .type can be either ERR, OK or RAW * .resultset (in case of OK) * .fields * .rows * .errmsg (in case of ERR) * .packet (in case of nil) * Note: if error occurred, should set the error string. */ int network_mysqld_con_python_handle_proxy_response(network_mysqld_con *con, PyObject *proxy){ assert(proxy); PyObject *response = PyObject_GetAttrString(proxy, "response"); //Note: the response is fetched through the tp_getset, and is a new reference. assert(response); Py_DECREF(response); PyObject *res_type = PyObject_GetAttrString(response, "type"); if(!res_type){ network_mysqld_con_send_error(con->client, C("Cannot get proxy.response.type")); return -1; } int res_type_int = PyInt_AsLong(res_type); Py_DECREF(res_type); switch(res_type_int){ case MYSQLD_PACKET_OK:{ PyObject *resultset = PyObject_GetAttrString(response, "resultset"); if(!resultset){ PyErr_Clear(); guint64 affected_rows = 0; guint64 insert_id = 0; PyObject *ar = PyObject_GetAttrString(response, "affected_rows"); if(!ar) PyErr_Clear(); else if(PyLong_Check(ar)) affected_rows = PyLong_AsLong(ar); else if(PyInt_Check(ar)) affected_rows = PyInt_AsLong(ar); Py_XDECREF(ar); PyObject *ii = PyObject_GetAttrString(response, "insert_id"); if(!ii) PyErr_Clear(); else if(PyLong_Check(ii)) insert_id = PyLong_AsLong(ii); else if(PyInt_Check(ii)) insert_id = PyInt_AsLong(ii); Py_XDECREF(ii); network_mysqld_con_send_ok_full(con->client, affected_rows, insert_id, 0x0002, 0); } else{ Py_DECREF(resultset); GPtrArray *fields = create_fields(resultset); if(!fields){ network_mysqld_con_send_error(con->client, C("Cannot get proxy.response.resultset.fields!")); PyErr_Print(); PyErr_Clear(); return -1; } if(fields->len <= 0){ network_mysqld_con_send_error(con->client, C("Size of proxy.response.resultset.fields is 0")); network_mysqld_proto_fielddefs_free(fields); return -1; } GPtrArray *rows = create_rows(resultset); if(!rows){ network_mysqld_con_send_error(con->client, C("Cannot get proxy.response.resultset.rows")); PyErr_Print(); network_mysqld_proto_fielddefs_free(fields); return -1; } network_mysqld_con_send_resultset(con->client, fields, rows); if (fields) { network_mysqld_proto_fielddefs_free(fields); fields = NULL; } if (rows) { guint i; for (i = 0; i < rows->len; i++) { GPtrArray *row = rows->pdata[i]; guint j; for (j = 0; j < row->len; j++) if (row->pdata[j]) g_free(row->pdata[j]); g_ptr_array_free(row, TRUE); } g_ptr_array_free(rows, TRUE); rows = NULL; } } break;} case MYSQLD_PACKET_ERR:{ gint errcode = ER_UNKNOWN_ERROR; /** let's call ourself Dynamic SQL ... 07000 is "dynamic SQL error" */ const gchar *sqlstate = "07000"; gchar *errmsg = NULL; PyObject *err_code = PyObject_GetAttrString(response, "errcode"); if(!err_code) //Here use the default error code: ER_UNKNOWN_ERROR PyErr_Clear(); else{ errcode = PyInt_AsLong(err_code); Py_DECREF(err_code); } PyObject *sql_state = PyObject_GetAttrString(response, "sqlstate"); if(!sql_state) //Here use the default sql state: 07000 PyErr_Clear(); else{ sqlstate = PyString_AsString(sql_state); Py_DECREF(sql_state); } PyObject *err_msg = PyObject_GetAttrString(response, "errmsg"); if(!err_msg){ PyErr_Clear(); network_mysqld_con_send_error(con->client, C("(python) proxy.response.errmsg is nil")); } else{ errmsg = PyString_AsString(err_msg); Py_DECREF(err_msg); network_mysqld_con_send_error_full(con->client, errmsg, strlen(errmsg), errcode, sqlstate); } break;} case MYSQLD_PACKET_RAW:{ PyObject *packets = PyObject_GetAttrString(response, "packets"); if(!packets) goto queue_reset; int i; for(i = 0; i < PySequence_Size(packets); i++){ PyObject *item = PySequence_GetItem(packets, i); //If invalid items doesn't influces valid ones before them. if(!item) goto queue_reset; if(!PyString_Check(item)){ PyErr_SetString(PyExc_ValueError, "proxy.response.packets' " "items should be strings."); Py_DECREF(item); Py_DECREF(packets); goto queue_reset; } network_mysqld_queue_append(con->client, con->client->send_queue, PyString_AsString(item), PyString_Size(item)); Py_DECREF(item); } Py_DECREF(packets); queue_reset: /* reset the packet-id checks */ network_mysqld_queue_reset(con->client); break;} default: g_critical("Now the response type is unknown: %d", res_type_int); return -1; } return 0; }