static int lua_mysqld_column_get(lua_State *L) { network_mysqld_column *col = *(network_mysqld_column **)luaL_checkself(L); gsize keysize = 0; const char *key = luaL_checklstring(L, 2, &keysize); LUA_UDATA_EXPORT_CSTR(col, name); LUA_UDATA_EXPORT_CSTR(col, org_name); if (strleq(C("type"), key, keysize)) { lua_pushstring(L, network_mysqld_column_get_typestring(col)); return 1; } if (strleq(C("is_nullable"), key, keysize)) { lua_pushboolean(L, (col->flags & NOT_NULL_FLAG) ? 0 : 1); return 1; } if (strleq(C("length"), key, keysize)) { lua_pushinteger(L, col->max_length); return 1; } return 0; }
/* * FIXME: 1) remove _set_address, make this function callable with result of same * 2) differentiate between reasons for "we didn't add" (now -1 in all cases) */ int network_backends_add(network_backends_t *bs, /* const */ gchar *address, backend_type_t type) { network_backend_t *new_backend; guint i; new_backend = network_backend_new(); new_backend->type = type; if (0 != network_address_set_address(new_backend->addr, address)) { network_backend_free(new_backend); return -1; } /* check if this backend is already known */ g_mutex_lock(bs->backends_mutex); for (i = 0; i < bs->backends->len; i++) { network_backend_t *old_backend = bs->backends->pdata[i]; if (strleq(S(old_backend->addr->name), S(new_backend->addr->name))) { network_backend_free(new_backend); g_mutex_unlock(bs->backends_mutex); g_critical("backend %s is already known!", address); return -1; } } g_ptr_array_add(bs->backends, new_backend); g_mutex_unlock(bs->backends_mutex); g_message("added %s backend: %s", (type == BACKEND_TYPE_RW) ? "read/write" : "read-only", address); return 0; }
/** * set proxy.global.backends.addslave * * add slave server into mysql backends * * @return nil or the backend */ static int proxy_backends_set(lua_State *L) { network_backends_t *bs = *(network_backends_t **)luaL_checkself(L); gsize keysize = 0; const char *key = luaL_checklstring(L, 2, &keysize); if (strleq(key, keysize, C("addslave"))) { network_backends_add(bs, g_strdup(lua_tostring(L, -1)), BACKEND_TYPE_RO); } else if (strleq(key, keysize, C("addmaster"))) { network_backends_add(bs, g_strdup(lua_tostring(L, -1)), BACKEND_TYPE_RW); } else if (strleq(key, keysize, C("removebackend"))) { network_backends_remove(bs, lua_tointeger(L, -1)); } else { return luaL_error(L, "proxy.global.backends.%s is not writable", key); } return 1; }
int proxy_user_password_get(lua_State *L) { user_password *user_pwd = *(user_password **)luaL_checkself(L); gsize keysize = 0; const char *key = luaL_checklstring(L, 2, &keysize); if (strleq(key, keysize, C("user"))) { lua_pushlstring(L, user_pwd->user, strlen(user_pwd->user)); } else if (strleq(key, keysize, C("pwd"))) { char* enpwds = pwds_encrypt(user_pwd->pwd); lua_pushlstring(L, enpwds, strlen(enpwds)); g_free(enpwds); } else { lua_pushnil(L); } return 1; }
/* * FIXME: 1) remove _set_address, make this function callable with result of same * 2) differentiate between reasons for "we didn't add" (now -1 in all cases) */ int network_backends_add(network_backends_t *bs, /* const */ gchar *address, backend_type_t type) { network_backend_t *new_backend; guint i; new_backend = network_backend_new(bs->event_thread_count); new_backend->type = type; gchar *p = NULL; if (type == BACKEND_TYPE_RO) { guint weight = 1; p = strrchr(address, '@'); if (p != NULL) { *p = '\0'; weight = atoi(p+1); } new_backend->weight = weight; } if (0 != network_address_set_address(new_backend->addr, address)) { network_backend_free(new_backend); return -1; } /* check if this backend is already known */ g_mutex_lock(bs->backends_mutex); /*remove lock*/ gint first_slave = -1; for (i = 0; i < bs->backends->len; i++) { network_backend_t *old_backend = bs->backends->pdata[i]; if (first_slave == -1 && old_backend->type == BACKEND_TYPE_RO) first_slave = i; if (old_backend->type == type && strleq(S(old_backend->addr->name), S(new_backend->addr->name))) { network_backend_free(new_backend); g_mutex_unlock(bs->backends_mutex); /*remove lock*/ g_critical("backend %s is already known!", address); return -1; } } g_ptr_array_add(bs->backends, new_backend); if (first_slave != -1 && type == BACKEND_TYPE_RW) { network_backend_t *temp_backend = bs->backends->pdata[first_slave]; bs->backends->pdata[first_slave] = bs->backends->pdata[bs->backends->len - 1]; bs->backends->pdata[bs->backends->len - 1] = temp_backend; } g_mutex_unlock(bs->backends_mutex); /*remove lock*/ g_message("added %s backend: %s", (type == BACKEND_TYPE_RW) ? "read/write" : "read-only", address); if (p != NULL) *p = '@'; return 0; }
static int proxy_resultset_field_get(lua_State *L) { MYSQL_FIELD *field = *(MYSQL_FIELD **)luaL_checkself(L); gsize keysize = 0; const char *key = luaL_checklstring(L, 2, &keysize); if (strleq(key, keysize, C("type"))) { lua_pushinteger(L, field->type); } else if (strleq(key, keysize, C("name"))) { lua_pushstring(L, field->name); } else if (strleq(key, keysize, C("org_name"))) { lua_pushstring(L, field->org_name); } else if (strleq(key, keysize, C("org_table"))) { lua_pushstring(L, field->org_table); } else if (strleq(key, keysize, C("table"))) { lua_pushstring(L, field->table); } else { lua_pushnil(L); } return 1; }
/** * get the info about a backend * * proxy.backend[0]. * connected_clients => clients using this backend * address => ip:port or unix-path of to the backend * state => int(BACKEND_STATE_UP|BACKEND_STATE_DOWN) * type => int(BACKEND_TYPE_RW|BACKEND_TYPE_RO) * * @return nil or requested information * @see backend_state_t backend_type_t */ static int proxy_backend_get(lua_State *L) { network_backend_t *backend = *(network_backend_t **)luaL_checkself(L); gsize keysize = 0; const char *key = luaL_checklstring(L, 2, &keysize); if (strleq(key, keysize, C("connected_clients"))) { lua_pushinteger(L, backend->connected_clients); } else if (strleq(key, keysize, C("dst"))) { network_address_lua_push(L, backend->addr); } else if (strleq(key, keysize, C("state"))) { lua_pushinteger(L, backend->state); } else if (strleq(key, keysize, C("type"))) { lua_pushinteger(L, backend->type); } else if (strleq(key, keysize, C("uuid"))) { if (backend->uuid->len) { lua_pushlstring(L, S(backend->uuid)); } else { lua_pushnil(L); } } else if (strleq(key, keysize, C("weight"))) { lua_pushinteger(L, backend->weight); } else { lua_pushnil(L); } return 1; }
static int proxy_tokenize_token_get(lua_State *L) { sql_token *token = *(sql_token **)luaL_checkself(L); size_t keysize; const char *key = luaL_checklstring(L, 2, &keysize); if (strleq(key, keysize, C("text"))) { lua_pushlstring(L, S(token->text)); return 1; } else if (strleq(key, keysize, C("token_id"))) { lua_pushinteger(L, token->token_id); return 1; } else if (strleq(key, keysize, C("token_name"))) { size_t token_name_len; const char *token_name = sql_token_get_name(token->token_id, &token_name_len); lua_pushlstring(L, token_name, token_name_len); return 1; } else { luaL_error(L, "tokens[...] has no %s field", key); } return 0; }
static int proxy_backend_set(lua_State *L) { network_backend_t *backend = *(network_backend_t **)luaL_checkself(L); gsize keysize = 0; const char *key = luaL_checklstring(L, 2, &keysize); if (strleq(key, keysize, C("state"))) { backend->state = lua_tointeger(L, -1); } else if (strleq(key, keysize, C("uuid"))) { if (lua_isstring(L, -1)) { size_t s_len = 0; const char *s = lua_tolstring(L, -1, &s_len); g_string_assign_len(backend->uuid, s, s_len); } else if (lua_isnil(L, -1)) { g_string_truncate(backend->uuid, 0); } else { return luaL_error(L, "proxy.global.backends[...].%s has to be a string", key); } } else { return luaL_error(L, "proxy.global.backends[...].%s is not writable", key); } return 1; }
static int lua_mysqld_table_get(lua_State *L) { network_mysqld_table *tbl = *(network_mysqld_table **)luaL_checkself(L); gsize keysize = 0; const char *key = luaL_checklstring(L, 2, &keysize); LUA_UDATA_EXPORT_STR(tbl, db_name); LUA_UDATA_EXPORT_STR(tbl, table_name); if (strleq(C("columns"), key, keysize)) { /* columns is a array */ return lua_mysqld_columns_push(L, tbl->columns); } return 0; }
static int proxy_backends_set(lua_State *L) { network_backends_t *bs = *(network_backends_t **)luaL_checkself(L); gsize keysize = 0; const char *key = luaL_checklstring(L, 2, &keysize); if (strleq(key, keysize, C("addslave"))) { network_backends_add(bs, g_strdup(lua_tostring(L, -1)), BACKEND_TYPE_RO); } else if (strleq(key, keysize, C("addmaster"))) { network_backends_add(bs, g_strdup(lua_tostring(L, -1)), BACKEND_TYPE_RW); } else if (strleq(key, keysize, C("changemaster"))) { //change_standby_to_master(bs); GThread* t = g_thread_new("change_master_thread", change_master_thread_func, srv); // g_thread_join(t); } else if (strleq(key, keysize, C("addstandby"))) { network_backends_add(bs, g_strdup(lua_tostring(L, -1)), BACKEND_TYPE_SY); } else if (strleq(key, keysize, C("removebackend"))) { network_backends_remove(bs, lua_tointeger(L, -1)); } else if (strleq(key, keysize, C("addpwds"))) { gchar* pwds = g_strdup(lua_tostring(L, -1)); network_backends_add_pwds(srv, pwds); g_free(pwds); } else if (strleq(key, keysize, C("addenpwds"))) { gchar* enpwds = convert_pwds(lua_tostring(L, -1)); network_backends_add_pwds(srv, enpwds); g_free(enpwds); } else if (strleq(key, keysize, C("removepwds"))) { gchar* users = g_strdup(lua_tostring(L, -1)); network_backends_remove_pwds(srv, users); g_free(users); } else if (strleq(key, keysize, C("saveconfig"))) { network_save_config(srv); } else { return luaL_error(L, "proxy.global.backends.%s is not writable", key); } return 1; }
/** * compare two GStrings for case-insensitive equality using UTF8 */ gboolean g_string_equal_ci(const GString *a, const GString *b) { char *a_ci, *b_ci; gsize a_ci_len, b_ci_len; gboolean is_equal = FALSE; if (g_string_equal(a, b)) return TRUE; a_ci = g_utf8_casefold(S(a)); a_ci_len = strlen(a_ci); b_ci = g_utf8_casefold(S(b)); b_ci_len = strlen(b_ci); is_equal = strleq(a_ci, a_ci_len, b_ci, b_ci_len); g_free(a_ci); g_free(b_ci); return is_equal; }
static int proxy_injection_get(lua_State *L) { injection *inj = *(injection **)luaL_checkself(L); gsize keysize = 0; const char *key = luaL_checklstring(L, 2, &keysize); if (strleq(key, keysize, C("type"))) { lua_pushinteger(L, inj->id); /** DEPRECATED: use "inj.id" instead */ } else if (strleq(key, keysize, C("id"))) { lua_pushinteger(L, inj->id); } else if (strleq(key, keysize, C("query"))) { lua_pushlstring(L, inj->query->str, inj->query->len); } else if (strleq(key, keysize, C("query_time"))) { lua_pushinteger(L, chassis_calc_rel_microseconds(inj->ts_read_query, inj->ts_read_query_result_first)); } else if (strleq(key, keysize, C("response_time"))) { lua_pushinteger(L, chassis_calc_rel_microseconds(inj->ts_read_query, inj->ts_read_query_result_last)); } else if (strleq(key, keysize, C("resultset"))) { /* fields, rows */ proxy_resultset_t *res; res = proxy_resultset_new(); /* only expose the resultset if really needed FIXME: if the resultset is encoded in binary form, we can't provide it either. */ if (inj->resultset_is_needed && !inj->qstat.binary_encoded) { res->result_queue = inj->result_queue; } res->qstat = inj->qstat; res->rows = inj->rows; res->bytes = inj->bytes; proxy_resultset_lua_push(L, res); } else { g_message("%s.%d: inj[%s] ... not found", __FILE__, __LINE__, key); lua_pushnil(L); } return 1; }
static int proxy_resultset_get(lua_State *L) { GRef *ref = *(GRef **)luaL_checkself(L); proxy_resultset_t *res = ref->udata; gsize keysize = 0; const char *key = luaL_checklstring(L, 2, &keysize); if (strleq(key, keysize, C("fields"))) { if (!res->result_queue) { luaL_error(L, ".resultset.fields isn't available if 'resultset_is_needed ~= true'"); } else { if (0 != parse_resultset_fields(res)) { /* failed */ } if (res->fields) { proxy_resultset_fields_lua_push_ref(L, ref); } else { lua_pushnil(L); } } } else if (strleq(key, keysize, C("rows"))) { if (!res->result_queue) { luaL_error(L, ".resultset.rows isn't available if 'resultset_is_needed ~= true'"); } else if (res->qstat.binary_encoded) { luaL_error(L, ".resultset.rows isn't available for prepared statements"); } else { parse_resultset_fields(res); /* set up the ->rows_chunk_head pointer */ if (res->rows_chunk_head) { res->row = res->rows_chunk_head; proxy_resultset_lua_push_ref(L, ref); lua_pushcclosure(L, proxy_resultset_rows_iter, 1); } else { lua_pushnil(L); } } } else if (strleq(key, keysize, C("row_count"))) { lua_pushinteger(L, res->rows); } else if (strleq(key, keysize, C("bytes"))) { lua_pushinteger(L, res->bytes); } else if (strleq(key, keysize, C("raw"))) { if (!res->result_queue) { luaL_error(L, ".resultset.raw isn't available if 'resultset_is_needed ~= true'"); } else { GString *s; s = res->result_queue->head->data; lua_pushlstring(L, s->str + 4, s->len - 4); /* skip the network-header */ } } else if (strleq(key, keysize, C("flags"))) { lua_newtable(L); lua_pushboolean(L, (res->qstat.server_status & SERVER_STATUS_IN_TRANS) != 0); lua_setfield(L, -2, "in_trans"); lua_pushboolean(L, (res->qstat.server_status & SERVER_STATUS_AUTOCOMMIT) != 0); lua_setfield(L, -2, "auto_commit"); lua_pushboolean(L, (res->qstat.server_status & SERVER_QUERY_NO_GOOD_INDEX_USED) != 0); lua_setfield(L, -2, "no_good_index_used"); lua_pushboolean(L, (res->qstat.server_status & SERVER_QUERY_NO_INDEX_USED) != 0); lua_setfield(L, -2, "no_index_used"); } else if (strleq(key, keysize, C("warning_count"))) { lua_pushinteger(L, res->qstat.warning_count); } else if (strleq(key, keysize, C("affected_rows"))) { /** * if the query had a result-set (SELECT, ...) * affected_rows and insert_id are not valid */ if (res->qstat.was_resultset) { lua_pushnil(L); } else { lua_pushnumber(L, res->qstat.affected_rows); } } else if (strleq(key, keysize, C("insert_id"))) { if (res->qstat.was_resultset) { lua_pushnil(L); } else { lua_pushnumber(L, res->qstat.insert_id); } } else if (strleq(key, keysize, C("query_status"))) { /* hmm, is there another way to figure out if this is a 'resultset' ? * one that doesn't require the parse the meta-data */ if (res->qstat.query_status == MYSQLD_PACKET_NULL) { lua_pushnil(L); } else { lua_pushinteger(L, res->qstat.query_status); } } else { lua_pushnil(L); } return 1; }
static int proxy_socket_get(lua_State *L) { network_socket *sock = *(network_socket **)luaL_checkself(L); gsize keysize = 0; const char *key = luaL_checklstring(L, 2, &keysize); /** * we to split it in .client and .server here */ if (strleq(key, keysize, C("default_db"))) { lua_pushlstring(L, sock->conn_attr.default_db->str, sock->conn_attr.default_db->len); return 1; }else if (strleq(key, keysize, C("charset_client"))) { lua_pushlstring(L, sock->conn_attr.charset_client->str, sock->conn_attr.charset_client->len); return 1; }else if (strleq(key, keysize, C("charset_connection"))) { lua_pushlstring(L, sock->conn_attr.charset_connection->str, sock->conn_attr.charset_connection->len); return 1; }else if (strleq(key, keysize, C("charset_results"))) { lua_pushlstring(L, sock->conn_attr.charset_results->str, sock->conn_attr.charset_results->len); return 1; }else if (strleq(key, keysize, C("address"))) { return luaL_error(L, ".address is deprecated. Use .src.name or .dst.name instead"); } else if (strleq(key, keysize, C("src"))) { return network_address_lua_push(L, sock->src); } else if (strleq(key, keysize, C("dst"))) { return network_address_lua_push(L, sock->dst); } if (sock->response) { if (strleq(key, keysize, C("username"))) { lua_pushlstring(L, S(sock->response->username)); return 1; } else if (strleq(key, keysize, C("scrambled_password"))) { lua_pushlstring(L, S(sock->response->response)); return 1; } } if (sock->challenge) { /* only the server-side has mysqld_version set */ if (strleq(key, keysize, C("mysqld_version"))) { lua_pushinteger(L, sock->challenge->server_version); return 1; } else if (strleq(key, keysize, C("thread_id"))) { lua_pushinteger(L, sock->challenge->thread_id); return 1; } else if (strleq(key, keysize, C("scramble_buffer"))) { lua_pushlstring(L, S(sock->challenge->challenge)); return 1; } } g_critical("%s: sock->challenge: %p, sock->response: %p (looking for %s)", G_STRLOC, (void *)sock->challenge, (void *)sock->response, key ); lua_pushnil(L); return 1; }