QuickIO  0.2
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Classes | Macros | Typedefs | Enumerations | Functions | Variables
qev.h File Reference

Provides all the qev_* functions that are needed for creating an event loop. More...

#include <arpa/inet.h>
#include <errno.h>
#include <glib.h>
#include <glib/gstdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <openssl/ssl.h>
#include <stdio.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/times.h>
#include <sys/types.h>
#include <unistd.h>
#include "bench.h"
#include "buffer.h"
#include "cleanup.h"
#include "config.h"
#include "fair.h"
#include "http.h"
#include "job.h"
#include "json.h"
#include "latch.h"
#include "list.h"
#include "lock.h"
#include "log.h"
#include "mock.h"
#include "pool.h"
#include "queue.h"
#include "rsock.h"
#include "safe.h"
#include "stats.h"
#include "strfuncs.h"

Go to the source code of this file.

Classes

struct  qev_flags
 Any flags associated with a client. More...
 
struct  qev_client
 Contains all of the information needed for quick-event to have a functioning client. More...
 

Macros

#define GLIB_VERSION_MIN_REQUIRED   GLIB_VERSION_2_32
 Only allow glib 2.32 as that's the highest on Debian Wheezy.
 
#define GLIB_VERSION_MAX_ALLOWED   GLIB_VERSION_2_32
 Only allow glib 2.32 as that's the highest on Debian Wheezy.
 
#define _GNU_SOURCE
 Give us access to more features.
 
#define QEV_VERSION_MAJOR   0
 Current major version of quick-event.
 
#define QEV_VERSION_MINOR   2
 Current minor version of quick-event.
 
#define QEV_VERSION_MICRO   0
 Current micro version of quick-event.
 
#define VERSION_NAME   UNKNOWN
 Name of the application being compiled with the server.
 
#define VERSION_MAJOR   0
 Major version application being compiled with the server.
 
#define VERSION_MINOR   0
 Minor version application being compiled with the server.
 
#define VERSION_MICRO   0
 Micro version application being compiled with the server.
 
#define QEV_SSL_CIPHERS   "HIGH:!aNULL:!MD5:"
 Whatever ciphers SSL should use.
 
#define QEV_CLIENT   qev_client
 If no client was configured externally, default to qev_client.
 
#define QEV_MS_TO_USEC(ms)   (ms * 1000)
 Convert milliseconds to microseconds. More...
 
#define QEV_MS_TO_NSEC(ms)   (QEV_MS_TO_USEC(ms) * 1000)
 Convert milliseconds to nanoseconds. More...
 
#define QEV_SEC_TO_USEC(secs)   QEV_MS_TO_USEC(secs * 1000)
 Convert seconds to microseconds. More...
 
#define QEV_YIELD_AFTER   1024
 The number of spins anything should yield after.
 
#define QEV_WAIT_FOR(cond)
 Waits for a condition to be true, yielding in the process if it waits too long. More...
 

Typedefs

typedef int qev_fd_t
 Sockets are just ints.
 
typedef struct qev_timeout qev_timeout_t
 You're never allowed to mess with timeout internals.
 
typedef void(* qev_cb )()
 A single callback that takes nothing and returns nothing.
 
typedef void(* qev_free_fn )(void *)
 Function type for a typical free function.
 
typedef qev_free_fn qev_data_cb
 Function type for something that recieves an argument.
 
typedef void(* qev_client_cb )(struct QEV_CLIENT *client, void *data)
 A callback that takes a single client.
 

Enumerations

enum  qev_close_reasons {
  QEV_CLOSE_HUP, QEV_CLOSE_READ_FAIL, QEV_CLOSE_TIMEOUT, QEV_CLOSE_OS_ERROR,
  QEV_CLOSE_OUT_OF_MEM, QEV_CLOSE_EXITING, QEV_CLOSE_LEN
}
 The reasons a client might be closed. More...
 

Functions

void qev_init (const gchar *app_name, gchar **argv, gint argc)
 Prepares QEV to run. More...
 
void qev_run ()
 Spawns all worker threads and starts QEV running.
 
void qev_kill ()
 Unblocks all threads waiting for QEV to exit. More...
 
void qev_wait_for_exit ()
 Allows you to wait for QEV to exit; really, this is a way to block the main thread while QEV is running. More...
 
void qev_exit ()
 Kill and wait for QEV to exit in one fell swoop. More...
 
void qev_listen (const gchar *ip_address, const guint16 port)
 Instruct quick event to listen on a socket for connections and route them into the event handler. More...
 
void qev_listen_ssl (const gchar *ip_address, const guint16 port, const gchar *cert_path0, const gchar *key_path0, const gchar *cert_path1, const gchar *key_path1)
 Instruct quick event to listen on an SSL socket for connections and route them into the event handler. More...
 
void qev_listen_unix (const gchar *path)
 Instruct quick event to create a Unix socket at the given path and listen on it. More...
 
void qev_listen_udp (const gchar *ip_address, const guint16 port)
 Instruct quick event to listen on on a UDP socket for messages. More...
 
void qev_chuser (const char *username)
 Run as this user.
 
void qev_setnofile (const gint nofile)
 Set the limits for the number of open files for this process. More...
 
void qev_timer (const qev_cb fn, const guint seconds, const guint ms)
 Add a callback to be fired on a timer. More...
 
const gchar * qev_get_hostname ()
 Get the name of this host. More...
 
struct QEV_CLIENTqev_surrogate_new ()
 Create a surrogate client. More...
 
GString * qev_surrogate_flush (struct QEV_CLIENT *surrogate)
 Steal the entire write buffer from the surrogate client. More...
 
void qev_write (struct QEV_CLIENT *client, const gchar *buff, const gsize len)
 Writes data to the client. More...
 
void qev_writef (struct QEV_CLIENT *client, const gchar *format,...) G_GNUC_PRINTF(2
 Allows you to use qev_write in a printf() style. More...
 
void void qev_close (struct QEV_CLIENT *client, guint reason)
 Close and free the client when it is safe to do so. More...
 
gboolean qev_is_surrogate (struct QEV_CLIENT *client)
 Determine if a client is a surrogate. More...
 
gboolean qev_is_closing (struct QEV_CLIENT *client)
 Check if a client is closing. More...
 
void qev_foreach (qev_client_cb cb, gint threads, void *data)
 Runs the callback on all clients. More...
 
struct QEV_CLIENTqev_ref (struct QEV_CLIENT *client)
 Take a reference to the client.
 
void qev_unref (struct QEV_CLIENT *client)
 Release a reference to the client.
 
void qev_unref0 (struct QEV_CLIENT **client)
 Release a reference to the client and set the corresponding memory location to NULL.
 
void qev_unref_as_free (void *client_)
 So that you can use it as a free function without a cast.
 
void qev_lock (struct QEV_CLIENT *client)
 Acquire a lock on a client. More...
 
void qev_unlock (struct QEV_CLIENT *client)
 Release a lock on a client. More...
 
void qev_timeout (struct QEV_CLIENT *client, qev_timeout_t **timeout)
 Set a timeout on a client. More...
 
void qev_timeout_clear (qev_timeout_t **timeout)
 Clear a timeout on a client and release your reference to the timeout. More...
 
void qev_chuser (const gchar *username)
 Change to a different user. More...
 
void qev_on_before_run ()
 Before the server is about to run (right before when the QEV threads are set into the event loop), this function will be executed to allow you to create pools, do app init, and all that good stuff.
 
void qev_on_open (struct QEV_CLIENT *client)
 Notification that a new client was accepted. More...
 
void qev_on_close (struct QEV_CLIENT *client, guint reason)
 Notification that a client has closed / been closed. More...
 
void qev_on_read (struct QEV_CLIENT *client)
 A notification that the client has data for reading. More...
 
void qev_on_udp (const gchar *msg, const gsize len, const gchar *ip)
 A notification that there is a new UDP message waiting. More...
 
void qev_on_tick ()
 Fired after every iteration of the event loop from every QEV thread. More...
 
void qev_on_exit ()
 A notification that QEV is going to shut down. More...
 
struct QEV_CLIENTqev_client_new ()
 Create a new client using whatever memory allocator you wish and sized appropriately for your needs. More...
 
void qev_client_free (struct QEV_CLIENT *client)
 Free the client allocated with qev_client_new(). More...
 

Variables

gint64 qev_time
 An approximation of the current time, set from g_get_real_time(), updated at least every 100ms.
 
gint64 qev_monotonic
 An approximate monotonic time, set from g_get_monotonic_time(), updated at least every 100ms.
 

Detailed Description

Provides all the qev_* functions that are needed for creating an event loop.

In order to interact with QEV, you're required to create the following functions in your program in a way that QEV can see them: 0) qev_on_before_run(); 1) qev_on_open(struct QEV_CLIENT *client); 2) qev_on_close(struct QEV_CLIENT *client, guint reason); 3) qev_on_read(struct QEV_CLIENT *client); 4) qev_on_udp(const gchar *msg, const gssize len, const gchar *ip); 5) qev_on_tick(); 6) qev_on_exit(); 7) qev_client_new(); 8) qev_client_free(struct QEV_CLIENT *client);

See the function definitions for information about what each function does.

Author
Andrew Stone andre.nosp@m.w@cl.nosp@m.ovar..nosp@m.com

Macro Definition Documentation

#define QEV_MS_TO_NSEC (   ms)    (QEV_MS_TO_USEC(ms) * 1000)

Convert milliseconds to nanoseconds.

Just so it's easier to read.

Parameters
msThe number of milliseconds to put into nanoseconds.
#define QEV_MS_TO_USEC (   ms)    (ms * 1000)

Convert milliseconds to microseconds.

Just so it's easier to read.

Parameters
msThe number of milliseconds to put into microseconds.
#define QEV_SEC_TO_USEC (   secs)    QEV_MS_TO_USEC(secs * 1000)

Convert seconds to microseconds.

Just so it's easier to read.

Parameters
secsThe number of seconds to put into microseconds.
#define QEV_WAIT_FOR (   cond)
Value:
{ \
register guint spins = 0; \
while (!(cond)) { \
if (++spins > QEV_YIELD_AFTER) { \
g_thread_yield(); \
} \
}}
#define QEV_YIELD_AFTER
The number of spins anything should yield after.
Definition: qev.h:153

Waits for a condition to be true, yielding in the process if it waits too long.

Enumeration Type Documentation

The reasons a client might be closed.

Enumerator
QEV_CLOSE_HUP 

The client's socket hung up or timed out.

QEV_CLOSE_READ_FAIL 

A read failed.

QEV_CLOSE_TIMEOUT 

The client timed out.

QEV_CLOSE_OS_ERROR 

A system call failed somewhere and the client must die.

QEV_CLOSE_OUT_OF_MEM 

Memory pressure has been hit, and the client is being closed as a result.

QEV_CLOSE_EXITING 

The server is exiting and on its way to shutdown.

QEV_CLOSE_LEN 

The number of items in this enum.

Function Documentation

void qev_chuser ( const gchar *  username)

Change to a different user.

This function will refuse to run as root and return and error if you try to.

Parameters
usernameThe username to run as
void qev_client_free ( struct QEV_CLIENT client)

Free the client allocated with qev_client_new().

This must be used to completely clean up all memory allocated for the client.

struct QEV_CLIENT* qev_client_new ( )

Create a new client using whatever memory allocator you wish and sized appropriately for your needs.

The returned client must be zerod out and ready for use.

void void qev_close ( struct QEV_CLIENT client,
guint  reason 
)

Close and free the client when it is safe to do so.

After calling this, no more read callbacks will be fired on this client, and you will receive the close callback only when all the underlying polling mechanisms have synced.

Parameters
clientThe client to destroy.
reasonWhy the client is being destroyed.
void qev_exit ( )

Kill and wait for QEV to exit in one fell swoop.

Note
This function will block forever if you call it from a QEV thread.
void qev_foreach ( qev_client_cb  cb,
gint  threads,
void *  data 
)

Runs the callback on all clients.

Note
When called from a QEV thread, this function acquires no locks, and it's really rather efficient when compared to calling from a non-QEV thread.
If a client closes while iterating the list, a callback will not be fired for that client. Likewise, if a client connects while iterating, there will be no callback for him. Due to the nature of lock-free iterating, however, it's possible that a client will recieve multiple callbacks, so be ready for that.
Parameters
cbThe callback to fire
threadsThe number of jobs that should be sent to QEV's thread pool. Less than 0 means use the default number of threads (config value "job-threads"). 0 and 1 mean that no job will be sent and this will execute in a single thread. Anything else is just the number of threads.
dataData to give to each callback
const gchar* qev_get_hostname ( )

Get the name of this host.

By default, it uses quick-event's config option "hostname" as the value but falls back to g_get_host_name() in the event that that wasn't set.

void qev_init ( const gchar *  app_name,
gchar **  argv,
gint  argc 
)

Prepares QEV to run.

This function MUST be called before QEV can do anything.

Parameters
app_nameThe name of your application. Used for stats reporting, monitoring, and the like. Make sure this is a static string, or you're gonna have a bad time.
argvPretty much main()'s argv
argcmain()'s argc
gboolean qev_is_closing ( struct QEV_CLIENT client)

Check if a client is closing.

Parameters
clientThe client to test
Returns
If the client is closing
gboolean qev_is_surrogate ( struct QEV_CLIENT client)

Determine if a client is a surrogate.

Parameters
clientThe client to test
Returns
If the client is a surrogate
void qev_kill ( )

Unblocks all threads waiting for QEV to exit.

After calling this, at least 1 thread MUST call qev_wait_for_exit() in order for QEV to clean up after itself; typically, the main thread of the application will already be waiting.

void qev_listen ( const gchar *  ip_address,
const guint16  port 
)

Instruct quick event to listen on a socket for connections and route them into the event handler.

Parameters
ip_addressThe IP address to listen on
portThe port to listen on
void qev_listen_ssl ( const gchar *  ip_address,
const guint16  port,
const gchar *  cert_path0,
const gchar *  key_path0,
const gchar *  cert_path1,
const gchar *  key_path1 
)

Instruct quick event to listen on an SSL socket for connections and route them into the event handler.

You may pass in both RSA and EC/DSA certificates and keys; each certificate is expected to be a certificate chain that will be given to clients.

Parameters
ip_addressThe IP address to listen on
portThe port to listen on
cert_path0The path to the server's CA file
key_path0The path to the server's private key file in PEM
cert_path1The path to another CA file
key_path1The path to another private key file in PEM
void qev_listen_udp ( const gchar *  ip_address,
const guint16  port 
)

Instruct quick event to listen on on a UDP socket for messages.

Parameters
ip_addressThe IP address to listen on
portThe port to listen on
void qev_listen_unix ( const gchar *  path)

Instruct quick event to create a Unix socket at the given path and listen on it.

This is mainly for getting around the TCP/IP limit of 65K clients and is therefore only used for streaming sockets, not datagram.

Parameters
pathThe path for the socket
void qev_lock ( struct QEV_CLIENT client)

Acquire a lock on a client.

This function will busy wait, while yielding its run time, until it is able to acquire a lock on a client, so you probably shouldn't use this for things like long-blocking IO operations, or other things that take a while.

Note
This is a reentrant lock.
Parameters
clientThe client to acquire the lock on.
void qev_on_close ( struct QEV_CLIENT client,
guint  reason 
)

Notification that a client has closed / been closed.

At this point, you may write a final farewell message to the client so that it knows why it's being killed.

Parameters
clientThe client that closed.
reasonThe reason the client closed.
void qev_on_exit ( )

A notification that QEV is going to shut down.

In this function, it's a good idea to tear down ALL parts of your application that call ANY qev_* functions. When this function is called, all QEV threads have exited, so there will be no future callbacks.

void qev_on_open ( struct QEV_CLIENT client)

Notification that a new client was accepted.

Parameters
clientThe client that just opened [transfer-none]
void qev_on_read ( struct QEV_CLIENT client)

A notification that the client has data for reading.

Note
The data for the client is in rbuff in the client struct.
Attention
Data MAY ONLY be read and removed from the client's rbuff; expanding it will result in incorrect memory pressure calculations.
Parameters
clientThe client ready for reading [transfer-none]
void qev_on_tick ( )

Fired after every iteration of the event loop from every QEV thread.

This is mainly used to execute periodic events that don't need to be on a timer.

void qev_on_udp ( const gchar *  msg,
const gsize  len,
const gchar *  ip 
)

A notification that there is a new UDP message waiting.

Parameters
msgThe data that was received
lenThe length of the data
ipWhere the dat came from
void qev_setnofile ( const gint  nofile)

Set the limits for the number of open files for this process.

It is a fatal error if the OS denies the request.

GString* qev_surrogate_flush ( struct QEV_CLIENT surrogate)

Steal the entire write buffer from the surrogate client.

Parameters
surrogateThe surrogate to flush from
Returns
The surrogate's write buffer
struct QEV_CLIENT* qev_surrogate_new ( )

Create a surrogate client.

A surrogate client is really just a fake client that has no active socket behind it and is useful for multiplexing a bunch of clients onto a single, real client.

A surrogate client is identical to a real client with the following exceptions:

  • The client WILL NEVER fire an on_read event. It is up to the application to route read events from real clients to surrogates.
  • Writes to the client will just buffer into userspace until flushed to a real client; see qev_surrogate_flush().
  • The client MUST be closed manually.
Returns
A new surrogate, or NULL if there are too many clients already
void qev_timeout ( struct QEV_CLIENT client,
qev_timeout_t **  timeout 
)

Set a timeout on a client.

Setting a timeout on an already active timeout overwrites the previous one.

Note
If a client is in the process of being closed, no timeout will be set.
You SHOULD call qev_timeout_clear() in qev_on_close() so that the client can be cleaned up as quickly as possible. Otherwise, the timeouts will remain in memory with the reference to the client until they are fired.
Parameters
clientThe client to set the timeout on
timeoutThe location where the timeout should be written.
void qev_timeout_clear ( qev_timeout_t **  timeout)

Clear a timeout on a client and release your reference to the timeout.

Parameters
timeoutThe location of the timeout to clear
void qev_timer ( const qev_cb  fn,
const guint  seconds,
const guint  ms 
)

Add a callback to be fired on a timer.

Attention
There is no way to disable or remove a timer; these timers are not for one-off events.
Note
Timers will never overlap; if a timer backs up, it will be fired from the same thread right after the previous timer callback returns.
This is the only non-static part of QEV simply because each timer needs a different callback, and making that static is pretty much a pointless mess.
Parameters
fnThe function to be called on a timer.
secondsThe number of seconds between fn calls
msThe number of milliseconds (in addition to seconds) between fn calls.
void qev_unlock ( struct QEV_CLIENT client)

Release a lock on a client.

Parameters
clientThe client to release the lock on.
void qev_wait_for_exit ( )

Allows you to wait for QEV to exit; really, this is a way to block the main thread while QEV is running.

Note
This function will block forever if you call it from a QEV thread.
void qev_write ( struct QEV_CLIENT client,
const gchar *  buff,
const gsize  len 
)

Writes data to the client.

Attention
This function acquires a lock on a client, and as the lock is not reentrant, it must not be held by the caller, or this will block forever.
Parameters
clientThe client to write to.
buffThe buffer to send to the client
lenThe amount of data in the buffer
void qev_writef ( struct QEV_CLIENT client,
const gchar *  format,
  ... 
)

Allows you to use qev_write in a printf() style.

Parameters
clientThe client to write to
formatThe string format
...The parameters for the format