Greenspot Technologies Ltd Logo

Extensible Storage Engine

The Extensible Storage Engine (ESE) is an Indexed Sequential Access Method (ISAM) database engine, used as a fast client-side storage system most notably by Microsoft Exchange Server and the Active Directory Service. The engine was known as JET Blue early in its use and development, in contrast to JET Red, the Microsoft Access Database Engine which it was originally intended to replace.

The Engine is programmed via a simplistic C-compatible API through the esent.dll that has been distributed with all versions of Windows since Windows 2000, as well as with Microsoft Exchange Server. Prior to this, it was distributed as a private API by Microsoft in any relevant software.

Programming with the ESE

To use the Extensible Storage Engine, you must use the esent.dll of the host system and the esent.h provided in the latest Windows SDK. The calls in the API are structured hierarcichally, so that functions representing parent concepts provide unique IDs relevant to calls to nested elements. For example, the JetRetrieveColumn function takes sessid, tableid and columnid parameters, which must have already been acquired by the application.

The first call that must be made before any other is a call to JetCreateInstance. This function creates an instance of the database engine environment in which all other calls must be made. The primary role of the instance is to associate the application's interactions with a particular log file. As of Windows 7, up to 1024 instances of the ESE may be created per application and up to 6 databases can be associated with each. The prototype for this function is as follows:

JET_ERR JET_API JetCreateInstance( JET_INSTANCE* pinstance, const tchar* szInstanceName );

Before the instance can be used, it must be configured with calls to JetSetSystemParameter followed by a call to JetInit. No other function can be used on the instance before doing so, and once JetInit has been called on an instance many system parameters for the instance can no longer be changed. For example, JET_paramBaseName, the system paramater which controlls the transaction log naming scheme, cannot be changed once JetInit has initialized the database for use. The function prototypes for these functions are detailed below:

JET_ERR JET_API JetInit( JET_INSTANCE* pinstance );

JET_ERR JET_API JetSetSystemParameter( JET_INSTANCE* pinstance, JET_SESID sesid, unsigned long paramid, JET_API_PTR lParam, JET_PCSTR szParam );

Finally, before a database can be directly accessed, it is necessary to acquire a Session ID for the session that will manage database transactions and can be used to commit or abort such actions. This function is structured as follows:

JET_ERR JET_API JetBeginSession( JET_INSTANCE instance, JET_SESID* psesid, JET_PCSTR szUserName, JET_PCSTR szPassword );

The session ID which is returned in the second parameter is required for any interaction with the database. All the transactive functions take a session ID as opposed to an instance ID. Multiple sessions may be created for each instance in order to perform parallel concurrent actions.

All the preceding functions to prepare the engine have a comparable which must be used to end the relevant sessions and instances once they are no longer required. After using any of these functions, the IDs associated with instances and sessions will be redundant.

JET_ERR JET_API JetEndSession( JET_SESID sesid, JET_GRBIT grbit );


Interacting with the Database

In order to begin interacting with a database, it is necessary to attach to and open a database session using the following 2 functions:

JET_ERR JET_API JetAttachDatabase( JET_SESID sesid, const tchar* szFilename, JET_GRBIT grbit );

JET_ERR JET_API JetOpenDatabase( JET_SESID sesid, const tchar* szFilename, const tchar* szConnect, JET_DBID* pdbid, JET_GRBIT grbit );

It is then possible to open a table, using it's name as a parameter, and retrieve information from it using JetRetrieveColumn.

JET_ERR JET_API JetOpenTable( JET_SESID sesid, JET_DBID dbid, const tchar* szTableName, ' ANSI Only const void* pvParameters, unsigned long cbParameters, JET_GRBIT grbit, JET_TABLEID* ptableid );

JET_ERR JET_API JetRetrieveColumn( JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, void* pvData, unsigned long cbData, unsigned long* pcbActual, JET_GRBIT grbit, JET_RETINFO* pretinfo );

Once all relevant table or database operations are complete, all active objects must be closed using the appropriate close function. Closing of these objects must take place in the correct order as shown by their prototypes.

JET_ERR JET_API JetCloseTable( JET_SESID sesid, JET_TABLEID tableid );

JET_ERR JET_API JetCloseDatabase( JET_SESID sesid, JET_DBID dbid, JET_GRBIT grbit );

JET_ERR JET_API JetDetachDatabase( JET_SESID sesid, const tchar* szFilename );

harddrive in action
File management view on Windows Search index analyzer