<commit_before>#include <mysql2_ext.h>
#include <client.h>
#include <errno.h>

VALUE cMysql2Client;
extern VALUE mMysql2, cMysql2Error;
static VALUE intern_encoding_from_charset;
static ID sym_id, sym_version, sym_async, sym_symbolize_keys, sym_as, sym_array;
static ID intern_merge, intern_error_number_eql, intern_sql_state_eql;

#define REQUIRE_OPEN_DB(wrapper) \
  if(wrapper->closed || !wrapper->client->net.vio) { \
    rb_raise(cMysql2Error, "closed MySQL connection"); \
    return Qnil; \
  }

#define MARK_CONN_INACTIVE(conn) \
  wrapper->active = 0

#define GET_CLIENT(self) \
  mysql_client_wrapper *wrapper; \
  Data_Get_Struct(self, mysql_client_wrapper, wrapper)

/*
 * used to pass all arguments to mysql_real_connect while inside
 * rb_thread_blocking_region
 */
struct nogvl_connect_args {
  MYSQL *mysql;
  const char *host;
  const char *user;
  const char *passwd;
  const char *db;
  unsigned int port;
  const char *unix_socket;
  unsigned long client_flag;
};

/*
 * used to pass all arguments to mysql_send_query while inside
 * rb_thread_blocking_region
 */
struct nogvl_send_query_args {
  MYSQL *mysql;
  VALUE sql;
};

/*
 * non-blocking mysql_*() functions that we won't be wrapping since
 * they do not appear to hit the network nor issue any interruptible
 * or blocking system calls.
 *
 * - mysql_affected_rows()
 * - mysql_error()
 * - mysql_fetch_fields()
 * - mysql_fetch_lengths() - calls cli_fetch_lengths or emb_fetch_lengths
 * - mysql_field_count()
 * - mysql_get_client_info()
 * - mysql_get_client_version()
 * - mysql_get_server_info()
 * - mysql_get_server_version()
 * - mysql_insert_id()
 * - mysql_num_fields()
 * - mysql_num_rows()
 * - mysql_options()
 * - mysql_real_escape_string()
 * - mysql_ssl_set()
 */

static void rb_mysql_client_mark(void * wrapper) {
  mysql_client_wrapper * w = wrapper;
  if (w) {
    rb_gc_mark(w->encoding);
  }
}

static VALUE rb_raise_mysql2_error(MYSQL *client) {
  VALUE e = rb_exc_new2(cMysql2Error, mysql_error(client));
  rb_funcall(e, intern_error_number_eql, 1, INT2NUM(mysql_errno(client)));
  rb_funcall(e, intern_sql_state_eql, 1, rb_tainted_str_new2(mysql_sqlstate(client)));
  rb_exc_raise(e);
  return Qnil;
}

static VALUE nogvl_init(void *ptr) {
  MYSQL **client = (MYSQL **)ptr;

  /* may initialize embedded server and read /etc/services off disk */
  *client = mysql_init(NULL);
  return *client ? Qtrue : Qfalse;
}

static VALUE nogvl_connect(void *ptr) {
  struct nogvl_connect_args *args = ptr;
  MYSQL *client;

  do {
    client = mysql_real_connect(args->mysql, args->host,
                                args->user, args->passwd,
                                args->db, args->port, args->unix_socket,
                                args->client_flag);
  } while (! client && errno == EINTR && (errno = 0) == 0);

  return client ? Qtrue : Qfalse;
}

static void rb_mysql_client_free(void * ptr) {
  mysql_client_wrapper *wrapper = (mysql_client_wrapper *)ptr;

  /*
   * we'll send a QUIT message to the server, but that message is more of a
   * formality than a hard requirement since the socket is getting shutdown
   * anyways, so ensure the socket write does not block our interpreter
   */
  int fd = wrapper->client->net.fd;

  if (fd >= 0) {
    /*
     * if the socket is dead we have no chance of blocking,
     * so ignore any potential fcntl errors since they don't matter
     */
#ifndef _WIN32
    int flags = fcntl(fd, F_GETFL);
    if (flags > 0 && !(flags & O_NONBLOCK))
      fcntl(fd, F_SETFL, flags | O_NONBLOCK);
#else
    u_long iMode = 1;
    ioctlsocket(fd, FIONBIO, &iMode);
#endif
  }

  /* It's safe to call mysql_close() on an already closed connection. */
  if (!wrapper->closed) {
    mysql_close(wrapper->client);
  }
  xfree(ptr);
}

static VALUE nogvl_close(void * ptr) {
  mysql_client_wrapper *wrapper = ptr;
  if (!wrapper->closed) {
    mysql_close(wrapper->client);
    client->net.fd = -1;
    wrapper->closed = 1;
  }
  return Qnil;
}

static VALUE allocate(VALUE klass) {
  VALUE obj;
  mysql_client_wrapper * wrapper;
  obj = Data_Make_Struct(klass, mysql_client_wrapper, rb_mysql_client_mark, rb_mysql_client_free, wrapper);
  wrapper->encoding = Qnil;
  wrapper->active = 0;
  wrapper->closed = 0;
  return obj;
}
<commit_msg>was in a hurry earlier<commit_after>#include <mysql2_ext.h>
#include <client.h>
#include <errno.h>

VALUE cMysql2Client;
extern VALUE mMysql2, cMysql2Error;
static VALUE intern_encoding_from_charset;
static ID sym_id, sym_version, sym_async, sym_symbolize_keys, sym_as, sym_array;
static ID intern_merge, intern_error_number_eql, intern_sql_state_eql;

#define REQUIRE_OPEN_DB(wrapper) \
  if(wrapper->closed || !wrapper->client->net.vio) { \
    rb_raise(cMysql2Error, "closed MySQL connection"); \
    return Qnil; \
  }

#define MARK_CONN_INACTIVE(conn) \
  wrapper->active = 0

#define GET_CLIENT(self) \
  mysql_client_wrapper *wrapper; \
  Data_Get_Struct(self, mysql_client_wrapper, wrapper)

/*
 * used to pass all arguments to mysql_real_connect while inside
 * rb_thread_blocking_region
 */
struct nogvl_connect_args {
  MYSQL *mysql;
  const char *host;
  const char *user;
  const char *passwd;
  const char *db;
  unsigned int port;
  const char *unix_socket;
  unsigned long client_flag;
};

/*
 * used to pass all arguments to mysql_send_query while inside
 * rb_thread_blocking_region
 */
struct nogvl_send_query_args {
  MYSQL *mysql;
  VALUE sql;
};

/*
 * non-blocking mysql_*() functions that we won't be wrapping since
 * they do not appear to hit the network nor issue any interruptible
 * or blocking system calls.
 *
 * - mysql_affected_rows()
 * - mysql_error()
 * - mysql_fetch_fields()
 * - mysql_fetch_lengths() - calls cli_fetch_lengths or emb_fetch_lengths
 * - mysql_field_count()
 * - mysql_get_client_info()
 * - mysql_get_client_version()
 * - mysql_get_server_info()
 * - mysql_get_server_version()
 * - mysql_insert_id()
 * - mysql_num_fields()
 * - mysql_num_rows()
 * - mysql_options()
 * - mysql_real_escape_string()
 * - mysql_ssl_set()
 */

static void rb_mysql_client_mark(void * wrapper) {
  mysql_client_wrapper * w = wrapper;
  if (w) {
    rb_gc_mark(w->encoding);
  }
}

static VALUE rb_raise_mysql2_error(MYSQL *client) {
  VALUE e = rb_exc_new2(cMysql2Error, mysql_error(client));
  rb_funcall(e, intern_error_number_eql, 1, INT2NUM(mysql_errno(client)));
  rb_funcall(e, intern_sql_state_eql, 1, rb_tainted_str_new2(mysql_sqlstate(client)));
  rb_exc_raise(e);
  return Qnil;
}

static VALUE nogvl_init(void *ptr) {
  MYSQL **client = (MYSQL **)ptr;

  /* may initialize embedded server and read /etc/services off disk */
  *client = mysql_init(NULL);
  return *client ? Qtrue : Qfalse;
}

static VALUE nogvl_connect(void *ptr) {
  struct nogvl_connect_args *args = ptr;
  MYSQL *client;

  do {
    client = mysql_real_connect(args->mysql, args->host,
                                args->user, args->passwd,
                                args->db, args->port, args->unix_socket,
                                args->client_flag);
  } while (! client && errno == EINTR && (errno = 0) == 0);

  return client ? Qtrue : Qfalse;
}

static void rb_mysql_client_free(void * ptr) {
  mysql_client_wrapper *wrapper = (mysql_client_wrapper *)ptr;

  /*
   * we'll send a QUIT message to the server, but that message is more of a
   * formality than a hard requirement since the socket is getting shutdown
   * anyways, so ensure the socket write does not block our interpreter
   */
  int fd = wrapper->client->net.fd;

  if (fd >= 0) {
    /*
     * if the socket is dead we have no chance of blocking,
     * so ignore any potential fcntl errors since they don't matter
     */
#ifndef _WIN32
    int flags = fcntl(fd, F_GETFL);
    if (flags > 0 && !(flags & O_NONBLOCK))
      fcntl(fd, F_SETFL, flags | O_NONBLOCK);
#else
    u_long iMode = 1;
    ioctlsocket(fd, FIONBIO, &iMode);
#endif
  }

  /* It's safe to call mysql_close() on an already closed connection. */
  if (!wrapper->closed) {
    mysql_close(wrapper->client);
  }
  xfree(ptr);
}

static VALUE nogvl_close(void * ptr) {
  mysql_client_wrapper *wrapper = ptr;
  if (!wrapper->closed) {
    mysql_close(wrapper->client);
    wrapper->client->net.fd = -1;
    wrapper->closed = 1;
  }
  return Qnil;
}

static VALUE allocate(VALUE klass) {
  VALUE obj;
  mysql_client_wrapper * wrapper;
  obj = Data_Make_Struct(klass, mysql_client_wrapper, rb_mysql_client_mark, rb_mysql_client_free, wrapper);
  wrapper->encoding = Qnil;
  wrapper->active = 0;
  wrapper->closed = 0;
  return obj;
}

{'fraction_non_alphanumeric': 0.11136999068033551, 'fraction_numerical': 0.005591798695246971, 'mean_word_length': 3.691256830601093, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 62, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3994268', 'n_tokens_mistral': 3021, 'n_tokens_neox': 2950, 'n_words': 752}