Files @ dd687d0e8de0
Branch filter:

Location: DistRen/src/server/mysql.c

ethanzonca
Auth updates
/*
  Copyright 2009 Nathan Phillip Brink, Ethan Zonca, Matthew Orlando

  This file is a part of DistRen.

  DistRen is free software: you can redistribute it and/or modify
  it under the terms of the GNU Affero General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  DistRen is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU Affero General Public License for more details.

  You should have received a copy of the GNU Affero General Public License
  along with DistRen.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "mysql.h"
#include <mysql/mysql.h>

#include "common/asprintf.h"
#include "common/protocol.h"

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>

/**
   local types
 */

#define SEVENTY_FIVE 75
#define FORTY_TWO 42

/**
   performs mysql query.
   errors will be logged to the user by this function.
   @return pointer to query handle on success, NULL on failure or if expected_columns=0 (no result set expected)
 */
distrend_mysql_result_t mysqlQuery(distrend_mysql_conn_t conn, char *query, MYSQL_FIELD_OFFSET expected_columns);

/**
   frees mysql query result. Accepts a NULL pointer and ignores it to
   help deal with one-shot calls to mysqlQuery so that you don't have to
   check if it returned NULL or not.
   @return 0 on success
 */
int mysqlResultFree(distrend_mysql_conn_t conn, distrend_mysql_result_t result);

/**
   reads an integer mysql field value
   @return 0 on success
*/
int distrend_mysql_getint(MYSQL_ROW row, MYSQL_FIELD_OFFSET column, int32_t *theint)
{
  if(!row[column])
    return 1;

  *theint = atol(row[column]);

  return 0;
}


struct distrend_mysql_conn
{
  MYSQL *mysqlconn;
  short pointlesscheck;
};

struct distrend_mysql_result
{
  MYSQL_RES *mysqlresult;
  short pointlesscheck;
};

/**
    funcs
 */

int mysqlConnect(distrend_mysql_conn_t *conn)
{
  MYSQL *mysqlconn;

  char *server = "zserver1";
  char *user = "distren";
  char *password = "HwLxuBqTvJ6J7FWj";
  char *database = "distren";

  my_bool mybool;

  mysqlconn = mysql_init(NULL);

  if(!mysql_real_connect(mysqlconn, server, user, password, database, 0, NULL, CLIENT_MULTI_STATEMENTS))
    {
      fprintf(stderr, "%s\n", mysql_error(mysqlconn));
      return 1;
    }

  /**
     Called after mysql_real_connect() due to bug fixed in MySQL 5.1.6 and later
  */
  mybool = 1;
  mysql_options(mysqlconn, MYSQL_OPT_RECONNECT, (char *)&mybool);


  *conn = malloc(sizeof(struct distrend_mysql_conn));
  if(!*conn)
    {
      mysql_close(mysqlconn);
      mysql_server_end();
      return 2;
    }
  (*conn)->mysqlconn = mysqlconn;
  (*conn)->pointlesscheck = SEVENTY_FIVE;

  return 0;
}

int mysqlDisconnect(distrend_mysql_conn_t conn)
{
  /**
     check if this handle is valid
   */
  if(conn->pointlesscheck != SEVENTY_FIVE)
    fprintf(stderr, "warning, I was passed a bad struct distrend_mysql_conn...\n");

  /**
     invalidate handle :-D
   */
  conn->pointlesscheck ++;

  mysql_close(conn->mysqlconn);
  mysql_server_end();
  free(conn);

  return 0;
}


distrend_mysql_result_t mysqlQuery(distrend_mysql_conn_t conn, char *query, MYSQL_FIELD_OFFSET expected_columns)
{
  MYSQL_RES *result;
  distrend_mysql_result_t distrenresult;
  MYSQL_FIELD_OFFSET num_columns;

  /**
     pointless sanity check
  */
  if(conn->pointlesscheck != SEVENTY_FIVE)
    fprintf(stderr, "warning, I was passed a bad struct distrend_mysql_conn...\n");

  /** make sure that connection is still alive
   */
  
  if(mysql_ping(conn->mysqlconn))
    {
      fprintf(stderr, "mysql_ping() failed: %s\n", mysql_error(conn->mysqlconn));
      return NULL;
    }

  fprintf(stderr,"Querying... ");
  if (mysql_query(conn->mysqlconn, query))
    {
      fprintf(stderr, "calling mysql_query() resulted in: %s\n", mysql_error(conn->mysqlconn));
      return NULL;
    }
  fprintf(stderr,"Queried!\n");

  fprintf(stderr,"Getting results... ");
  result = mysql_use_result(conn->mysqlconn);
  
  /**
     Flush stuff out when an empty set is expected.
   */
  if(!expected_columns)
    {
      if(result)
	{
	  while(mysql_fetch_row(result))
	    ;
	  mysql_free_result(result);
	}
      return NULL;
    }

  if(!result)
    {
      fprintf(stderr, "expected response/result for query ``%s'', got nothing\n", query);
      return NULL;
    }

  /**
     Sanity check
   */
  num_columns = mysql_num_fields(result);
  if(num_columns != expected_columns)
    {
      fprintf(stderr, "Expected %d columns, got %d for ``%s''\n", expected_columns, num_columns, query);
      
      mysql_free_result(result);
      return NULL;
    }
  fprintf(stderr,"Done!\n");

  /**
     Prepare data for return.
   */
  distrenresult = malloc(sizeof(struct distrend_mysql_result));
  if(!distrenresult)
    {
      while(mysql_fetch_row(result))
	;
        mysql_free_result(result);
      return NULL;
    }

  distrenresult->mysqlresult = result;
  distrenresult->pointlesscheck = FORTY_TWO;

  return distrenresult;
}

int mysqlResultFree(distrend_mysql_conn_t conn, distrend_mysql_result_t result)
{
  size_t counter;
  MYSQL_RES *mysqlresult;

  if(!result)
    {
      fprintf(stderr, "mysqlResultFree(): warning, passed NULL parameter\n");
      return 0;
    }
  
  if(result->pointlesscheck != FORTY_TWO)
    fprintf(stderr, "%s:%d: I didn't get the type of handle I wanted\n", __FILE__, __LINE__);

  mysqlresult = result->mysqlresult;
  free(result);

  /**
     Must flush the resultset buffer.
   */
  for(counter = 0;
      mysql_fetch_row(mysqlresult);
      counter ++)
    ;
  if(counter)
    fprintf(stderr, "Calling function did not flush %d rows\n", (int)counter);

  while(mysql_more_results(conn->mysqlconn))
    {
      fprintf(stderr, "flushing an extraneous result set\n");
      mysql_next_result(conn->mysqlconn);
      mysqlresult = mysql_use_result(conn->mysqlconn);
      if(mysqlresult)
	{
	  while(mysql_fetch_row(mysqlresult))
	    ;
	  mysql_free_result(mysqlresult);
	}
    }

  return 0;
}

/*
   Individual query functions:
 */

void finish_frame(distrend_mysql_conn_t conn, int32_t slavekey, int32_t jobkey, int32_t framenum)
{
  char *query;

  _distren_asprintf(&query, "CALL `distren`.`Frame_Complete`(%d,%d,%d);", slavekey, jobkey, framenum);

  mysqlQuery(conn, query, 0);
  free(query);
}

void start_frame(distrend_mysql_conn_t conn, int32_t slavekey, int32_t jobkey, int32_t framenum)
{
  char *query;

  _distren_asprintf(&query, "CALL `distren`.`Frame_Start`(%d,%d,%d);", slavekey, jobkey, framenum);

  mysqlQuery(conn, query, 0);
  free(query);
}

void set_renderpower(distrend_mysql_conn_t conn, int32_t slavekey, int32_t renderpower)
{
  char *query;

  _distren_asprintf(&query, "CALL `distren`.`Set_Render_Power`(%d,%d);", slavekey, renderpower);

  mysqlQuery(conn, query, 0);
  free(query);
}

int change_job_priority(distrend_mysql_conn_t conn, int32_t jobkey, int32_t newpriority)
{
  char *query;

  _distren_asprintf(&query, "UPDATE `distren`.`Job` SET `Priority`=%d WHERE `Job_Key`=%d",
		    newpriority, jobkey);
  mysqlQuery(conn, query, 0);

  return 0;
}

int find_jobframe(distrend_mysql_conn_t conn, int32_t slavekey, jobnum_t *jobkey, int32_t *framenum)
{
  distrend_mysql_result_t result;
  char *query;
  MYSQL_ROW row;

  int rtn;

  _distren_asprintf(&query, "CALL `distren`.`Frame_Get`(%d);", slavekey);

  result = mysqlQuery(conn, query, 2);
  free(query);

  if(!result)
    return 1;

  row = mysql_fetch_row(result->mysqlresult);
  if(!row)
    {
      mysqlResultFree(conn, result);
      return 1;
    }

  rtn = distrend_mysql_getint(row, 0, (int32_t *)jobkey);
  rtn += distrend_mysql_getint(row, 1, framenum);
  
  mysqlResultFree(conn, result);

  return rtn;
}

int auth_slave(distrend_mysql_conn_t conn, int32_t slavekey, char *slavepass)
{
  distrend_mysql_result_t result;
  char *query;
  MYSQL_ROW row;
  int32_t *isAuth = 0;

  int rtn;
  mysql_real_escape_string(conn->mysqlconn,slavepass,slavepass,(unsigned int)strlen(slavepass));

  _distren_asprintf(&query, "CALL `distren`.`Slave_Auth`(%d,'%s');", slavekey, slavepass);

  result = mysqlQuery(conn, query, 2);
  free(query);

  if(!result)
    return 1;

  row = mysql_fetch_row(result->mysqlresult);
  if(!row)
    {
      mysqlResultFree(conn, result);
      return 1;
    }

  rtn = distrend_mysql_getint(row, 0, (int32_t *)isAuth);
  
  mysqlResultFree(conn, result);

  return rtn;
}