Exemple #1
0
/**
 * This is the main command execution function. The function contains
 * all the necessary logic to detect reset or disconnected database
 * connections and uploads commands to the server if necessary.
 * @param cmd Command to be executed
 * @return    0 if OK, <0 on MySQL failure, >0 on DB API failure
 */
static int exec_cmd_safe(db_cmd_t* cmd)
{
    int i, err;
    db_con_t* con;
    struct my_cmd* mcmd;
    struct my_con* mcon;
	
    /* First things first: retrieve connection info
     * from the currently active connection and also
     * mysql payload from the database command
     */
    mcmd = DB_GET_PAYLOAD(cmd);
    con = cmd->ctx->con[db_payload_idx];
    mcon = DB_GET_PAYLOAD(con);
    
    for(i = 0; i <= my_retries; i++) {
	if ((mcon->flags & MY_CONNECTED) == 0) {
	    /* The connection is disconnected, try to reconnect */
	    if (my_con_connect(con)) {
		INFO("mysql: exec_cmd_safe failed to re-connect\n");
		continue;
	    }
	}	
	
	/* Next check the number of resets in the database connection, if this
	 * number is higher than the number we keep in my_cmd structure in
	 * last_reset variable then the connection was reset and we need to
	 * upload the command again to the server before executing it, because
	 * the server recycles all server side information upon disconnect.
	 */
	if (mcon->resets > mcmd->last_reset) {
	    INFO("mysql: Connection reset detected, uploading command to server\n");
	    err = upload_cmd(cmd);
	    if (err < 0) {
		INFO("mysql: Error while uploading command\n");
		continue;
	    } else if (err > 0) {
		/* DB API error, this is a serious problem such as memory
		 * allocation failure, bail out
		 */
		return 1;
	    }
	}
	
	set_mysql_params(cmd);
	err = mysql_stmt_execute(mcmd->st);
	if (err == 0) {
	    /* The command was executed successfully, now fetch all data to
	     * the client if it was requested by the user */
	    if (mcmd->flags & MY_FETCH_ALL) {
		err = mysql_stmt_store_result(mcmd->st);
		if (err) {
		    INFO("mysql: Error while fetching data to client.\n");
		    goto error;
		}
	    }
	    return 0;
	}
	
    error:
	/* Command execution failed, log a message and try to reconnect */
	INFO("mysql: libmysql: %d, %s\n", mysql_stmt_errno(mcmd->st),
	     mysql_stmt_error(mcmd->st));
	INFO("mysql: Error while executing command on server, trying to reconnect\n");

	my_con_disconnect(con);
	if (my_con_connect(con)) {
	    INFO("mysql: Failed to reconnect server\n");
	} else {
	    INFO("mysql: Successfully reconnected server\n");
	}
    }
    
    INFO("mysql: Failed to execute command, giving up\n");
    return -1;
}
Exemple #2
0
int pg_cmd(db_cmd_t* cmd)
{
	struct pg_cmd* pcmd;
 
	pcmd = (struct pg_cmd*)pkg_malloc(sizeof(struct pg_cmd));
	if (pcmd == NULL) {
		ERR("postgres: No memory left\n");
		goto error;
	}
	memset(pcmd, '\0', sizeof(struct pg_cmd));
	if (db_drv_init(&pcmd->gen, pg_cmd_free) < 0) goto error;

	switch(cmd->type) {
	case DB_PUT:
		if (build_insert_sql(&pcmd->sql_cmd, cmd) < 0) goto error;
		break;
		
	case DB_DEL:
		if (build_delete_sql(&pcmd->sql_cmd, cmd) < 0) goto error;
		break;

	case DB_GET:
		if (build_select_sql(&pcmd->sql_cmd, cmd) < 0) goto error;
		break;

	case DB_UPD:
		if (build_update_sql(&pcmd->sql_cmd, cmd) < 0) goto error;
		break;
		
	case DB_SQL:
		pcmd->sql_cmd.s = (char*)pkg_malloc(cmd->table.len + 1);
		if (pcmd->sql_cmd.s == NULL) {
			ERR("postgres: Out of private memory\n");
			goto error;
		}
		memcpy(pcmd->sql_cmd.s,cmd->table.s, cmd->table.len);
		pcmd->sql_cmd.s[cmd->table.len] = '\0';
		pcmd->sql_cmd.len = cmd->table.len;
        break;
	}

	DB_SET_PAYLOAD(cmd, pcmd);

	/* Create parameter arrays for PostgreSQL API functions */
	if (create_pg_params(cmd) < 0) goto error;	

	/* Generate a unique name for the command on the server */
	if (gen_cmd_name(cmd) != 0) goto error; 

	/* Upload the command to the server */
	if (upload_cmd(cmd) != 0) goto error;

	/* Obtain the description of the uploaded command, this includes
	 * information about result and parameter fields */
	if (get_types(cmd) != 0) goto error;

	/* Update fields based on the information retrieved from the */
	if (pg_resolve_param_oids(cmd->vals, cmd->match,
							  cmd->vals_count, cmd->match_count,
							  pcmd->types)) 
		goto error;
	if (pg_resolve_result_oids(cmd->result, cmd->result_count, pcmd->types)) 
		goto error;

	if (check_types(cmd)) goto error;

	return 0;

 error:
	if (pcmd) {
		DB_SET_PAYLOAD(cmd, NULL);
		free_pg_params(&pcmd->params);

		if (pcmd->types) PQclear(pcmd->types);
		if (pcmd->name) pkg_free(pcmd->name);
		if (pcmd->sql_cmd.s) pkg_free(pcmd->sql_cmd.s);

		db_drv_free(&pcmd->gen);
		pkg_free(pcmd);
	}
	return -1;
}
Exemple #3
0
int my_cmd(db_cmd_t* cmd)
{
	struct my_cmd* res;
 
	res = (struct my_cmd*)pkg_malloc(sizeof(struct my_cmd));
	if (res == NULL) {
		ERR("mysql: No memory left\n");
		goto error;
	}
	memset(res, '\0', sizeof(struct my_cmd));
	/* Fetch all data to client at once by default */
	res->flags |= MY_FETCH_ALL;
	if (db_drv_init(&res->gen, my_cmd_free) < 0) goto error;

	switch(cmd->type) {
	case DB_PUT:
		if (DB_FLD_EMPTY(cmd->vals)) {
			BUG("mysql: No parameters provided for DB_PUT in context '%.*s'\n", 
				cmd->ctx->id.len, ZSW(cmd->ctx->id.s));
			goto error;
		}
		if (build_replace_cmd(&res->sql_cmd, cmd) < 0) goto error;
		break;

	case DB_DEL:
		if (build_delete_cmd(&res->sql_cmd, cmd) < 0) goto error;
		break;

	case DB_GET:
		if (build_select_cmd(&res->sql_cmd, cmd) < 0) goto error;
		break;

	case DB_UPD:
		if (build_update_cmd(&res->sql_cmd, cmd) < 0) goto error;
		break;

	case DB_SQL:
		res->sql_cmd.s = (char*)pkg_malloc(cmd->table.len);
		if (res->sql_cmd.s == NULL) {
			ERR("mysql: Out of private memory\n");
			goto error;
		}
		memcpy(res->sql_cmd.s,cmd->table.s, cmd->table.len);
		res->sql_cmd.len = cmd->table.len;
        break;
	}

	DB_SET_PAYLOAD(cmd, res);

	/* In order to check all the parameters and results, we need to upload
	 * the command to the server. We need to do that here before we report
	 * back that the command was created successfully. Hence, this
	 * function requires the corresponding connection be established. We
	 * would not be able to check parameters if we don't do that there and
	 * that could result in repeated execution failures at runtime.
	 */
	if (upload_cmd(cmd)) goto error;
	return 0;

 error:
	if (res) {
		DB_SET_PAYLOAD(cmd, NULL);
		db_drv_free(&res->gen);
		if (res->sql_cmd.s) pkg_free(res->sql_cmd.s);
		pkg_free(res);
	}
	return -1;
}