Member of The Internet Defense League Últimos cambios
Últimos Cambios
Blog personal: El hilo del laberinto Geocaching

Application Programming Interface (A.P.I.)

Última Actualización: 07 de Agosto de 2002 - Miércoles


Página en construcción...


Historia

Olimpo es un framework diseñado para soportar módulos externos, en muchos casos cargables y descargables de forma dinámica.

Para poder intercomunicar dichos módulos con el núcleo funcional de Olimpo, se ha definido una interfaz, API, accesible desde los lenguajes C y Python.

La invocación de funciones Olimpo ANTES de que el framework llame a la rutina "inicio()" del módulo, tiene un resultado indefinido. En particular, no se garantiza la identidad devuelta por el API "IPC".

Salvo que se indique lo contrario de forma explícita, estas funciones no son Thread Safe. La ejecución de una rutina NO Thread Safe desde un thread distinto del principal, tiene un resultado indefinido (incluyendo la caída de Olimpo). Si un thread distinto al principal necesita invocar funciones prohibidas, puede hacerlo, por ejemplo, mediante colas e IRQ.


MODULE

C: int inicio(void);
Python: inicio()

Proporciona la interfaz básica utilizada por cualquier módulo.

Cuando se carga un módulo dinámico, se ejecuta la rutina "inicio", responsable de la inicialización del módulo y de la activación de las funciones "callback" que se vayan a utilizar.

Esta rutina sólo se invoca cuando se carga el módulo, y se invoca de forma automática.

No debería invocarse ninguna función del framework antes de que éste llame a esta función, ya que el resultado sería indefinido. Esto es especialmente importante en el caso de módulos escritos en Python, ya que pueden contener código global que se ejecuta en el mismo instante en que se importa el módulo en Olimpo.

C: void comentario_modulo(char *comentario);
Python: Olimpo.comentario_modulo(comentario);

Permite especificar un comentario para el módulo actual. El comentario es visible en dllist.

C: void especifica_fin(void (*fin) (void));
Python: Olimpo.especifica_fin(fin)

Indicamos qué rutina queremos que sea invocada cuando el usuario descargue el módulo, o cuando finalice la ejecución de Olimpo.

La rutina a ejecutar en ese caso no recibe ningún parámetro.

Esta rutina debe liberar todos los recursos utilizados, como bases de datos, memoria, etc. No es necesario desregistrar callbacks, ya que Olimpo lo hace automáticamente al descargar un módulo.

C: void hace_log(int nick, char *comando);
Python: Olimpo.hace_log(nick, comando)

Indicamos a Olimpo que queremos hacer log del comando especificado.

C: void hace_log2(char *comando);
Python: Olimpo.hace_log2(comando)

Indicamos a Olimpo que queremos hacer log del comando especificado.

C: int debug();
Python: Olimpo.debug()

Esta función nos indica si el framework Olimpo en el que se ha cargado el módulo está compilado en modo desarrollo o en modo producción.


IPC

Este módulo cobija funciones de comunicación entre módulos y entre threads.

C: char *nombre_modulo();
Python: Olimpo.ipc.nombre_modulo()

Esta función nos devuelve el nombre del módulo actual.

En C, el puntero devuelto señala a una cadena terminada en cero. Dicha cadena NO debe modificarse en modo alguno.

Thread Safe
C: int existe_nombre_modulo(char *nombre);
Python: Olimpo.ipc.existe_nombre_modulo(nombre)

Esta función nos dice si en el sistema existe algún módulo con el nombre indicado.

Útil, por ejemplo, para que un thread verifique que está comunicándose con la instancia correcta, sobre todo ante cargas y descargas de módulos en el sistema.

Thread Safe
C: int id_modulo(char *nombre);
Python: Olimpo.ipc.id_modulo(nombre)

Esta función nos devuelve el identificador de un módulo determinado.

La utilidad de esta función reside, básicamente, en distinguir diferentes instancias de un mismo módulo.

Útil, por ejemplo, para que un thread verifique que está comunicándose con la instancia correcta, sobre todo ante cargas y descargas de módulos en el sistema.

Olimpo garantiza que los identificadores son únicos durante la duración de la ejecución actual del programa.

Si no existe ningún módulo con el nombre indicado, el identificador devuelto es -1. Se garantiza que ningún módulo del sistema tendrá dicho identificador.

Thread Safe
C: int existe_id_modulo(int id);
Python: Olimpo.ipc.existe_id_modulo(id)

Esta función nos dice si en el sistema existe algún módulo con el identificador indicado.

Útil, por ejemplo, para que un thread verifique que está comunicándose con la instancia correcta, sobre todo ante cargas y descargas de módulos en el sistema.

C: void IRQ_handler(void (*func) (void));
Python: Olimpo.ipc.IRQ_handler(func)

Esta función define un callback invocable desde "IRQ_nombre()" o "IRQ_id()".

Si se indica una función NULL (en C) o None (en Python), el callback se desactiva.

Obsérvese que esta rutina NO es Thread Safe.

Thread Safe
C: int IRQ_nombre(char *modulo);
Python: Olimpo.ipc.IRQ_nombre(modulo)

Esta función indica nuestro interés en invocar el handler de interrupciones del módulo especificado.

Si el módulo especificado no existe, la llamada es ignorada y se devuelve un cero.

Olimpo no garantiza una latencia mínima en la ejecución del handler.

La ejecución de llamadas repetidas a esta función, con el mismo módulo destino, suponen una única llamada al handler. Esto es cierto incluso aunque las llamadas provengan de threads o módulos distintos.

Thread Safe
C: int IRQ_id(int id);
Python: Olimpo.ipc.IRQ_id(id)

Esta función indica nuestro interés en invocar el handler de interrupciones del módulo con el identificador especificado.

Las características son iguales a las de la rutina anterior.

Python: Olimpo.ipc.obj_add(clave, objeto)

Función disponible en módulos Python.

Esta función publica un objeto en Olimpo, con la clave especificada.

Si publicamos un objeto con la misma clave que uno ya existente, el anterior se elimina.

Obsérvese que esta rutina NO es Thread Safe.

Thread Safe
Python: Olimpo.ipc.obj_add2(nombre_modulo, id_modulo, clave, objeto)

Función disponible en módulos Python.

Esta función publica un objeto en Olimpo, con la clave especificada.

Un módulo sólo debería publicar objetos utilizando su propio nombre e identificador de módulo, a menos que tenga muy claro qué está haciendo. El uso incorrecto de esta función puede suponer, por ejemplo, la creación de bucles en las estructuras de datos o la eliminación de objetos publicados cuando se descarga un módulo que no tiene nada que ver.

Si publicamos un objeto con la misma clave que uno ya existente, el anterior se elimina.

Esta función es útil para que un módulo publique objetos desde un thread que no es el principal, por ejemplo.

Thread Safe
Python: Olimpo.ipc.obj_del(clave)

Función disponible en módulos Python.

Esta función elimina un objeto en Olimpo, con la clave especificada.

La rutina devuelve un cero si el objeto no existía.

En buena lógica, un módulo sólo debería eliminar los objetos publicados por él mismo, no por otros módulos, a menos que tenga muy claro qué está haciendo.

Thread Safe
Python: Olimpo.ipc.obj(clave)

Función disponible en módulos Python.

Esta función devuelve el objeto especificado. El resultado es una tupla compuesta por: nombre del módulo que publica el objeto, id del módulo en cuestión y objeto propiamente dicho.

Si el objeto fue publicado por un módulo que ya no está cargado (aunque puede haberse cargado otra instancia con posterioridad), se eliminan todos los objetos publicados por ese módulo que ya no existe, y la rutina devuelve un resultado acorde con la inexistencia de la clave solicitada.

Si el objeto no existe, la tupla que se devuelve es "(None, -1, None)".

Una vez devuelto el objeto, no tenemos ninguna garantía de cuánto tiempo va a persistir, ya que su módulo madre puede decidir despublicarlo o ser descargado en cualquier momento.

Thread Safe
Python: Olimpo.ipc.del_id_objects(id)

Función disponible en módulos Python.

Esta función destruye todos los objetos publicados en el módulo indicado.

La rutina devuelve el número de objetos que el módulo tenía publicados.

La intención de esta rutina es eliminar los objetos publicados por un módulo cuando se va a descargar.

En buena lógica, un módulo sólo debería eliminar los objetos publicados por él mismo, no por otros módulos, a menos que tenga muy claro qué está haciendo.

Thread Safe
Python: Olimpo.ipc.get_objects()

Función disponible en módulos Python.

Esta función devuelve un diccionario con todos los objetos publicados. La clave del diccionario es la clave de cada objeto, y su valor es una tupla "(nombre del módulo que publica el objeto, 'id' del módulo en cuestión, objeto)".

Los datos devueltos constituyen una estructura independiente de la original; son una copia. Se pueden modificar y no se garantiza que los objetos sigan existiendo.

En particular, se pueden devolver objetos pertenecientes a módulos descargados, que ya no existen, pero que su módulo madre no eliminó correctamente al descargarse.

Thread Safe
Python: Olimpo.ipc.purge_objects()

Función disponible en módulos Python.

Esta función elimina los objetos stale publicados. Esto es, los objetos publicados cuyo módulo madre está descargado pero no los limpió adecuadamente.

La rutina devuelve el número de objetos eliminados.


TOOLS

Este módulo cobija funciones de uso genérico.

C: unsigned int base64toint(char *);
Python: Olimpo.tools.base64toint(cadena)

Transforma una cadena de 6 caracteres a un entero sin signo de 32 bits. En la versión Python, se devuelve el resultado como una tupla de dos elementos: (16 bits altos, 16 bits bajos).

Si la cadena mide más de 6 caracteres, se toman sólo los 6 primeros. Si la cadena mide menos de 6 caracteres, el resultado es indefinido.

C: char *inttobase64(unsigned int valor);
Python: Olimpo.tools.inttobase64(valor)

Transforma un entero sin signo de 32 bits en una cadena de 6 bytes de longitud. En la versión en C, la cadena devuelta es sobreescrita en llamadas subsiguientes.

En la versión Python, se pasa el entero sin signo de 32 bits como una tupla de dos elementos, de 16 bits cada uno. El primer elemento es el de mayor peso.

C: void tea_crypt(unsigned int *entrada, unsigned int *salida, unsigned int *clave);
Python: Olimpo.tools.tea_crypt(entrada, clave)

Cifra, usando TEA, 64 bits, tomando una clave de 128 bits. Los parámetros son matrices de dos, dos y cuatro elementos.

En Python, los valores son tuplas, en los que cada elemento proporciona 16 bits. El primer elemento es el de mayor peso.

C: void tea_decrypt(unsigned int *entrada, unsigned int *salida, unsigned int *clave);
Python: Olimpo.tools.tea_decrypt(entrada, clave)

Descifra, usando TEA, 64 bits, tomando una clave de 128 bits. Los parámetros son matrices de dos, dos y cuatro elementos.

En Python, los valores son tuplas, en los que cada elemento proporciona 16 bits. El primer elemento es el de mayor peso.

C: char *which_server(int handle, char *buf);
Python: Olimpo.tools.which_server(handle)

Esta función nos indica el nombre del servidor de IRC utilizado por un usuario determinado. Si el usuario no está online, devuelve NULL (en C) o None (en Python).

En C es preciso pasarle un búfer lo bastante amplio como para acomodar el nombre de nodo más largo de la red. Si el usuario no está online, no se garantiza que el búfer no haya sido modificado.

C: unsigned char *nick_normalizado(unsigned char *nick, unsigned char *destino);
Python: Olimpo.tools.nick_normalizado(nick)

Nos devuelve el nick que le pasamos, normalizado.

En C, el puntero devuelto es idéntico al destino que le pasamos como parámetro. Si el puntero origen y el destino coinciden, la conversión se realiza "in place". Si los punteros no coinciden pero las cadenas se solapan, el resultado es indefinido.

C: unsigned long long get_entropia();
Python: Olimpo.tools.get_entropia()

Nos devuelve un valor pseudoaleatorio de 64 bits. Llamadas próximas pueden devolver valores correlados, por lo que conviene a) no desvelar el resultado y b) utilizar fuentes adicionales de entropía.

En Python, se devuelve una secuencia de cuatro valores de 16 bits.

C: void set_entropia(unsigned int random);
Python: Olimpo.tools.set_entropia()

Añade datos a la entropía. En C se añaden 32 bits. En Python se añaden 16 bits.

C: char *handle2nicknumeric(int handle, char *buf);
Python: Olimpo.tools.handle2nicknumeric(handle)
C: int nicknumeric2handle(char *numeric);
Python: Olimpo.tools.nicknumeric2handle(numeric)
C: char *handle2servernumeric(int handle, char *buf);
Python: Olimpo.tools.handle2servernumeric(handle)
C: int servernumeric2handle(char *numeric);
Python: Olimpo.tools.servernumeric2handle(numeric)

Esta rutina permite convertir entre "numerics" y "handles". En la interfaz C, el búfer proporcionado debe tener capacidad, al menos, para todos los caracteres necesarios (cinco más el "\0" terminador).

El "numeric" no necesita estar en uso, pero debe ser válido.


NOTIFY

Este módulo activa funciones callback que son invocadas cuando se producen determinados eventos.

C: void notifica_nick_entrada(void (*func) (int nick));
Python: Olimpo.notify.notifica_nick_entrada(func)

Informa de la entrada de un nuevo usuario en el sistema. Si el valor pasado es NULL (C) o None (Python), se desactiva el callback.

Si el módulo ha definido también el callback de entrada de usuario con "+r", se invocarán a las dos funciones. El orden de la invocación no está determinado.

Si los usuarios están siendo injectados por la entrada de un nuevo nodo, se comunica al módulo, primero, la entrada de dicho nodo.

Cuando se envía esta notificación, el usuario ya está presente en las tablas internas de Olimpo, por lo que se pueden hacer consultas adicionales al framework sobre el usuario en cuestión.

C: void notifica_nick_salida(void (*func) (int nick));
Python: Olimpo.notify.notifica_nick_salida(func)

Informa de la salida de un nuevo usuario en el sistema, por la razón que sea. Si el valor pasado es NULL (C) o None (Python), se desactiva el callback.

Si los usuarios están siendo eliminados por la desaparición de uno o más nodos, se comunica al módulo, primero, la salida de dichos nodos.

Cuando se envía esta notificación, el usuario todavía está presente en las tablas internas de Olimpo, por lo que se pueden hacer consultas adicionales al framework sobre el usuario en cuestión.

C: void notifica_nicks();
Python: Olimpo.notify.notifica_nicks()

Esta rutina hace llamadas a la rutina indicada en "notifica_nick_entrada()", inyectando la lista de usuarios presentes en la red. El orden de presentación de nicks no es reproducible.

Esta llamada resulta potencialmente muy costosa, y sólo debería utilizarse si hay una necesidad real.

C: void notifica_nick_registrado(void (*func) (int nick));
Python: Olimpo.notify.notifica_nick_registrado(func)

Cuando entra un nick registrado (flag "+r"), se invoca la rutina especificada. Dicha rutina recibe el identificador del nick en cuestión como parámetro.

Si se indica una función NULL (en C) o None (en Python), el callback se desactiva.

C: void notifica_nicks_registrados();
Python: Olimpo.notify.notifica_nicks_registrados()

Esta rutina hace llamadas a la rutina indicada en "notifica_nick_registrado()", inyectando la lista de usuarios con modo "+r" presentes en la red. El orden de presentación de nicks no es reproducible.

Esta llamada resulta potencialmente muy costosa, y sólo debería utilizarse si hay una necesidad real.

C: void notifica_server_join(void (*func) (char *server, char *id, char *padre));
Python: Olimpo.notify.notifica_server_join(func)

Indicamos qué rutina queremos que se llame cuando entra un servidor en la red. La rutina en cuestión recibe como parámetros, el nombre del servidor y el nombre del nodo padre (su HUB directo).

Si el nodo que entra es el propio HUB de Olimpo, el padre aparecerá como NULL (en C) o None (en Python).

"id" es un identificador único para cada nodo. Se trata de su numeric.

Si se indica una función NULL (en C) o None (en Python), el callback se desactiva.

C: void notifica_server_split(void (*func) (char *server, char *causa));
Python: Olimpo.notify.notifica_server_split(func)

Especifica la rutina a llamar cuando ocurre un split. La rutina recibe el nombre del nodo que se desconecta, o NULL (en C) o None (en Python) si el que se desconecta es Olimpo. También se recibe la causa de la desconexión, que puede ser NULL (en C) o None (en Python).

Cuando un split afecta a varios servidores, se envían notificaciones para todos ellos, pero sin seguir ningún tipo de orden topológico o numérico, etc. reproducible.

Si se indica una función NULL (en C) o None (en Python), el callback se desactiva.

C: void notifica_servers_split_end(void (*func) (void));
Python: Olimpo.notify.notifica_servers_split_end(func)

Especifica una rutina a llamar cuando se completa el split de uno o más nodos de la red. Es decir, la función se invocará tras haber dado de baja los nodos afectados y sus nicks asociados.

Esta función está pensada como optimización cuando un módulo hace un seguimiento de nicks presentes en la red. Un módulo de este tipo puede, por ejemplo, pedir que se le deje de enviar las bajas de nicks cuando se está procesando un split, para no recibir 30.000 bajas en un segundo. El módulo puede eliminar su registro interno de nicks de forma masiva a medida que ve caerse módulos, sin necesidad de que el framework le comunique uno a uno. Una vez que el procesamiento del split se completa, el módulo vuelve a pedir que se le envíen las bajas individuales.

Cuando un módulo define varios callbacks, primero le llegan las notificaciones de bajas de nodos, seguidamente las bajas de nicks conectados a dichos nodos y, por último, el informe de que el procesado del split ha finalizado.

Si el valor indicado es NULL (C) o None (Python), el callback se desactiva.

C: void notifica_servers();
Python: Olimpo.notify.notifica_servers()

Esta rutina hace llamadas a la rutina indicada en "notifica_server_join()", inyectando la lista de nodos actuales de la red. La lista de nodos suministrados no sigue ningún orden concreto, topológico o numérico, etc. reproducible.

C: void notifica_timer(int tiempo, void (*func) (void));
Python: Olimpo.notify.notifica_timer(tiempo, func)

Esta función programa un temporizador que invocará una rutina en un momento determinado. El tiempo se especifica en segundos desde 1.970 (epoch tradicional Unix). Si se especifica un tiempo ya pasado, la rutina es invocada enseguida. Si se especifica un tiempo de cero, se elimina la llamada temporizada. Si se realiza una nueva llamada cuando hay una temporización en curso, la vieja temporización se elimina.

Olimpo puede no invocar la rutina en el preciso instante seleccionado, pero nunca lo hará antes del momento pedido.

En Python podemos pasar una rutina None. En ese caso se ignora el tiempo y se desactivar la temporización. Esto es útil para desactivar una temporización en curso, sin tener que definir un objeto "callable" y liberando el objeto "callable" utilizado en la temporización que retiramos.

En Python, asimismo, se liberará el objeto "callable" invocado cuando vence la temporización.

Si se indica una función NULL (en C) o None (en Python), el callback se desactiva.


NOTIFYDB

Este módulo activa funciones callback que son invocadas cuando se producen determinados eventos. Al contrario que en el caso anterior, estos eventos son "persistentes" y "fiables". Es decir, si un módulo se carga tras haberse producido eventos de este tipo, dicho módulo los recibirá en "diferido". Los eventos en cuestión, por tanto, se almacenan en una base de datos que hay que purgar cuando sea necesario, para limitar su crecimiento.

C: void notifica_db_nickdrop(void (*func) (char *nick, long num_serie), long num_serie_actual);
Python: Olimpo.notify_db.notifica_nickdrop(func, num_serie_actual)

Definimos un callback que debe invocarse cada vez que se hace un nickdrop. El número de serie indica que queremos recibir, también, los nickdrops que se hayan producido a posteriori, aunque no tuviésemos cargado el módulo dinámico en ese momento.

La rutina indicada recibe el nick eliminado (normalizado), y el número de serie de dicha eliminación.

Esta función provocará subinvocaciones de la rutina de notificación si existen notificaciones pendientes, y se ejecuta durante la inicialización del módulo. Si la rutina se llama con posterioridad, no se recibirán las notificaciones pendientes. Si se va a utilizar esta función, se recomienda su empleo durante la inicialización del módulo.

Si se indica una función NULL (en C) o None (en Python), el callback se desactiva. En ese caso, el número de serie proporcionado se ignora.


PRIVMSG

Este módulo proporciona la interfaz para que un módulo pueda dar de alta "nicks", y que estos "nicks" puedan intercomunicarse con los usuarios de la red.

C: int nuevo_nick(char *nick, char *modos, void (*func) (int handle, int remitente, char *mensaje));
Python: Olimpo.privmsg.nuevo_nick(nick, modos, func)

Damos de alta un nuevo nick, con los modos especificados. Los modos deben empezar con un signo más ("+"). Se indica también la función que será invocada cuando un usuario envíe un mensaje (vía PRIVMSG) a ese nick. La función recibirá como parámetros el identificador del nick destino, el identificador del remitente y el mensaje en sí.

Esta función devuelve el identificador del nick que damos de alta.

Un módulo puede dar de alta varios nicks, si lo desea.

Los nicks dados de alta por un módulo serán eliminados automáticamente cuando se descarga dicho módulo.

Olimpo no comprueba que el nick que intentamos introducir ya exista. Si existe algún usuario con ese nick, el usuario recibirá un kill. Si el nick está siendo utilizado por otro módulo, el resultado es indefinido. Se recomienda que los nicks empleados por módulos estén protegidos mediante la base de datos distribuída.

C: int quit_nick(int handle);
Python: Olimpo.privmsg.quit_nick(handle)

Esta rutina permite que un módulo elimine un nick dado de alta con "nuevo_nick()". Todos los callback asociados a ese nick son destruidos.

Un módulo sólo debe dar de baja nicks creados por él mismo. Un intento de dar de baja un nick de otro módulo, un nick presente en la red o un nick inexistente, tiene resultados indefinidos.

C: int envia_nick(int handle, int destino, char *mensaje);
Python: Olimpo.privmsg.envia_nick(handle, destino, mensaje)

Esta función envía el mensaje al destino especificado. El nick remitente será el especificado por el handle.

El envío de un mensaje con un remitente no registrado por este módulo tiene resultados indefinidos.

No es posible enviar mensajes a nicks introducidos por módulos (incluyendo el propio módulo). El resultado de dicha acción es indefinido.

C: char *lee_flags_nick(int handle, char *flags);
Python: Olimpo.privmsg.lee_flags_nick(handle)

Nos proporciona los modos del usuario en cuestión. Si el usuario no existe o se trata de un nick introducido por un módulo, la rutina revuelve NULL (en C) o None (en Python). Los modos devueltos contendrán un signo más ("+") inicial.

En C es necesario proporcionar un búfer para copiar en él los modos del usuario. Se garantiza que con 512 bytes de espacio es suficiente para evitar "overflows".

C: char *lee_host_nick(int handle, char *host);
Python: Olimpo.privmsg.lee_host_nick(handle)

Nos proporciona el host del usuario en cuestión. Si el usuario no existe o se trata de un nick introducido por un módulo, la rutina revuelve NULL (en C) o None (en Python).

En C es necesario proporcionar un búfer para copiar en él el host del usuario. Se garantiza que con 512 bytes de espacio es suficiente para evitar "overflows".

C: unsigned long lee_ip_nick(int handle);
Python: Olimpo.privmsg.lee_ip_nick(handle)

Nos proporciona la dirección IP del usuario en cuestión. Si el usuario no existe o se trata de un nick introducido por un módulo, la rutina revuelve 0 (en C) o None (en Python).

En Python se devuelve una secuencia de cuatro enteros, correspondiendo a los cuatro bytes de la dirección IP.

C: char *lee_nick(int handle, char *nick);
Python: Olimpo.privmsg.lee_nick(handle)

Esta rutina nos proporciona el nick, en texto, equivalente al identificador proporcionado. Si el identificador no existe o se trata de un nick introducido por un módulo, la rutina revuelve NULL (en C) o None (en Python).

En C es necesario proporcionar un búfer para copiar el nick en él. Se garantiza que con 512 bytes de espacio es suficiente para evitar "overflows".

C: char *lee_nick_normalizado(int handle, char *nick);
Python: Olimpo.privmsg.lee_nick_normalizado(handle)

Esta rutina es semejante a la anterior, pero proporciona el nick normalizado en minúsculas (incluyendo los caracteres especiales, como {, [, ^, etc).

C: int lee_handle(char *nick);
Python: Olimpo.privmsg.lee_handle(nick)

Esta rutina devuelve el handle de un nick determinado. El nick no necesita estar normalizado.

Si el nick no está conectado en este momento, devuelve -1 (en C) o None (en Python).


SERVMSG

Este módulo posibilita la comunicación directa entre un módulo y un servidor IRC.

C: int serv_callback(int handle, void (*func) (int handle, char *remitente, char *respuesta));
Python: Olimpo.servmsg.serv_callback(handle, func)

Esta función permite definir la rutina que será invocada por Olimpo cuando llegue un mensaje de un servidor para el identificador. Si el identificador no ha sido dado de alta por este módulo, el resultado es indefinido.

La rutina invocada recibe como parámetros el identificar, una cadena con el nombre del servidor remitente y el texto en sí.

Si se indica una función NULL (en C) o None (en Python), el callback se desactiva.

C: int envia_raw(int handle, char *comando);
Python: Olimpo.servmsg.envia_raw(handle, comando)

Esta función envía un comando arbitrario, típicamente a un servidor.

Si el destino del mensaje es un módulo Olimpo, el resultado es indefinido.

Si el comando ocasiona un cambio de estado que debería ser seguido por Olimpo, Olimpo no lo verá. El caso típico es un KILL.

C: int envia_raw2(char *comando);
Python: Olimpo.servmsg.envia_raw2(comando)

Similar al comando anterior, pero el remitente que consta en el mensaje será Olimpo, no este módulo.

Como en el caso anterior, si el comando ocasiona un cambio de estado que debería ser seguido por Olimpo, Olimpo no lo verá. El caso típico es un MODE.

C: void intercepta_comando(char *comando, int (*func) (char *comando));
Python: Olimpo.servmsg.intercepta_comando(comando,func)

Esta función permite definir un "callback" que será invocado cuando Olimpo recibe el comando especificado. La rutina se invoca con todo elcomando completo, sin interpretaciones ni conversiones de handles, etc.

Si la función es NULL (C) o None (Python), se elimina la interceptación de dicho comando para este módulo.

Si varios módulos interceptan un mismo comando, el orden en que se invocan no está documentado. Eso incluye también el propio framework Olimpo. No sabemos, por ejemplo, si la entrada de un nuevo nick es visto primero por el framework o por el módulo.

Si un mismo módulo intenta realizar múltiples interceptaciones de un mismo comando, el resultado es indefinido. Si se intenta eliminar una interceptación inexistente, el resultado es indefinido.

Los módulos no recibirán comandos enviados por el propio módulo o por otros módulos.

En la interfaz C, la cadena proporcionada no debe ser modificada en modo alguno.

La rutina invocada debe devolver SIEMPRE el valor cero (0), para permitir futuras expansiones. Devolver otro valor provoca un resultado indefinido. Una excepción Python se interpretará también como un valor de CERO, aunque esto puede modificarse en el futuro.


BERKELEYDB

Base de datos.

C: char *mod_version_db(void);
Python: Olimpo.BerkeleyDB.version()

Devuelve la versión de la base de datos.

C: p_db mod_abre_db(char *nombre);
Python: Olimpo.BerkeleyDB.db(nombre)

Abre una base de datos y devuelve un identificador para la misma.

C: void mod_cierra_db(p_db);
Python: db.cierra()

Cierra una base de datos abierta previamente.

C: txn mod_inicia_txn_db(void);
Python: Ver más adeltante

Inicia una transacción ACID.

C: txn mod_inicia_txn_db_no_sync(void);
Python: Ver más adelante

Inicia una transacción ACI. Si ocurre algún problema, podemos perder la propiedad D (durabilidad o persistencia). Esta opción es más eficiente, y resulta útil cuando el cambio que hacemos en las bases de datos pueden perderse sin mayor impacto. Un ejemplo típico sería la hora de última conexión a la red de un usuario, por ejemplo.

C: txn mod_inicia_txn_db_no_wait(void);
Python: Ver más adelante

Inicia una transacción ACID, pero si en algún momento tenemos que esperar por un semáforo, abortamos la transacción. Este tipo de transacciones son útiles para evitar "deadlocks".

Python: Olimpo.BerkeleyDB.txn(modo)

En Python, las transacciones se gestionan a través de un objeto separado. El modo, equivalente a las funciones C descritas con anterioridad, puede ser: NORMAL, NO_SYNC, NO_WAIT.

C: void mod_compromete_txn_db(txn txn);
Python: txn.compromete()

Cierra una transacción, y nos asegura las propiedades ACID (o ACI, si es una transacción sin sincronización).

C: void mod_aborta_txn_db(txn txn);
Python: txn.aborta()

Aborta una transacción y deshace todos los cambios realizados en su interior.

C: int mod_get_db(p_db db, txn transaccion, dbt * clave, dbt * contenido);
Python: db.get(transaccion, clave)

Devuelve el valor de un registro. La transacción puede ser NULL (C) o None (Python).

C: int mod_put_db(p_db db, txn transaccion, dbt * clave, dbt * contenido);
Python: db.put(transaccion, clave, contenido)

Introduce un registro nuevo en una base de datos, o reemplaza un registro ya existente. La transacción puede ser NULL (C) o None (Python).

C: int mod_del_db(p_db db, txn transaccion, dbt * clave);
Python: db.delete(transaccion, clave)

Borra un registro de una base de datos. La transacción puede ser NULL (C) o None (Python).

C: c_db mod_cursor_db(p_db db, txn transaccion, dbt * clave, int bulk);
Python: db.cursor(transaccion, clave=None, bulk=1)

Abre un cursor nuevo, dentro de una transacción.

La clave especificada puede ser NULL (en C) o None (en Python), indicando que se debe empezar el recorrido desde el principio. Si se indica una clave, el primer registro devuelto será el registro SIGUIENTE a la clave especificada.

Si se indica una clave y ésta no existe, se empieza a recorrer la base de datos desde el principio.

Si utilizamos el modo bulk, estaremos empleando un "read ahead". Es decir, se transfieren varios registros a memoria de una vez. Esto es mucho más eficiente que acudir a disco para cargar cada registro.

C: int mod_cursor_get_db(c_db db_cursor, dbt * clave, dbt * contenido);
Python: cursor.get()

Devuelve el siguiente registro. El orden de los registros devueltos no está especificado.

En el C, si estamos utilizando el modo bulk para el cursor, NO hay que liberar memoria cuando terminemos con los datos devueltos. En ese modo tampoco se garantiza ningún tipo de alineamiento de los datos devueltos.

C: int mod_cursor_close_db(c_db db_cursor);
Python: cursor.close()

Cierra un cursor.

C: char *mod_strerror_db();
Python: Olimpo.BerkeleyDB.strerror()

Devuelve el texto del último error que ha ocurrido en una operación de base de datos.


BDD

Este módulo permite interaccionar con la Base de Datos Distribuída.

C: long bdd_envia_registro(unsigned char bd, char *clave, char *valor);
Python: Olimpo.bdd.envia_registro(bd, clave, valor)

Envía un registro al sistema de base de datos distribuída. La base de datos indicada debe ser válida y esta instancia de Olimpo DEBE ser autoritativa sobre ella.

El valor puede ser NULL (en C) o None (en Python), para señalar el borrado de un registro.

El valor devuelto es el número de registro propagado.

Si se elimina un registro y existen definidas callbacks de notificación, se invocarán durante la ejecución de esta rutina. Ello incluye los callbacks definidos en el propio módulo.

Si se intenta enviar un registro a través de una base de datos distribuida que tenga el flujo cerrado, Olimpo aborta su ejecución como mal menor.

No existe una garantía 100% de que la red reciba el nuevo registro, ya que el enlace TCP/IP puede cortarse tiempo después, conteniendo datos no recibidos por el HUB.

C: int bdd_flujo_abierto(unsigned char bd);
Python: Olimpo.bdd.flujo_abierto(bd)

Esta rutina indica si una base de datos distribuida concreta tiene su flujo abierto o cerrado.

Una BDD tiene su flujo cerrado si a) no estamos enlazados al HUB o b) estamos enlazados pero todavía desconocemos el número de serie que debemos utilizar.

En Python se devuelven los valores True o False (novedad en Python 2.2.1).

Existe una ventana de vulnerabilidad. Es decir, esta rutina puede indicarnos que el flujo está abierto, pero cuando vamos a enviar un registro, encontrarse ya cerrado. Habrá que vivir con ello, de momento.


Historia

  • 07/Ago/02: Actualizamos la descripcion de la función "server_join()" del API "NOTIFY". También le añadimos un parámetro adicional. Lo mismo con la función "server_split()".

  • 03/Jul/02: Modificamos el API "TOOLS" de Python para que " inttobase64()" acepte tuplas como argumento. Eso nos obliga a retocar buena parte de los módulos, aunque los cambios son minúsculos.

  • 19/Jun/02:

    • Amplío el API "PRIVMSG" para que un módulo pueda obtener la dirección IP y el nombre de host de un usuario.

    • Amplío el API "BDD" para que un módulo pueda saber si puede o no puede enviar un registro a través de la base de datos distribuida. Esto es importante, ya que si se intenta enviar un registro cuando Olimpo no está enlazado a su HUB, dicho registro se perdería.

      Actualmente Olimpo comprueba, mediante un "assert()" que solo se envíen registros con flujo abierto. Pero eso lo hace internamente. La ampliación del API permite que un módulo realice esas comprobaciones por sí mismo.

  • 03/Jun/02: Soluciono un par de errores de la documentación del API "BerkeleyDB". También permito que operaciones de lectura, escritura y borrado de registros de las bases de datos no necesiten estar incluidas en transacciones, necesariamente, si no lo deseamos así.

  • 30/May/02: Ampliamos el API "NOTIFY" para que un módulo reciba la notificación final de que se ha completado un split.

  • 29/May/02: Ampliamos el API "NOTIFY" para que un módulo reciba notificaciones de entradas y salidas de usuarios de la red.

  • 27/May/02: Ampliamos el API "TOOLS" para poder convertir entre "handles" y "numerics", de nicks y de servidores.

  • 20/May/02: Ampliamos el API "SERVMSG" para poder escuchar cualquier comando enviado a Olimpo.

  • 26/Feb/02: Ampliamos el API "SERVMSG" para poder hacer envíos como Olimpo. Asimismo, se mejora la documentación de esta sección.

  • 21/Feb/02: Ampliamos el API "BERKELEYDB" para soportar transferencias bulk.

  • 14/Ene/02:

    • Aclaramos algunos puntos en la documentación, sobre todo en lo relativo a la desactivación de callbacks.
    • Añadimos al API "PRIVMSG" una nueva función "quit_nick()", que elimina el nick dado de alta por un módulo.

  • 08/Ene/02:

    • Añado el API "IPC", y muevo las rutinas de intercomunicación entre módulos y threads a dicha API.
    • Añado al API "IPC" las funciones "add_obj()", "del_obj()", "obj()", "del_id_objects()" y "get_objects()". Estas funciones están disponibles exclusivamente para módulos Python.
    • Añado al API "IPC" la función "add_obj2()", para poder publicar objetos desde threads que no sean la principal.
    • Añado al API "IPC" la función "purge_objects()", para poder eliminar objetos stale, cuyo módulo madre está descargado pero no los eliminó correctamente.

  • 04/Ene/02:

    • Añadimos la función "nombre_modulo()" para que un módulo obtenga su propio nombre.
    • Documento la función "debug()", existente desde hace tiempo, y que nos indica si el framework de Olimpo en el que se carga el módulo está compilado en modo desarrollo o en modo producción.
    • Añadidas al API "NOTIFY" las funciones "notifica_IRQ()" y "notifica_IRQ_handler()". Estas funciones se utilizan para la intercomunicación entre threads de un módulo y entre módulos distintos (previo acuerdo de un API personalizado caso a caso).
    • Añadimos la función "id_modulo()" para que un módulo pueda obtener un identificador único por instancia.
    • Añadimos funciones "existe_nombre_modulo()" y "existe_id_modulo()" para que un módulo o thread pueda verificar la existencia y la identidad de un módulo o una instancia.
    • En el API "NOTIFY" cambiamos el nombre de la función "notifica_IRQ()" por "notifica_IRQ_nombre()", y añadimos la rutina "notifica_IRQ_id()".
    • Asimismo, estas dos funciones ahora indican si el destinatario del IRQ existe o no.

  • 20/Dic/01: Cuando abrimos un cursor, podemos especificar un registro en el que empezar el recorrido.

  • 04/Dic/01:

    • Es posible hacer log sin necesitar un nick remitente, a través de la nueva "hace_log2()".
    • Añadidas al API "TOOLS" las funciones "get_entropia()" y "add_entropia()".
    • Añadida al API "NOTIFY" la función "notifica_servers()", para obtener la lista de servidores actuales.
    • Añadida al API "NOTIFY" la función "notifica_nicks_registrados()", para obtener la lista de usuarios "+r" actuales.
    • Añadida al API "NOTIFY" la función "notifica_timer()", para temporizaciones e invocaciones diferidas.

  • 25/Jul/01: Añadida una función al API "PRIVMSG", para obtener el "numeric" a partir de un "nick", si está conectado.

  • 23/Jul/01:

    • En los "bindings" Python para BerkeleyDB, cambiamos el método "del" de "db" a "delete", ya que se trata de una palabra reservada.
    • Se advierte en la documentación que "notifica_db_nickdrop()" y "bdd_envia_registro()" pueden provocar subinvocaciones del mismo módulo. Por ejemplo, si un módulo indica que desea recibir las informaciones sobre "drops" de nicks, y ese módulo elimina un nick, Olimpo invocará la función de señalización correspondiente del módulo en cuestión antes de devolver el control a la función que elimina el nick.
    • Más clarificaciones sobre "notifica_db_nickdrop()".
    • Añadidas las funciones "TEA".

  • 19/Jul/01:

    • En los "bindings" Python para el módulo BerkeleyDB, cambio "berkeleydb" por "BerkeleyDB", que es el nombre real.
    • Cambio los "bindings" Python para BerkeleyDB, en lo que respecta al control de transacciones, para hacerlos más orientados a objetos.
    • Cambio los "bindings" Python para BerkeleyDB, en lo que respecta a la gestión de bases de datos, para hacerlos más orientados a objetos.
    • Cambio los "bindings" Python para BerkeleyDB, en lo que respecta a la gestión de cursores, para hacerlos más orientados a objetos.
    • Perfilo los nuevos módulos TOOLS y BDD. Documentación.

  • 21/May/01: Documentación de los módulos SERVMSG y BERKELEYDB.

  • 19/Abr/01: Documentamos el módulo PRIVMSG.

  • 10/Abr/01: Primera versión de este documento.



Python Zope ©2000-2002 jcea@jcea.es

Más información sobre los OpenBadges

Donación BitCoin: 19niBN42ac2pqDQFx6GJZxry2JQSFvwAfS