QiblaDriver

Required Methods

The following methods should be invoked by the Cairo Application Object Server only. Casbah application developers should not need to use these methods. A conformant Cairo implementation must invoke these methods in this order.

In addition to these, __cb_info__() must also be implemented.

__cb_init__()

Table 1. __cb_get__ method

return type

method name

method arguments

void

__cb_init__()

(CaDict options)

__cb_init__() asks a Qibla driver instance to configure itself based on the options being handed to it. __cb_init__() is the constructor so it is only invoked when the system administrator is setting up a server. __cb_init__() must not be invoked at server startup by Cairo. __cb_init__() must not actually create any network sockets or attach to any shared memory segments. __cb_init__() must only fill in the instance variables of this object in preparation for a call to __cb_setup__()

Since each Qibla driver will speak a different protocol, each one will support different configuration options at bind time. This is possible because a CaDict is supplied to __cb_init__(). Any QiblaDriver which needs the options from the following table must use these names. All of the following are optional. A driver must use the default supplied in the following table if it requires an option that is not supplied. A driver may consider it an error if a required option is not in the table below and is not supplied in the input dictionary to the __cb_init__() method.

Table 2. __cb_init__() options

Datatype

Meaning

Default

Other

?

ip-address

CaString

IP address (in String form) that the driver must bind to. The special addresses "NULL" and "*" should bind to all addresses on the machine, and "localhost" or "loopback" should bind to the "loopback" address (127.0.0.1 in IPv4).

"*"

none required

tcp-port

CaInt32

Create a TCP socket and bind it to this port on the address supplied in ip-address. This option may be supplied along with the udp-port option.

no default

ip-address

tcp-sockopt-backlog

CaInt32

Set TCP accept queue depth. A value less than 1 must be viewed as using the operating system default value. (If no default exists for the OS, the largest possible queue must be used.) This value must only affect the TCP socket used to accept clients.

no default

tcp-port

tcp-client-sockopt-sndbuffer

CaInt32

Set the size of the TCP send buffer. This is a low-level OS setting that may not be available on all platforms. Drivers which cannot support this option must ignore it. This option must only affect the result client socket created by __cb_accept_one_client__(). It may affect the socket used to listen for connections.

operating system default

tcp-port

tcp-client-sockopt-rcvbuffer

CaInt32

Set the size of the TCP receive buffer. This is a low-level OS setting that may not be available on all platforms. Drivers which cannot support this option must ignore it. This option must only affect the result client socket created by __cb_accept_one_client__(). It may affect the socket used to listen for connections.

operating system default

tcp-port

udp-port

CaInt32

Create a UDP socket and bind it to this port on the address supplied in ip-address. This option may be supplied with the tcp-port option.

no default

ip-address

unix-socket

CaString

String form of the Unix path at which to create a Unix socket. Unix sockets are only available on Unix-based operating systems. Some drivers may use this for a "higher-speed" connection.

no default

none required

sysv-ipc-sem

CaInt32

The id of a System V IPC semaphore. There is no way to supply IPC_PRIVATE. System V IPC is not available on all machines or configurations.

no default

none required

sysv-ipc-shm

CaInt32

The id of a System V IPC shared memory segment. There is no way to supply IPC_PRIVATE. System V IPC is not available on all machines or configurations.

no default

none required

sysv-ipc-msg

CaInt32

The id of a System V IPC message queue. There is no way to supply IPC_PRIVATE. System V IPC is not available on all machines or configurations.

no default

none required

lock-file

CaString

The path of a file in the OS filesystem. This file may be used as a lock file to coordinate access to some shared resource like a shared memory buffer or a shared socket. This file must be created (if it does not exist) by the driver. The driver must not give an error if the file already exists, it must only return an error if it cannot use the file as a lock. The exact OS locking method used is up to the driver.

no default

none required

shared-buffer-file

CaString

The path of a file in the OS filesystem. This file may be used as a shared memory buffer. The exact method of using this file as a shared buffer is left up to the driver. a A driver may use this file as an ordinary file, using normal read and write calls to move data into and out of it.

no default

none required

unix-fifo

CaString

The path of a file in the base operating system's file system. This file should be used as a FIFO queue. FIFOs are special files handled by the Unix operating system kernel that allows writers and readers to write to (and read from) a file as if it were a network stream.

no default

none required

Notes:
a. Common schemes are mmap(2) (on Unix), or shared arenas on SGI's Irix.

The options tcp-client-sockopt-sndbuffer and tcp-client-sockopt-rcvbuffer are placed here to allow runtime fine-tuning of driver instances. These must be used with extreme attention to detail. Driver authors should support these options; but they may override the option value with their own values tuned for their specific driver.

__cb_setup__()

Table 3. __cb_setup__() method

return type

method name

method arguments

CaBoolean

__cb_setup__()

()

__cb_setup__() asks the driver instance to create any shared memory segments that it needs, or to clear and setup any locks or memory buffers that it requires. __cb_setup__() must be invoked only once, in a single thread, prior to __cb_bind__() being invoked.

__cb_setup__() should create any shared memory segments that are not defined yet, and it must also initalize them to a known state. [3] __cb_bind__() will be executed in multiple independent threads simultaneously; it should, therefore, only create network sockets or attach to shared memory segments.

Note: the driver must return immediately from this method when the setup is complete; i.e., it must not block in an event-loop. The purpose of this method is only to begin to create the server socket, not to handle incoming client connections.

__cb_setup__() must return TRUE if the setup procedure was successful, otherwise it should throw an appropriate exception. __cb_setup__() may return FALSE, applications must expect a return value of FALSE. If FALSE is returned by __cb_setup__() __cb_bind__() must not be called.

__cb_bind__()

Table 4. __cb_bind__() method

return type

method name

method arguments

CaBoolean

__cb_bind__()

()

__cb_bind__() will be invoked by Cairo multiple times. In a Cairo Application Object Server that is implemented using multiple Unix processes, it will be necessary to invoke __cb_bind__() in each process. __cb_bind__() should actually create and configure the sockets, attach to shared memory segments or semaphores, and open any necessary files (such as locks or FIFOs). After __cb_bind__() completes, the driver should be ready to invoke __cb_accept_one_client__().

On platforms that support it, the author must use setsockopt(2) to configure the socket so that Cairo can reuse the local address (setsockopt option is SO_REUSEADDR). This is an important detail that shouldn't be neglected: some implementations of Cairo will rely on it.

__cb_bind__() must return TRUE if the bind procedure was successful, otherwise it should throw an appropiate error. __cb_bind__() may return FALSE, applications must expect a return value of FALSE. If __cb_bind__() returns FALSE, __cb_unbind__() must be called in all processes in which __cb_bind__() returned TRUE, followed by a call to __cb_cleanup__().

__cb_accept_one_client__()

Table 5. __cb_accept_one_client__() method

return type

method name

method arguments

CaBoolean

__cb_accept_one_client__()

()

Accept a single client and return an object to hold all data associated with a connection. This method should be used to get the client attached to the server and to obtain information about how the client is connected [4] For most protocols, actual protocol conversations should be delayed until the call to __cb_handle_connection__().

Cairo must ensure that only one thread at any point in time may execute __cb_accept_one_client__().

The object returned must be of a type created by the QiblaDriver author in order to hold the state of the connection. This object must implement the __cb_handle_connection__() method, and must be subclassed from QiblaConnection.

If the QiblaDriver author needs to access the QiblaDriver instance while inside of the method __cb_handle_connection__() a pointer to the driver instance must be stored in the client object that is returned. Access to the QiblaDriver instance is restricted while inside of __cb_handle_connection__(). See __cb_handle_connection__() for more information.

__cb_unbind__()

Table 6. __cb_unbind__() method

return type

method name

method arguments

void

__cb_unbind__()

()

Unbinds the communications sockets used by this instance of the driver. __cb_unbind__() closes any listen sockets and stops accepting connections in the current process. __cb_unbind__() must detach from any shared memory segments that the driver is utilizing or any inter-process locks/semaphores to which the driver has attached.

A driver must not be unbound until all of its currently active connections have closed and all __cb_handle_connection__() calls have returned. This allows the QiblaDriver to store global state information in the driver instance itself.

Any clients that may be queued up waiting for a call to __cb_accept_one_client__() must be disconnected and thrown away when __cb_unbind__() is invoked.

__cb_unbind__() must be invoked once per process. __cb_cleanup__() will be invoked once, allowing the driver to cleanup shared memory segments or files that are left around. See __cb_cleanup__().

__cb_cleanup__()

Table 7. __cb_cleanup__() method

return type

method name

method arguments

void

__cb_cleanup__()

()

__cb_cleanup__() must be invoked only once for a Cairo server instance. After __cb_cleanup__() is invoked, __cb_setup__() must be invoked in order to begin restarting services offered by Cairo. __cb_cleanup__() must be invoked in a single thread of execution. __cb_cleanup__() must be invoked after all processes, including the one that is invoking __cb_cleanup__(), have invoked __cb_unbind__() on this driver.

__cb_info__()

The __cb_info__() method must be implemented in QiblaDriver. __cb_info__() returns a dictionary of driver metadata. The following key/value pairs must be returned in __cb_info__()'s dictionary.

Table 8. __cb_info__() method

return type

method name

method arguments

CaDict

__cb_info__

()

Table 9. __cb_info__() key/value pairs

Key Name (type)

Example Value (type)

Description

name (CaString)

QiblaHTTP (CaString)

A short, descriptive filename-like name for the driver.

description (CaString) (CaString)

Provides HTTP protocol access to Cairo Application Object Server (CaString)

A sentence or two that describes the functions the driver performs.

author (CaString)

Scott Miller (CaString)

The full name of the primary developer of the driver.

contact (CaString)

(CaString)

Contact information for the driver author; typically an email address.

api (CaString)

qibla driver (CaString)

Specifies which API the driver implements. For QiblaDriver objects, this is always the string "qibla driver".

revision (CaString)

1.15 (CaString)

The CVS driver revision. Used for quality control and support. This is not the API version number.

resource (CaList)

tcpip-port/2853

Contains a CaList of mapped resources the driver is using

Optional Methods

__cb_listen_socket__()

Table 10. __cb_cleanup__() method

return type

method name

method arguments

CaInt32

__cb_listen_socket__()

()

Allows a QiblaDriver to optimize itself for a Cairo server. __cb_listen_socket__() returns a file descriptor which can be placed into a select(2) call with other file descriptors, allowing a Cairo server to use only one thread to handle multiple QiblaDriver instances. A Cairo server must not require this method for QiblaDrivers to function correctly. Driver may return a value of -1 to indicate that no listen socket is appropiate for the instance. A Cairo server must recognize a return value of -1 as equivlant to __cb_listen_socket__() not being implemented. This method may not function at all in some OSes.[5]

Notes

[1]

Can be called multiple times, once per process.

while(TRUE)
 {
   client = __cb_accept_one_client__()
   spawn_new_thread(client, __cb_handle_connection__())
 } 
// wait for all currently open connections to close

[3]

These two actions are necessary only if the driver utilizes shared memory segments or mutexes.

[4]

For example, the IP address that the client is connected to.

[5]

See accept(2) and select(2) manpages on a Unix machine. The socket returned by listen_socket should be the same socket as used by accept(2), and should be placed in non-blocking mode.