nfs-ganesha 1.4
|
00001 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; -*- 00002 * vim:expandtab:shiftwidth=4:tabstop=4: 00003 */ 00004 #ifdef HAVE_CONFIG_H 00005 #include "config.h" 00006 #endif 00007 #include "posixdb_internal.h" 00008 00009 #include <ctype.h> 00010 #include <string.h> 00011 #include "abstract_mem.h" 00012 00013 /* forward declaration of function */ 00014 fsal_posixdb_status_t fsal_posixdb_initPreparedQueries(fsal_posixdb_conn * p_conn); 00015 00016 /* read a password in a file */ 00017 static int ReadPasswordFromFile(char *filename, char *password) 00018 { 00019 FILE *passfile; 00020 char errstr[1024]; 00021 int rc; 00022 00023 passfile = fopen(filename, "r"); 00024 if(!passfile) 00025 { 00026 rc = errno; 00027 strerror_r(rc, errstr, 1024); 00028 LogCrit(COMPONENT_FSAL, "Error openning password file '%s' : %s", filename, errstr); 00029 return rc; 00030 } 00031 fscanf(passfile, "%1023s", password); 00032 if(ferror(passfile)) 00033 { 00034 rc = errno; 00035 strerror_r(rc, errstr, 1024); 00036 LogCrit(COMPONENT_FSAL, "Error reading password file '%s' : %s", filename, errstr); 00037 fclose(passfile); 00038 return rc; 00039 } 00040 fclose(passfile); 00041 return 0; 00042 } 00043 00045 fsal_posixdb_status_t fsal_posixdb_connect(fsal_posixdb_conn_params_t * dbparams, 00046 fsal_posixdb_conn ** p_conn) 00047 { 00048 my_bool reconnect = 1; 00049 char password[1024] = ""; 00050 int rc; 00051 unsigned int port; 00052 00053 /* read password from password file */ 00054 rc = ReadPasswordFromFile(dbparams->passwdfile, password); 00055 if(rc) 00056 ReturnCodeDB(ERR_FSAL_POSIXDB_CMDFAILED, rc); 00057 00058 /* resolve the port number */ 00059 if(dbparams->port[0] != '\0') 00060 { 00061 if(!isdigit(dbparams->port[0])) 00062 { 00063 LogCrit(COMPONENT_FSAL, 00064 "Numerical value expected for database port number (invalid value: %s)", 00065 dbparams->port); 00066 ReturnCodeDB(ERR_FSAL_POSIXDB_CMDFAILED, 0); 00067 } 00068 00069 port = atoi(dbparams->port); 00070 } 00071 else 00072 port = 0; 00073 00074 *p_conn = gsh_malloc(sizeof(fsal_posixdb_conn)); 00075 if(*p_conn == NULL) 00076 { 00077 LogCrit(COMPONENT_FSAL, "ERROR: failed to allocate memory"); 00078 ReturnCodeDB(ERR_FSAL_POSIXDB_NO_MEM, errno); 00079 } 00080 00081 /* Init client structure */ 00082 if(mysql_init(&(*p_conn)->db_conn) == NULL) 00083 { 00084 gsh_free(*p_conn); 00085 LogCrit(COMPONENT_FSAL, "ERROR: failed to create MySQL client struct"); 00086 ReturnCodeDB(ERR_FSAL_POSIXDB_BADCONN, errno); 00087 } 00088 #if ( MYSQL_VERSION_ID >= 50013 ) 00089 /* set auto-reconnect option */ 00090 mysql_options(&(*p_conn)->db_conn, MYSQL_OPT_RECONNECT, &reconnect); 00091 #else 00092 /* older version */ 00093 (*p_conn)->db_conn->reconnect = 1; 00094 #endif 00095 00096 /* connect to server */ 00097 if(!mysql_real_connect(&(*p_conn)->db_conn, dbparams->host, dbparams->login, 00098 password, dbparams->dbname, port, NULL, 0)) 00099 { 00100 int rc; 00101 LogCrit(COMPONENT_FSAL, "Failed to connect to MySQL server: Error: %s", 00102 mysql_error(&(*p_conn)->db_conn)); 00103 rc = mysql_errno(&(*p_conn)->db_conn); 00104 gsh_free(*p_conn); 00105 ReturnCodeDB(ERR_FSAL_POSIXDB_BADCONN, rc); 00106 } 00107 00108 /* Note [MySQL reference guide]: mysql_real_connect() incorrectly reset 00109 * the MYSQL_OPT_RECONNECT option to its default value before MySQL 5.1.6. 00110 * Therefore, prior to that version, if you want reconnect to be enabled for 00111 * each connection, you must call mysql_options() with the MYSQL_OPT_RECONNECT 00112 * option after each call to mysql_real_connect(). 00113 */ 00114 #if (MYSQL_VERSION_ID >= 50013) && (MYSQL_VERSION_ID < 50106) 00115 /* reset auto-reconnect option */ 00116 mysql_options(&(*p_conn)->db_conn, MYSQL_OPT_RECONNECT, &reconnect); 00117 #endif 00118 00119 LogEvent(COMPONENT_FSAL, "Logged on to database sucessfully"); 00120 00121 /* Create prepared statements */ 00122 return fsal_posixdb_initPreparedQueries(*p_conn); 00123 00124 } 00125 00126 fsal_posixdb_status_t fsal_posixdb_disconnect(fsal_posixdb_conn * p_conn) 00127 { 00128 mysql_close(&p_conn->db_conn); 00129 gsh_free(p_conn); 00130 ReturnCodeDB(ERR_FSAL_POSIXDB_NOERR, 0); 00131 } 00132 00133 fsal_posixdb_status_t fsal_posixdb_initPreparedQueries(fsal_posixdb_conn * p_conn) 00134 { 00135 int rc; 00136 unsigned int retry = 1; 00137 00138 static const char *buildonepath_query = 00139 "SELECT CONCAT('/',name), handleidparent, handletsparent FROM Parent WHERE handleid=? AND handlets=?"; 00140 00141 /* @TODO retry = lmgr_config.connect_retry_min; */ 00142 00143 /* create prepared statements */ 00144 00145 do 00146 { 00147 /* First create the prepared statement */ 00148 p_conn->stmt_tab[BUILDONEPATH] = mysql_stmt_init(&p_conn->db_conn); 00149 00150 /* retry if connection to server failed */ 00151 if((p_conn->stmt_tab[BUILDONEPATH] == NULL) 00152 && db_is_retryable(mysql_errno(&p_conn->db_conn))) 00153 { 00154 LogCrit(COMPONENT_FSAL, "Connection to database lost in %s()... Retrying in %u sec.", 00155 __FUNCTION__, retry); 00156 sleep(retry); 00157 retry *= 2; 00158 /*if ( retry > lmgr_config.connect_retry_max ) 00159 retry = lmgr_config.connect_retry_max; */ 00160 } 00161 else 00162 break; 00163 00164 } 00165 while(1); 00166 00167 if(!p_conn->stmt_tab[BUILDONEPATH]) 00168 ReturnCodeDB(ERR_FSAL_POSIXDB_CMDFAILED, mysql_errno(&p_conn->db_conn)); 00169 00170 /* another retry loop */ 00171 /* @TODO retry = lmgr_config.connect_retry_min; */ 00172 retry = 1; 00173 00174 do 00175 { 00176 /* prepare the request */ 00177 rc = mysql_stmt_prepare(p_conn->stmt_tab[BUILDONEPATH], buildonepath_query, 00178 strlen(buildonepath_query)); 00179 00180 if(rc && db_is_retryable(mysql_stmt_errno(p_conn->stmt_tab[BUILDONEPATH]))) 00181 { 00182 LogCrit(COMPONENT_FSAL, "Connection to database lost in %s()... Retrying in %u sec.", 00183 __FUNCTION__, retry); 00184 sleep(retry); 00185 retry *= 2; 00186 /*if ( retry > lmgr_config.connect_retry_max ) 00187 retry = lmgr_config.connect_retry_max; */ 00188 00189 } 00190 else 00191 break; 00192 00193 } 00194 while(1); 00195 00196 if(rc) 00197 { 00198 LogCrit(COMPONENT_FSAL, "Failed to create prepared statement: Error: %s (query='%s')", 00199 mysql_stmt_error(p_conn->stmt_tab[BUILDONEPATH]), buildonepath_query); 00200 mysql_stmt_close(p_conn->stmt_tab[BUILDONEPATH]); 00201 ReturnCodeDB(ERR_FSAL_POSIXDB_CMDFAILED, rc); 00202 } 00203 00204 ReturnCodeDB(ERR_FSAL_POSIXDB_NOERR, 0); 00205 }