OS Interface Object
typedef struct sqlite3_vfs sqlite3_vfs; typedef void (*sqlite3_syscall_ptr)(void); struct sqlite3_vfs { int iVersion; /* Número de versión de la estructura (actualmente 3) */ int szOsFile; /* Tamaño de la subclase sqlite3_file */ int mxPathname; /* Longitud máxima del nombre y camino de fichero */ sqlite3_vfs *pNext; /* Siguiente VFS registrada */ const char *zName; /* Nombre del sistema de ficheros virtual */ void *pAppData; /* Puntero de datos específicos de la aplicación */ int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, int flags, int *pOutFlags); int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut); int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void); void (*xDlClose)(sqlite3_vfs*, void*); int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); int (*xSleep)(sqlite3_vfs*, int microseconds); int (*xCurrentTime)(sqlite3_vfs*, double*); int (*xGetLastError)(sqlite3_vfs*, int, char *); /* ** Los métodos anteriores están desde la versión 1 de la definición del objeto ** sqlite_vfs. Los que siguen fueron añadidos en la versión 2 y posteriores */ int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*); /* ** Los métodos anteriores están en las versiones 1 y 2 del objeto sqlite_vfs. ** Los siguientes se añadieron en la versión 3 y posteriores. */ int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr); sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName); const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName); /* ** Los métodos anteriores están en las versiones 1 a 3 del objeto sqlite_vfs. ** Nuevos campos pueden ser añadidos en futuras versiones. El valor iVersion ** será incrementado cuando eso ocurra. */ };
Una instancia del objeto sqlite3_vfs define el interfaz entre el núcleo de SQLite y el sistema operativo subyacente. El "vfs" en el nombre del objeto son las iniciales de "virtual file system".
El valor del campo iVersion es inicialmente 1 pero puede ser mayor en futuras versiones de SQLite. Se pueden añadir campos adicionales a este objeto cuando el valor de iVersion se incremente. Tener en cuenta que la estructura del objeto sqlite3_vfs cambia en la transición entre SQLite 3.5.9 y 3.6.0 y sin embargo el campo iVersion no se modificó.
El campo szOsFile es el tamaño de la estructura subclase sqlite3_file usada por este VFS. mxPathname el la longitud máxima del nombre de camino para este VFS.
Los objetos sqlite3_vfs registrados se mantienen en una lista enlazada apuntada por pNext. Los interfaces sqlite3_vfs_register() y sqlite3_vfs_unregister() manejan esta lista en modo multihilo. La función sqlite3_vfs_find() busca en la lista. Ni el código de la aplicación ni la implementación del VFS deben usar el puntero pNext.
El campo pNext es el único en la estructura sqlite3_vfs que SQLite modificará. SQLite sólo accede o modifica este campo mientras se mantiene un mutex estático en particular. La aplicación nunca debe modificar nada dentro del objeto sqlite3_vfs una vez haya sido registrado.
El campo zName contiene el nombre del módulo VFS. El nombre debe ser único a lo largo de todos los módulos VFS.
SQLite garantiza que el parámetro zFilename para xOpen es un puntero NULL o una cadena obtenida desde xFullPathname() con un sufijo opcional añadido. Si un sufijo es añadido al parámetro zFilename, debe consistir en un "-" sencillo seguido de no más de caracteres alfanuméricos y/o "-". SQLite garantiza además que la cadena es válida y no cambia hasta que xClose() sea llamada. Debido a la frase anterior, sqlite3_file puede almacenar con seguridad un puntero al nombre de fichero si necesita recordarlo por algún motivo. Si el parámetro zFilename para xOpen es un puntero NULL entonces xOpen debe inventar su propio nombre temporal para el fichero. Siempre que el parámetro xFilename sea NULL también el parámetro flags debe incluir SQLITE_OPEN_DELETEONCLOSE.
El argumento flags para xOpen() incluye todos los bits activos en el argumento flags para sqlite3_open_v2(). O si se usa sqlite3_open() o sqlite3_open16(), entonces flags incluye al menos SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE. Si xOpen() abre un fichero en sólo lectura entonces asigna *pOutFlags para que incluya SQLITE_OPEN_READONLY. Se pueden configudar otros bits en *pOutFlags.
SQLite también añadira una de las banderas siguientes a la llamada a xOpen(), dependiendo del objeto a abrir:
- SQLITE_OPEN_MAIN_DB
- SQLITE_OPEN_MAIN_JOURNAL
- SQLITE_OPEN_TEMP_DB
- SQLITE_OPEN_TEMP_JOURNAL
- SQLITE_OPEN_TRANSIENT_DB
- SQLITE_OPEN_SUBJOURNAL
- SQLITE_OPEN_MASTER_JOURNAL
- SQLITE_OPEN_WAL
La implementación I/O de ficheros puede usar tipo de objeto flags para modificar el modo en que trabaja con ficheros. Por ejemplo, una aplicación que no se preocupe de la recuperación de un crash o rollback puede hacer que la apertura de un archivo de diario se omita. Las escrituras en ese diario también pueden ser omitidas, y caulquier intento de leer el diario podría regresar con SQLITE_IOERR. O la implementación puede reconocer que el fichero de una base de datos va a hacer que la alineación de página coincida con lecturas y escrituras de sectores en un orden aleatorio y establecer su subsistema de entrada y salida en consecuencia.
SQLite también puede añadir uno de las banderas siguientes al método xOpen:
- SQLITE_OPEN_DELETEONCLOSE
- SQLITE_OPEN_EXCLUSIVE
La bandera SQLITE_OPEN_DELETEONCLOSE significa que el fichero debe ser borrado cuando se cierre. La bandera SQLITE_OPEN_DELETEONCLOSE será activada para bases de datos TEMP y para sus diarios, bases de datos en transito y subdiarios.
La bandera SQLITE_OPEN_EXCLUSIVE siempre se usa en conjunción con SQLITE_OPEN_CREATE, que son directamente análogas a las banderas O_EXCL y O_CREAT de la función POSIX open() API. La bandera SQLITE_OPEN_EXCLUSIVE, cuando se empareja con SQLITE_OPEN_CREATE, se usa para indicar que el fichero siempre debe ser creado, y se produce un error su ya existe. Esto se usa para indicar que el fichero debe ser abierto para acceso exclusivo.
Al menos szOsFile bytes de memoria se asignan por SQLite para contener la estructura sqlite3_file pasada como el tercer argumento a xOpen. El método xOpen no tiene que asginar memoria para la estructura; tan solo debe rellenarla. Tener en cuenta que el método xOpen debe asignar a sqlite3_file.pMethods un objeto válido sqlite3_io_methods o NULL. xOpen debe hacer esto aunque la apertura falle. SQLite espera que el elemento sqlite3_file.pMethods sea válido después de que xOpen regrese independientemente la llamada a xOpen tenga éxito o falle.
El argumento flags para xAccess() puede ser SQLITE_ACCESS_EXISTS para verificar la existencia de un fichero, o SQLITE_ACCESS_READWRITE para verificar si un fichero es de lectura y escritura, o SQLITE_ACCESS_READ para verificar si un fichero es al menos de lectura. El fichero puede ser un directorio.
SQLite siempre asignará al menos mxPathname+1 bytes para el buffer de salida xFullPathname. El tamaño exacto del buffer de salida también es pasado comi un parámetro a ambos métodos. Si el buffer de salida no es lo bastante grande, se retornará SQLITE_CANTOPEN. Daro que esto se maneja como un error fatal por SQLite, las implementaciones de vfs deben esforzarse para evitar esto asignando a mxPathname un valor lo suficientemente grande.
Los interfaces xRandomness(), xSleep(), xCurrentTime() y xCurrentTimeInt64() no son estrictamente parte del sistema de ficheros, pero se incluyen en la estrucutra FVS por integridad. La función xRandomness() intenta retornar nBytes de bytes aleatorios de buena calidad dentro de zOut. El valor de retorno es el número actual de bytes aleatios obtenidos. El método xSleep()provoca que el hilo que lo invoca duerma por al menos el número de microsegundos dado. El método xCurrentTime() devuelve el número de día juliano para la fecha y hora actual como un valor en punto flotante. El método xCurrentTimeInt64() retorna, como un entero, el número de día juliano multiplicado por 86400000 (el número de milisegundos en un día de 24 horas). SQLite usará el método xCurrentTimeInt64() para obtener la fecha y hora actual si ese método está disponible (si iVersion es 2 o mayor y el puntero a la función no es NULL) y recurrirá a xCurrentTime() si xCurrentTimeInt64() no está disponible.
Los interfaces xSetSystemCall(), xGetSystemCall() y xNestSystemCall() no se usan por el núcleo de SQLite. Estos interfaces opcionales se proporcionan por algunos VFS para facilitar las pruebas del código del VFS. Al reemplazar las llamadas al sistema con funciones bajo su control, un programa de prueba puede simular fallos y condiciones de error que de otro modo serían difíciles o implesibles de inducir. El conjunto de llamadas de sistema que pueden ser reemplazadas varia de un VFS a otro, y de una versión del mismo VFS a la siguiente. Las aplicaciones que usen estos interfaces deben estar preapradas para que alguno o todos estos interfaces sean NULL o para que sus comportamientos cambien de una versión a la siguiente. Las aplicaciones no deben intentar acceder a ninguno de estos métodos si el valor de iVersion del VFS es menor que 3.