📄 mysql.c
字号:
which is why we need to use InnoDB for those (even though MyISAM would be faster) */ if (50046 <= mysql_get_server_version (dbh->dbf)) { /* MySQL 5.0.46 fixes bug in MyISAM */ mysql_query (dbh->dbf, "CREATE TABLE IF NOT EXISTS gn080 (" " size INT(11) UNSIGNED NOT NULL DEFAULT 0," " type INT(11) UNSIGNED NOT NULL DEFAULT 0," " prio INT(11) UNSIGNED NOT NULL DEFAULT 0," " anonLevel INT(11) UNSIGNED NOT NULL DEFAULT 0," " expire BIGINT UNSIGNED NOT NULL DEFAULT 0," " hash BINARY(64) NOT NULL," " vhash BINARY(64) NOT NULL PRIMARY KEY," " vkey BIGINT UNSIGNED NOT NULL DEFAULT 0," " INDEX hash (hash(64))," " INDEX hash_vhash_vkey (hash(64),vhash(64),vkey)," " INDEX hash_vkey (hash(64),vkey)," " INDEX vkey (vkey)," " INDEX prio (prio,vkey)," " INDEX expire (expire,vkey,type)," " INDEX anonLevel (anonLevel,prio,vkey,type)" ") ENGINE=MyISAM"); } else { mysql_query (dbh->dbf, "CREATE TABLE IF NOT EXISTS gn080 (" " size INT(11) UNSIGNED NOT NULL DEFAULT 0," " type INT(11) UNSIGNED NOT NULL DEFAULT 0," " prio INT(11) UNSIGNED NOT NULL DEFAULT 0," " anonLevel INT(11) UNSIGNED NOT NULL DEFAULT 0," " expire BIGINT UNSIGNED NOT NULL DEFAULT 0," " hash BINARY(64) NOT NULL DEFAULT ''," " vhash BINARY(64) NOT NULL DEFAULT ''," " vkey BIGINT UNSIGNED NOT NULL DEFAULT 0," " INDEX hash (hash(64))," " INDEX hash_vhash_vkey (hash(64),vhash(64),vkey)," " INDEX hash_vkey (hash(64),vkey)," " INDEX vkey (vkey)," " INDEX prio (prio,vkey)," " INDEX expire (expire,vkey,type)," " INDEX anonLevel (anonLevel,prio,vkey,type)" ") ENGINE=InnoDB"); } if (mysql_error (dbh->dbf)[0]) { LOG_MYSQL (GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK, "mysql_query", dbh); iclose (); return GNUNET_SYSERR; } mysql_query (dbh->dbf, "CREATE TABLE IF NOT EXISTS gn072 (" " vkey BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY," " value BLOB NOT NULL DEFAULT '') ENGINE=MyISAM"); if (mysql_error (dbh->dbf)[0]) { LOG_MYSQL (GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK, "mysql_query", dbh); iclose (); return GNUNET_SYSERR; } mysql_query (dbh->dbf, "SET AUTOCOMMIT = 1"); if (mysql_error (dbh->dbf)[0]) { LOG_MYSQL (GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_BULK, "mysql_query", dbh); iclose (); return GNUNET_SYSERR; }#define PINIT(a,b) a = mysql_stmt_init(dbh->dbf); if (a == NULL) { iclose(); return GNUNET_SYSERR; } else { \ if (mysql_stmt_prepare (a, b, strlen(b))) { \ GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, \ _("`%s' failed at %s:%d with error: %s"), "mysql_stmt_prepare", __FILE__, __LINE__, \ mysql_stmt_error (a)); iclose(); return GNUNET_SYSERR; } } PINIT (dbh->select_value, SELECT_VALUE); PINIT (dbh->delete_value, DELETE_VALUE); PINIT (dbh->insert_value, INSERT_VALUE); PINIT (dbh->insert_entry, INSERT_ENTRY); PINIT (dbh->delete_entry_by_vkey, DELETE_ENTRY_BY_VKEY); PINIT (dbh->select_entry_by_hash, SELECT_ENTRY_BY_HASH); PINIT (dbh->select_entry_by_hash_and_vhash, SELECT_ENTRY_BY_HASH_AND_VHASH); PINIT (dbh->select_entry_by_hash_and_type, SELECT_ENTRY_BY_HASH_AND_TYPE); PINIT (dbh->select_entry_by_hash_vhash_and_type, SELECT_ENTRY_BY_HASH_VHASH_AND_TYPE); PINIT (dbh->count_entry_by_hash, COUNT_ENTRY_BY_HASH); PINIT (dbh->count_entry_by_hash_and_vhash, COUNT_ENTRY_BY_HASH_AND_VHASH); PINIT (dbh->count_entry_by_hash_and_type, COUNT_ENTRY_BY_HASH_AND_TYPE); PINIT (dbh->count_entry_by_hash_vhash_and_type, COUNT_ENTRY_BY_HASH_VHASH_AND_TYPE); PINIT (dbh->update_entry, UPDATE_ENTRY); PINIT (dbh->iter[0], SELECT_IT_LOW_PRIORITY); PINIT (dbh->iter[1], SELECT_IT_NON_ANONYMOUS); PINIT (dbh->iter[2], SELECT_IT_EXPIRATION_TIME); PINIT (dbh->iter[3], SELECT_IT_MIGRATION_ORDER); dbh->valid = GNUNET_YES; return GNUNET_OK;}/** * Check if DBH handle is valid, return GNUNET_OK if it is. * Also tries to re-connect to the DB if the connection * is down. */#define CHECK_DBH ((dbh->valid == GNUNET_NO) ? iopen(dbh, GNUNET_YES) : GNUNET_OK)/** * Delete an value from the gn072 table. * * @param vkey vkey identifying the value to delete * @return GNUNET_OK on success, GNUNET_NO if no such value exists, GNUNET_SYSERR on error */static intdelete_value (unsigned long long vkey){ MYSQL_BIND qbind[1]; int ret; memset (qbind, 0, sizeof (qbind)); qbind[0].is_unsigned = GNUNET_YES; qbind[0].buffer_type = MYSQL_TYPE_LONGLONG; qbind[0].buffer = &vkey; GNUNET_GE_ASSERT (ectx, mysql_stmt_param_count (dbh->delete_value) == 1); if (mysql_stmt_bind_param (dbh->delete_value, qbind)) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _("`%s' failed at %s:%d with error: %s\n"), "mysql_stmt_bind_param", __FILE__, __LINE__, mysql_stmt_error (dbh->delete_value)); iclose (); return GNUNET_SYSERR; } if (mysql_stmt_execute (dbh->delete_value)) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _("`%s' failed at %s:%d with error: %s\n"), "mysql_stmt_execute", __FILE__, __LINE__, mysql_stmt_error (dbh->delete_value)); iclose (); return GNUNET_SYSERR; } if (mysql_stmt_affected_rows (dbh->delete_value) == 0) ret = GNUNET_NO; else ret = GNUNET_OK; mysql_stmt_reset (dbh->delete_value); return ret;}/** * Insert a value into the gn072 table. * * @param value the value to insert * @param size size of the value * @param vkey vkey identifying the value henceforth (set) * @return GNUNET_OK on success, GNUNET_SYSERR on error */static intinsert_value (const void *value, unsigned int size, unsigned long long *vkey){ MYSQL_BIND qbind[1]; unsigned long length = size; memset (qbind, 0, sizeof (qbind)); qbind[0].buffer_type = MYSQL_TYPE_BLOB; qbind[0].buffer = (void *) value; qbind[0].buffer_length = size; qbind[0].length = &length; GNUNET_GE_ASSERT (ectx, mysql_stmt_param_count (dbh->insert_value) == 1); if (mysql_stmt_bind_param (dbh->insert_value, qbind)) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _("`%s' failed at %s:%d with error: %s\n"), "mysql_stmt_bind_param", __FILE__, __LINE__, mysql_stmt_error (dbh->insert_value)); iclose (); return GNUNET_SYSERR; } if (mysql_stmt_execute (dbh->insert_value)) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _("`%s' failed at %s:%d with error: %s\n"), "mysql_stmt_execute", __FILE__, __LINE__, mysql_stmt_error (dbh->insert_value)); iclose (); return GNUNET_SYSERR; } *vkey = (unsigned long long) mysql_stmt_insert_id (dbh->insert_value); mysql_stmt_reset (dbh->insert_value); return GNUNET_OK;}/** * Delete an entry from the gn080 table. * * @param vkey vkey identifying the entry to delete * @return GNUNET_OK on success, GNUNET_NO if no such value exists, GNUNET_SYSERR on error */static intdelete_entry_by_vkey (unsigned long long vkey){ MYSQL_BIND qbind[1]; int ret; memset (qbind, 0, sizeof (qbind)); qbind[0].is_unsigned = GNUNET_YES; qbind[0].buffer_type = MYSQL_TYPE_LONGLONG; qbind[0].buffer = &vkey; GNUNET_GE_ASSERT (ectx, mysql_stmt_param_count (dbh->delete_entry_by_vkey) == 1); if (mysql_stmt_bind_param (dbh->delete_entry_by_vkey, qbind)) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _("`%s' failed at %s:%d with error: %s\n"), "mysql_stmt_bind_param", __FILE__, __LINE__, mysql_stmt_error (dbh->delete_entry_by_vkey)); iclose (); return GNUNET_SYSERR; } if (mysql_stmt_execute (dbh->delete_entry_by_vkey)) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _("`%s' failed at %s:%d with error: %s\n"), "mysql_stmt_execute", __FILE__, __LINE__, mysql_stmt_error (dbh->delete_entry_by_vkey)); iclose (); return GNUNET_SYSERR; } if (mysql_stmt_affected_rows (dbh->delete_entry_by_vkey) == 0) ret = GNUNET_NO; else ret = GNUNET_OK; mysql_stmt_reset (dbh->delete_entry_by_vkey); return ret;}/** * Given a full (SELECT *) result set from gn080 table, * assemble it into a GNUNET_DatastoreValue representation. * * Call *without* holding the lock, but while within * mysql_thread_start/end. * * @param result location where mysql_stmt_fetch stored the results * @return NULL on error */static GNUNET_DatastoreValue *assembleDatum (MYSQL_BIND * result){ GNUNET_DatastoreValue *datum; unsigned int contentSize; unsigned int type; unsigned int prio; unsigned int level; unsigned long long exp; unsigned long long vkey; unsigned long length; MYSQL_BIND qbind[1]; MYSQL_BIND rbind[1]; if ((result[0].buffer_type != MYSQL_TYPE_LONG) || (!result[0].is_unsigned) || (result[1].buffer_type != MYSQL_TYPE_LONG) || (!result[1].is_unsigned) || (result[2].buffer_type != MYSQL_TYPE_LONG) || (!result[2].is_unsigned) || (result[3].buffer_type != MYSQL_TYPE_LONG) || (!result[3].is_unsigned) || (result[4].buffer_type != MYSQL_TYPE_LONGLONG) || (!result[4].is_unsigned) || (result[5].buffer_type != MYSQL_TYPE_BLOB) || (result[5].buffer_length != sizeof (GNUNET_HashCode)) || (*result[5].length != sizeof (GNUNET_HashCode)) || (result[6].buffer_type != MYSQL_TYPE_LONGLONG) || (!result[6].is_unsigned)) { GNUNET_GE_BREAK (NULL, 0); return NULL; /* error */ } contentSize = *(unsigned int *) result[0].buffer; if (contentSize < sizeof (GNUNET_DatastoreValue)) return NULL; /* error */ contentSize -= sizeof (GNUNET_DatastoreValue); type = *(unsigned int *) result[1].buffer; prio = *(unsigned int *) result[2].buffer; level = *(unsigned int *) result[3].buffer; exp = *(unsigned long long *) result[4].buffer; vkey = *(unsigned long long *) result[6].buffer; datum = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + contentSize); datum->size = htonl (contentSize + sizeof (GNUNET_DatastoreValue)); datum->type = htonl (type); datum->priority = htonl (prio); datum->anonymity_level = htonl (level); datum->expiration_time = GNUNET_htonll (exp); /* now do query on gn072 */ length = contentSize; memset (qbind, 0, sizeof (qbind)); qbind[0].is_unsigned = 1; qbind[0].buffer_type = MYSQL_TYPE_LONGLONG; qbind[0].buffer = &vkey; memset (rbind, 0, sizeof (rbind)); rbind[0].buffer_type = MYSQL_TYPE_BLOB; rbind[0].buffer_length = contentSize; rbind[0].length = &length; rbind[0].buffer = &datum[1]; GNUNET_mutex_lock (lock); if (GNUNET_OK != CHECK_DBH) { GNUNET_mutex_unlock (lock); GNUNET_free (datum); return NULL; } GNUNET_GE_ASSERT (ectx, mysql_stmt_param_count (dbh->select_value) == 1); if (mysql_stmt_bind_param (dbh->select_value, qbind)) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _("`%s' failed at %s:%d with error: %s\n"), "mysql_stmt_bind_param", __FILE__, __LINE__, mysql_stmt_error (dbh->select_value)); iclose (); GNUNET_mutex_unlock (lock); GNUNET_free (datum); return NULL; } if (mysql_stmt_execute (dbh->select_value)) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _("`%s' failed at %s:%d with error: %s\n"), "mysql_stmt_execute", __FILE__, __LINE__, mysql_stmt_error (dbh->select_value)); iclose (); GNUNET_mutex_unlock (lock); GNUNET_free (datum); return NULL; } GNUNET_GE_ASSERT (ectx, mysql_stmt_field_count (dbh->select_value) == 1); if (mysql_stmt_bind_result (dbh->select_value, rbind)) { GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _("`%s' failed at %s:%d with error: %s\n"), "mysql_stmt_bind_result", __FILE__, __LINE__, mysql_stmt_error (dbh->select_value)); iclose (); GNUNET_mutex_unlock (lock); GNUNET_free (datum); return NULL; } if ((0 != mysql_stmt_fetch (dbh->select_value)) || (rbind[0].buffer_length != contentSize) || (length != contentSize)) { mysql_stmt_reset (dbh->select_value); GNUNET_GE_LOG (ectx,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -