Skip to content

Commit

Permalink
WL#11381: Add asynchronous support into the mysql protocol
Browse files Browse the repository at this point in the history
C APIs are synchronous, which means client sends a request and waits until
server responds. This makes applications to not do anything until server
sends a response. There can be a requirement where client is not bothered
about when server sends data back, client can submit a query, do some other
tasks and when in need of server response, client can check if server has sent
the response and act accordingly. Thus making a need to implement asynchronous
communication between client and server.

This WL introduces new non blocking version of above C APIs which does not wait
for data to be available on the socket to be read. These APIs will return
immediately with a return status. Return status is used to decide if the API
has completed its operation or needs to be called again at some later point
in time to complete the operation.

RB: 21150
Reviewed-by: Georgi Kodinov
             Ramil Kalimullin
  • Loading branch information
Bharathy Satish committed Jan 11, 2019
1 parent b8be8ee commit c1fffc3
Show file tree
Hide file tree
Showing 44 changed files with 5,346 additions and 533 deletions.
529 changes: 450 additions & 79 deletions client/mysqltest.cc

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions include/errmsg.h
@@ -1,7 +1,7 @@
#ifndef ERRMSG_INCLUDED
#define ERRMSG_INCLUDED

/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
/* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2.0,
Expand Down Expand Up @@ -123,7 +123,8 @@ extern const char *client_errors[]; /* Error messages */
#define CR_INSECURE_API_ERR 2062
#define CR_FILE_NAME_TOO_LONG 2063
#define CR_SSL_FIPS_MODE_ERR 2064
#define CR_ERROR_LAST /*Copy last error nr:*/ 2064
#define CR_COMPRESSION_NOT_SUPPORTED 2065
#define CR_ERROR_LAST /*Copy last error nr:*/ 2065
/* Add error numbers before CR_ERROR_LAST and change it accordingly. */

/* Visual Studio requires '__inline' for C code */
Expand Down
18 changes: 18 additions & 0 deletions include/mysql.h
Expand Up @@ -465,6 +465,20 @@ int STDCALL mysql_real_query(MYSQL *mysql, const char *q, unsigned long length);
MYSQL_RES *STDCALL mysql_store_result(MYSQL *mysql);
MYSQL_RES *STDCALL mysql_use_result(MYSQL *mysql);

enum net_async_status STDCALL mysql_real_connect_nonblocking(
MYSQL *mysql, const char *host, const char *user, const char *passwd,
const char *db, unsigned int port, const char *unix_socket,
unsigned long clientflag);
enum net_async_status STDCALL mysql_send_query_nonblocking(
MYSQL *mysql, const char *query, unsigned long length);
enum net_async_status STDCALL mysql_real_query_nonblocking(
MYSQL *mysql, const char *query, unsigned long length);
enum net_async_status STDCALL
mysql_store_result_nonblocking(MYSQL *mysql, MYSQL_RES **result);
enum net_async_status STDCALL mysql_next_result_nonblocking(MYSQL *mysql);
enum net_async_status STDCALL mysql_select_db_nonblocking(MYSQL *mysql,
const char *db,
bool *error);
void STDCALL mysql_get_character_set_info(MYSQL *mysql,
MY_CHARSET_INFO *charset);

Expand Down Expand Up @@ -510,12 +524,16 @@ int STDCALL mysql_options4(MYSQL *mysql, enum mysql_option option,
int STDCALL mysql_get_option(MYSQL *mysql, enum mysql_option option,
const void *arg);
void STDCALL mysql_free_result(MYSQL_RES *result);
enum net_async_status STDCALL mysql_free_result_nonblocking(MYSQL_RES *result);
void STDCALL mysql_data_seek(MYSQL_RES *result, my_ulonglong offset);
MYSQL_ROW_OFFSET STDCALL mysql_row_seek(MYSQL_RES *result,
MYSQL_ROW_OFFSET offset);
MYSQL_FIELD_OFFSET STDCALL mysql_field_seek(MYSQL_RES *result,
MYSQL_FIELD_OFFSET offset);
MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result);
enum net_async_status STDCALL mysql_fetch_row_nonblocking(MYSQL_RES *res,
MYSQL_ROW *row);

unsigned long *STDCALL mysql_fetch_lengths(MYSQL_RES *result);
MYSQL_FIELD *STDCALL mysql_fetch_field(MYSQL_RES *result);
MYSQL_RES *STDCALL mysql_list_fields(MYSQL *mysql, const char *table,
Expand Down
34 changes: 33 additions & 1 deletion include/mysql.h.pp
Expand Up @@ -264,16 +264,31 @@
} protocol;
int socket;
};
enum net_async_status {
NET_ASYNC_COMPLETE = 0,
NET_ASYNC_NOT_READY,
NET_ASYNC_ERROR,
NET_ASYNC_COMPLETE_WITH_MORE_RESULTS
};
typedef struct MYSQL_PLUGIN_VIO {
int (*read_packet)(struct MYSQL_PLUGIN_VIO *vio, unsigned char **buf);
int (*write_packet)(struct MYSQL_PLUGIN_VIO *vio, const unsigned char *packet,
int packet_len);
void (*info)(struct MYSQL_PLUGIN_VIO *vio,
struct MYSQL_PLUGIN_VIO_INFO *info);
enum net_async_status (*read_packet_nonblocking)(struct MYSQL_PLUGIN_VIO *vio,
unsigned char **buf,
int *result);
enum net_async_status (*write_packet_nonblocking)(
struct MYSQL_PLUGIN_VIO *vio, const unsigned char *pkt, int pkt_len,
int *result);
} MYSQL_PLUGIN_VIO;
struct auth_plugin_t {
int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; const char *license; void *mysql_api; int (*init)(char *, size_t, int, va_list); int (*deinit)(void); int (*options)(const char *option, const void *);
int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct MYSQL *mysql);
enum net_async_status (*authenticate_user_nonblocking)(MYSQL_PLUGIN_VIO *vio,
struct MYSQL *mysql,
int *result);
};
typedef struct auth_plugin_t st_mysql_client_plugin_AUTHENTICATION;
struct st_mysql_client_plugin *mysql_load_plugin(struct MYSQL *mysql,
Expand Down Expand Up @@ -309,7 +324,7 @@
void finish_client_errs(void);
extern const char *client_errors[];
static inline const char *ER_CLIENT(int client_errno) {
if (client_errno >= 2000 && client_errno <= 2064)
if (client_errno >= 2000 && client_errno <= 2065)
return client_errors[client_errno - 2000];
return client_errors[2000];
}
Expand Down Expand Up @@ -561,6 +576,20 @@
int mysql_real_query(MYSQL *mysql, const char *q, unsigned long length);
MYSQL_RES * mysql_store_result(MYSQL *mysql);
MYSQL_RES * mysql_use_result(MYSQL *mysql);
enum net_async_status mysql_real_connect_nonblocking(
MYSQL *mysql, const char *host, const char *user, const char *passwd,
const char *db, unsigned int port, const char *unix_socket,
unsigned long clientflag);
enum net_async_status mysql_send_query_nonblocking(
MYSQL *mysql, const char *query, unsigned long length);
enum net_async_status mysql_real_query_nonblocking(
MYSQL *mysql, const char *query, unsigned long length);
enum net_async_status
mysql_store_result_nonblocking(MYSQL *mysql, MYSQL_RES **result);
enum net_async_status mysql_next_result_nonblocking(MYSQL *mysql);
enum net_async_status mysql_select_db_nonblocking(MYSQL *mysql,
const char *db,
bool *error);
void mysql_get_character_set_info(MYSQL *mysql,
MY_CHARSET_INFO *charset);
int mysql_session_track_get_first(MYSQL *mysql,
Expand Down Expand Up @@ -600,12 +629,15 @@
int mysql_get_option(MYSQL *mysql, enum mysql_option option,
const void *arg);
void mysql_free_result(MYSQL_RES *result);
enum net_async_status mysql_free_result_nonblocking(MYSQL_RES *result);
void mysql_data_seek(MYSQL_RES *result, my_ulonglong offset);
MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result,
MYSQL_ROW_OFFSET offset);
MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES *result,
MYSQL_FIELD_OFFSET offset);
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
enum net_async_status mysql_fetch_row_nonblocking(MYSQL_RES *res,
MYSQL_ROW *row);
unsigned long * mysql_fetch_lengths(MYSQL_RES *result);
MYSQL_FIELD * mysql_fetch_field(MYSQL_RES *result);
MYSQL_RES * mysql_list_fields(MYSQL *mysql, const char *table,
Expand Down
8 changes: 6 additions & 2 deletions include/mysql/client_authentication.h
@@ -1,4 +1,4 @@
/* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
/* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2.0,
Expand Down Expand Up @@ -35,5 +35,9 @@ int sha256_password_deinit(void);
int caching_sha2_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
int caching_sha2_password_init(char *, size_t, int, va_list);
int caching_sha2_password_deinit(void);

net_async_status caching_sha2_password_auth_client_nonblocking(
MYSQL_PLUGIN_VIO *vio, MYSQL *mysql, int *res);
net_async_status sha256_password_auth_client_nonblocking(MYSQL_PLUGIN_VIO *vio,
MYSQL *mysql,
int *res);
#endif
7 changes: 5 additions & 2 deletions include/mysql/client_plugin.h
@@ -1,5 +1,5 @@
#ifndef MYSQL_CLIENT_PLUGIN_INCLUDED
/* Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
/* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2.0,
Expand Down Expand Up @@ -75,7 +75,7 @@ extern "C" {
#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN 2
#define MYSQL_CLIENT_TRACE_PLUGIN 3

#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0100
#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0101
#define MYSQL_CLIENT_TRACE_PLUGIN_INTERFACE_VERSION 0x0100

#define MYSQL_CLIENT_MAX_PLUGINS 4
Expand Down Expand Up @@ -113,6 +113,9 @@ struct MYSQL;
struct auth_plugin_t {
MYSQL_CLIENT_PLUGIN_HEADER
int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct MYSQL *mysql);
enum net_async_status (*authenticate_user_nonblocking)(MYSQL_PLUGIN_VIO *vio,
struct MYSQL *mysql,
int *result);
};

// Needed for the mysql_declare_client_plugin() macro. Do not use elsewhere.
Expand Down
15 changes: 15 additions & 0 deletions include/mysql/client_plugin.h.pp
Expand Up @@ -13,16 +13,31 @@
} protocol;
int socket;
};
enum net_async_status {
NET_ASYNC_COMPLETE = 0,
NET_ASYNC_NOT_READY,
NET_ASYNC_ERROR,
NET_ASYNC_COMPLETE_WITH_MORE_RESULTS
};
typedef struct MYSQL_PLUGIN_VIO {
int (*read_packet)(struct MYSQL_PLUGIN_VIO *vio, unsigned char **buf);
int (*write_packet)(struct MYSQL_PLUGIN_VIO *vio, const unsigned char *packet,
int packet_len);
void (*info)(struct MYSQL_PLUGIN_VIO *vio,
struct MYSQL_PLUGIN_VIO_INFO *info);
enum net_async_status (*read_packet_nonblocking)(struct MYSQL_PLUGIN_VIO *vio,
unsigned char **buf,
int *result);
enum net_async_status (*write_packet_nonblocking)(
struct MYSQL_PLUGIN_VIO *vio, const unsigned char *pkt, int pkt_len,
int *result);
} MYSQL_PLUGIN_VIO;
struct auth_plugin_t {
int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; const char *license; void *mysql_api; int (*init)(char *, size_t, int, va_list); int (*deinit)(void); int (*options)(const char *option, const void *);
int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct MYSQL *mysql);
enum net_async_status (*authenticate_user_nonblocking)(MYSQL_PLUGIN_VIO *vio,
struct MYSQL *mysql,
int *result);
};
typedef struct auth_plugin_t st_mysql_client_plugin_AUTHENTICATION;
struct st_mysql_client_plugin *mysql_load_plugin(struct MYSQL *mysql,
Expand Down
12 changes: 12 additions & 0 deletions include/mysql/plugin_auth.h.pp
Expand Up @@ -130,12 +130,24 @@
} protocol;
int socket;
};
enum net_async_status {
NET_ASYNC_COMPLETE = 0,
NET_ASYNC_NOT_READY,
NET_ASYNC_ERROR,
NET_ASYNC_COMPLETE_WITH_MORE_RESULTS
};
typedef struct MYSQL_PLUGIN_VIO {
int (*read_packet)(struct MYSQL_PLUGIN_VIO *vio, unsigned char **buf);
int (*write_packet)(struct MYSQL_PLUGIN_VIO *vio, const unsigned char *packet,
int packet_len);
void (*info)(struct MYSQL_PLUGIN_VIO *vio,
struct MYSQL_PLUGIN_VIO_INFO *info);
enum net_async_status (*read_packet_nonblocking)(struct MYSQL_PLUGIN_VIO *vio,
unsigned char **buf,
int *result);
enum net_async_status (*write_packet_nonblocking)(
struct MYSQL_PLUGIN_VIO *vio, const unsigned char *pkt, int pkt_len,
int *result);
} MYSQL_PLUGIN_VIO;
struct MYSQL_SERVER_AUTH_INFO {
char *user_name;
Expand Down
28 changes: 27 additions & 1 deletion include/mysql/plugin_auth_common.h
@@ -1,5 +1,5 @@
#ifndef MYSQL_PLUGIN_AUTH_COMMON_INCLUDED
/* Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
/* Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2.0,
Expand Down Expand Up @@ -126,6 +126,14 @@ struct MYSQL_PLUGIN_VIO_INFO {
#endif
};

/* state of an asynchronous operation */
enum net_async_status {
NET_ASYNC_COMPLETE = 0,
NET_ASYNC_NOT_READY,
NET_ASYNC_ERROR,
NET_ASYNC_COMPLETE_WITH_MORE_RESULTS
};

/**
Provides plugin access to communication channel
*/
Expand All @@ -151,6 +159,24 @@ typedef struct MYSQL_PLUGIN_VIO {
void (*info)(struct MYSQL_PLUGIN_VIO *vio,
struct MYSQL_PLUGIN_VIO_INFO *info);

/**
Non blocking version of read_packet. This function points buf to starting
position of incoming packet. When this function returns NET_ASYNC_NOT_READY
plugin should call this function again until all incoming packets are read.
If return code is NET_ASYNC_COMPLETE, plugin can do further processing of
read packets.
*/
enum net_async_status (*read_packet_nonblocking)(struct MYSQL_PLUGIN_VIO *vio,
unsigned char **buf,
int *result);
/**
Non blocking version of write_packet. Sends data available in pkt of length
pkt_len to server in asynchrnous way.
*/
enum net_async_status (*write_packet_nonblocking)(
struct MYSQL_PLUGIN_VIO *vio, const unsigned char *pkt, int pkt_len,
int *result);

} MYSQL_PLUGIN_VIO;

#endif

0 comments on commit c1fffc3

Please sign in to comment.