/** * qlog->write(): Log messages * * @param log a pointer of qlog_t * @param str message string * * @return true if successful, otherewise returns false */ static bool write_(qlog_t *log, const char *str) { if (log == NULL || log->fp == NULL) return false; Q_MUTEX_ENTER(log->qmutex); /* duplicate stream */ if (log->outfp != NULL) { fprintf(log->outfp, "%s\n", str); if (log->outflush == true) fflush(log->outfp); } /* check if log rotation is needed */ if (log->nextrotate > 0 && time(NULL) >= log->nextrotate) { _real_open(log); } /* log to file */ bool ret = false; if (fprintf(log->fp, "%s\n", str) >= 0) { if (log->logflush == true) fflush(log->fp); ret = true; } Q_MUTEX_LEAVE(log->qmutex); return ret; }
/** * qlog->duplicate(): Duplicate log string into other stream * * @param log a pointer of qlog_t * @param fp logging messages will be printed out into this stream. * set NULL to disable. * @param flush set to true if you want to flush everytime duplicating. * * @return true if successful, otherewise returns false * * @code * log->duplicate(log, stdout, true); // enable console out with flushing * log->duplicate(log, stderr, false); // enable console out * log->duplicate(log, NULL, false); // disable console out (default) * @endcode */ static bool duplicate(qlog_t *log, FILE *outfp, bool flush) { if (log == NULL) return false; Q_MUTEX_ENTER(log->qmutex); log->outfp = outfp; log->outflush = flush; Q_MUTEX_LEAVE(log->qmutex); return true; }
/** * qdb->begin_tran(): Start transaction * * @param db a pointer of qdb_t object * * @return true if successful, otherwise returns false * * @code * db->begin_tran(db); * (... insert/update/delete ...) * db->commit(db); * @endcode * * @note * This operation will raise lock if you compile "--enable-threadsafe" option * to protect thread-safe operation. In this case, before calling * qdb->commit() or qdb->rollback(), another threads will be hold. */ static bool begin_tran(qdb_t *db) { if (db == NULL) return false; #ifdef _Q_ENABLE_MYSQL Q_MUTEX_ENTER(db->qmutex); if (db->qmutex.count != 1) { Q_MUTEX_LEAVE(db->qmutex); return false; } qdbresult_t *result; result = db->execute_query(db, "START TRANSACTION"); if (result == NULL) { Q_MUTEX_LEAVE(db->qmutex); return false; } result->free(result); return true; #else return false; #endif }
/** * qlog->flush(): Flush buffered log * * @param log a pointer of qlog_t * * @return true if successful, otherewise returns false */ static bool flush_(qlog_t *log) { if (log == NULL) return false; // only flush if flush flag is disabled Q_MUTEX_ENTER(log->qmutex); if (log->fp != NULL && log->logflush == false) fflush(log->fp); if (log->outfp != NULL && log->outflush == false) fflush(log->outfp); Q_MUTEX_LEAVE(log->qmutex); return false; }
/** * qlog->free(): Close ratating-log file & de-allocate resources * * @param log a pointer of qlog_t */ static void free_(qlog_t *log) { if (log == NULL) return; flush_(log); Q_MUTEX_ENTER(log->qmutex); if (log->fp != NULL) { fclose(log->fp); log->fp = NULL; } Q_MUTEX_LEAVE(log->qmutex); Q_MUTEX_DESTROY(log->qmutex); free(log); return; }
/** * qdb->rellback(): Roll-back and abort transaction * * @param db a pointer of qdb_t object * * @return true if successful, otherwise returns false */ static bool rollback(qdb_t *db) { if (db == NULL) return false; #ifdef _Q_ENABLE_MYSQL bool ret = false; if (mysql_rollback(db->mysql) == 0) { ret = true; } if (db->qmutex.count > 0) { Q_MUTEX_LEAVE(db->qmutex); } return ret; #else return 0; #endif }
/** * qdb->free(): De-allocate qdb_t structure * * @param db a pointer of qdb_t object */ static void free_(qdb_t *db) { if (db == NULL) return; Q_MUTEX_ENTER(db->qmutex); close_(db); free(db->info.dbtype); free(db->info.addr); free(db->info.username); free(db->info.password); free(db->info.database); free(db); Q_MUTEX_LEAVE(db->qmutex); Q_MUTEX_DESTROY(db->qmutex); return; }
/** * qdb->close(): Disconnect from database server * * @param db a pointer of qdb_t object * * @return true if successful, otherwise returns false. * * @note * Unless you call qdb->free(), qdb_t object will keep the database * information. So you can re-connect to database using qdb->open(). */ static bool close_(qdb_t *db) { if (db == NULL) return false; #ifdef _Q_ENABLE_MYSQL Q_MUTEX_ENTER(db->qmutex); if (db->mysql != NULL) { mysql_close(db->mysql); db->mysql = NULL; mysql_library_end(); } db->connected = false; Q_MUTEX_LEAVE(db->qmutex); return true; #else return false; #endif }
/** * qdb->execute_update(): Executes the update DML * * @param db a pointer of qdb_t object * @param query query string * * @return a number of affected rows */ static int execute_update(qdb_t *db, const char *query) { if (db == NULL || db->connected == false) return -1; #ifdef _Q_ENABLE_MYSQL Q_MUTEX_ENTER(db->qmutex); int affected = -1; // query DEBUG("%s", query); if (mysql_query(db->mysql, query) == 0) { /* get affected rows */ if ((affected = mysql_affected_rows(db->mysql)) < 0) affected = -1; } Q_MUTEX_LEAVE(db->qmutex); return affected; #else return -1; #endif }
/** * qlist->unlock(): Leaves critical section. * * @param list qlist_t container pointer. */ void qlist_unlock(qlist_t *list) { Q_MUTEX_LEAVE(list->qmutex); }
/** * qdb->open(): Connect to database server * * @param db a pointer of qdb_t object * * @return true if successful, otherwise returns false. */ static bool open_(qdb_t *db) { if (db == NULL) return false; // if connected, close first if (db->connected == true) { close_(db); } #ifdef _Q_ENABLE_MYSQL Q_MUTEX_ENTER(db->qmutex); // initialize handler if (db->mysql != NULL) close_(db); if (mysql_library_init(0, NULL, NULL) != 0) { Q_MUTEX_LEAVE(db->qmutex); return false; } if ((db->mysql = mysql_init(NULL)) == NULL) { Q_MUTEX_LEAVE(db->qmutex); return false; } // set options my_bool reconnect = _Q_MYSQL_OPT_RECONNECT; unsigned int connect_timeout = _Q_MYSQL_OPT_CONNECT_TIMEOUT; unsigned int read_timeout = _Q_MYSQL_OPT_READ_TIMEOUT; unsigned int write_timeout = _Q_MYSQL_OPT_WRITE_TIMEOUT; if (reconnect != false) { mysql_options(db->mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect); } if (connect_timeout > 0) { mysql_options(db->mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *)&connect_timeout); } if (read_timeout > 0) { mysql_options(db->mysql, MYSQL_OPT_READ_TIMEOUT, (char *)&read_timeout); } if (write_timeout > 0) { mysql_options(db->mysql, MYSQL_OPT_WRITE_TIMEOUT, (char *)&write_timeout); } // try to connect if (mysql_real_connect(db->mysql, db->info.addr, db->info.username, db->info.password, db->info.database, db->info.port, NULL, 0) == NULL) { close_(db); // free mysql handler Q_MUTEX_LEAVE(db->qmutex); return false; } // set auto-commit if (mysql_autocommit(db->mysql, db->info.autocommit) != 0) { close_(db); // free mysql handler Q_MUTEX_LEAVE(db->qmutex); return false; } // set flag db->connected = true; Q_MUTEX_LEAVE(db->qmutex); return true; #else return false; #endif }
/** * qhashtbl->unlock(): Leave critical section. * * @param tbl qhashtbl_t container pointer. * * @note * This operation will do nothing if QHASHTBL_THREADSAFE option was not * given at the initialization time. */ void qhashtbl_unlock(qhashtbl_t *tbl) { Q_MUTEX_LEAVE(tbl->qmutex); }