Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DB core: add support for asynchronous raw SQL queries
The DB core now allows SQL modules to register async raw query functions. For normal, blocking queries, execution flow remains exactly the same. Documentation available in db/db_async.h
- Loading branch information
1 parent
5081dde
commit 92755be
Showing
13 changed files
with
320 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
/* | ||
* MySQL async connection array management | ||
* | ||
* Copyright (C) 2015 OpenSIPS Solutions | ||
* | ||
* This file is part of opensips, a free SIP server. | ||
* | ||
* opensips is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version | ||
* | ||
* opensips 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 General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
* | ||
* History: | ||
* -------- | ||
* 2015-01-XX initial version (liviu) | ||
*/ | ||
|
||
#include <stdlib.h> | ||
|
||
#include "db_async.h" | ||
#include "db_pool.h" | ||
#include "../dprint.h" | ||
#include "../error.h" | ||
|
||
/* | ||
* aux variable which holds the default connection (used in blocking mode) | ||
* while async database operations are done (separate connections & queries) | ||
*/ | ||
static struct pool_con *sync_con; | ||
|
||
struct pool_con *db_switch_to_async(db_con_t *_h, get_con_fd_f get_fd, int **fd_ref, | ||
void *(*new_connection)(const struct db_id *)) | ||
{ | ||
struct pool_con *con = (struct pool_con *)_h->tail; | ||
void *new; | ||
|
||
if (con->no_transfers == db_max_async_connections) | ||
return NULL; | ||
|
||
/* no idle connections for async queries? open a new one! */ | ||
if (!con->async_pool) { | ||
new = new_connection(con->id); | ||
if (!new) { | ||
LM_ERR("failed to open new DB connection on " | ||
"%s://XXXX:XXXX@%s:%d/%s\n", con->id->scheme, | ||
con->id->host, con->id->port, con->id->database); | ||
return NULL; | ||
} | ||
} else { | ||
new = con->async_pool; | ||
con->async_pool = con->async_pool->next; | ||
} | ||
|
||
*fd_ref = &con->transfers[con->no_transfers].fd; | ||
|
||
con->transfers[con->no_transfers].fd = get_fd(new); | ||
con->transfers[con->no_transfers].con = new; | ||
|
||
LM_INFO(" %d/%d transfers: (%d - %p)\n", con->no_transfers + 1, | ||
db_max_async_connections, con->transfers[con->no_transfers].fd, | ||
con->transfers[con->no_transfers].con); | ||
|
||
con->no_transfers++; | ||
|
||
|
||
/* switch to async con */ | ||
sync_con = con; | ||
_h->tail = (unsigned long)new; | ||
|
||
return new; | ||
} | ||
|
||
void db_switch_to_sync(db_con_t *_h) | ||
{ | ||
if (!sync_con) { | ||
LM_BUG("sync_con == NULL"); | ||
abort(); | ||
} | ||
|
||
/* switch to sync con */ | ||
_h->tail = (unsigned long)sync_con; | ||
} | ||
|
||
void db_store_async_con(db_con_t *_h, struct pool_con *con) | ||
{ | ||
int i; | ||
struct pool_con *tail = (struct pool_con *)_h->tail; | ||
|
||
con->next = tail->async_pool; | ||
tail->async_pool = con; | ||
|
||
LM_INFO("XXXXXXXXXXXXXXXXXX RESTORE CONNNN: %p <<<<<<<<<<<<<<<\n", con); | ||
|
||
for (i = 0; i < tail->no_transfers; i++) { | ||
if (tail->transfers[i].con == con) { | ||
tail->no_transfers--; | ||
for (; i < tail->no_transfers; i++) | ||
tail->transfers[i] = tail->transfers[i + 1]; | ||
|
||
return; | ||
} | ||
} | ||
|
||
LM_BUG("DB con %p not found", con); | ||
abort(); | ||
} | ||
|
||
struct pool_con *db_match_async_con(int fd, db_con_t *_h) | ||
{ | ||
int i, max; | ||
struct db_transfer *transfers; | ||
|
||
LM_INFO("XXX MATCH fd %d\n", fd); | ||
|
||
transfers = ((struct pool_con *)_h->tail)->transfers; | ||
max = ((struct pool_con *)_h->tail)->no_transfers; | ||
|
||
for (i = 0; i < max; i++) | ||
if (fd == transfers[i].fd) { | ||
/* switch to async con */ | ||
sync_con = (struct pool_con *)_h->tail; | ||
_h->tail = (unsigned long)transfers[i].con; | ||
|
||
return (struct pool_con *)_h->tail; | ||
} | ||
|
||
return NULL; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* | ||
* MySQL async connection array management | ||
* | ||
* Copyright (C) 2015 OpenSIPS Solutions | ||
* | ||
* This file is part of opensips, a free SIP server. | ||
* | ||
* opensips is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version | ||
* | ||
* opensips 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 General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
* | ||
* History: | ||
* -------- | ||
* 2015-01-XX initial version (liviu) | ||
*/ | ||
|
||
/** | ||
* Basic primitives which enable async DB support on top of existing code | ||
* while keeping the existing logic working exactly as before | ||
*/ | ||
|
||
#ifndef DB_ASYNC_H | ||
#define DB_ASYNC_H | ||
|
||
#include "db_con.h" | ||
|
||
typedef int (*get_con_fd_f) (void *con); | ||
|
||
/** | ||
* Sets up the DB handle for an asynchronous query. A new connections is | ||
* opened if necessary, otherwise one is grabbed from the idle pool. | ||
* | ||
* params: | ||
* _h - DB handle | ||
* get_fd - function which returns a read file descriptor (used for polling) | ||
* from the backend's connection structure | ||
* fd_ref - if the connection fetched from the pool disconnected | ||
* (requiring a reconnect operation), or if you happen to know its fd | ||
* has changed, make sure you also update the reference passed on here | ||
* new_connection - backend-specific function to allocate and set up a new con | ||
*/ | ||
struct pool_con *db_switch_to_async(db_con_t *_h, get_con_fd_f get_fd, int **fd_ref, | ||
void *(*new_connection)(const struct db_id *)); | ||
|
||
/** | ||
* Restores the DB handle in its normal state (i.e. ready for blocking queries) | ||
* | ||
* MUST be called after initiating async operations and/or if: | ||
* * a previous db_switch_to_async() was done | ||
* * a previous db_match_async_con() was done | ||
*/ | ||
void db_switch_to_sync(db_con_t *_h); | ||
|
||
/** | ||
* Places the given connection back into the async idle pool. | ||
* | ||
* MUST be called after db_switch_to_sync(). | ||
* | ||
* MUST be called if: | ||
* * errors occurred while starting up a new async transfer | ||
* * a transfer is fully completed. | ||
*/ | ||
void db_store_async_con(db_con_t *_h, struct pool_con *con); | ||
|
||
/** | ||
* Matches the given fd to one of the ongoing async DB transfers. | ||
* Returns the DB connection of the given fd. | ||
* | ||
* Note: the DB handle is switched to async mode. | ||
* Make sure you switch back to sync mode when done. | ||
*/ | ||
struct pool_con *db_match_async_con(int fd, db_con_t *_h); | ||
|
||
#endif /* DB_ASYNC_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.