====== Abstract Extension API and Dependency Interface ======
* The original application is [[http://socghop.appspot.com/student_project/show/google/gsoc2009/php/t124023314420]]
* For those who don't have access - [[http://www.xvpj.net/gsoc-09-application-php-abstract-extension-api-and-dependency-interface/]]
===== Details =====
* Student: Varuna Jayasiri
* Mentor: shire
* Timezone: GMT +5:30 (Varuna)
* Mailing list: pecl-dev@lists.php.net
===== Abstract =====
The objective of this project is to develop functionality for PHP that will allow extensions to register a set of functions as a versioned API, since PHP does not currently handle interdependencies among PHP extensions well, which leads to various problems. This would also solve the current problem of extension load order.
===== Documentation =====
==== Versioning ====
Versions are in the format major.minor[.build[.revision]] in the string representation. These are stored in unsigned integers for ease of searching. The first 8 bits are used for the major, next 8 for the minor, next 8 for the build and the last 8 bits for the revision. It is possible to convert from the string representation to an unsigned integer using zend_eapi_toi and from an unsigned integer to the string format using zend_eapi_toa function.
==== Macros ====
EAPI_SET_CALLBACK(ext_name, version, callback)
Sets a callback - with reference to a extension and a version - should be called during MINIT. The callback will be called after all extensions have been initialized. Callback will be called with a reference to the API of the specified extension. See zend_eapi_set_callback.
^ ''ext_name'' | Extension name |
^ ''version'' | Version - if a null value will is passed the callback will be called with the latest version |
^ ''callback'' | Function pointer to the callback function |
EAPI_SET_EMPTY_CALLBACK(callback)
Sets an empty callback - should be called during MINIT. The callback will be called after all extensions have been initialized. See zend_eapi_set_empty_callback.
^ ''callback'' | Function pointer to the callback function |
EAPI_CALLBACK_FUNCTION(callback)
Defines the callback function. The callback function will be called with the following parameters: type, module_number, api (pointer to the api), ext_name, version,
^ ''callback'' | Name of the callback function |
EAPI_EMPTY_CALLBACK_FUNCTION(callback)
Defines the empty callback function. The callback function will be called with the following parameters: typei and module_number,
^ ''callback'' | Name of the callback function |
==== Functions ====
All functions return ''SUCCESS'' on success and ''FAILURE'' on failure.
int zend_eapi_register(char *ext_name, char * version_text, void *api, size_t size)
Registers an API
^ ''ext_name'' | Extension name |
^ ''version'' | API version in format major.minor[.build[.revision]] |
^ ''api'' | A ponter to the API structure |
^ ''size'' | Size of the API structure |
int zend_eapi_version_toi(char *version_text, uint *version_int)
Converts a version in text format to an integer.
^ ''version_text'' | Version as a string |
^ ''version_int'' | Version as a numerical value |
int zend_eapi_version_toa(uint version, char * version_text)
Converts a version in integer format to a string
^ ''version_text'' | Version as a string |
^ ''version_int'' | Version as a numerical value |
int zend_eapi_find_versions(char *ext_name, uint version, uint mask, uint *result, int *size, int buf_length)
Finds the set of versions available. Matches versions if ''(extension_version & mask) == (version & mask)''.
^ ''ext_name'' | Extension name |
^ ''version'' | Version to be searched for |
^ ''mask'' | A mask to specify which part of version should be matched |
^ ''result'' | Pointer to an array, which will be filled with matched versions |
^ ''size'' | Number of matches found |
^ ''buf_length'' | Capacity of the array results (memory allocated) |
int zend_eapi_get_latest_version(char *ext_name, uint *version)
Gives the latest version of the extension available
^ ''ext_name'' | Extension name |
^ ''version'' | Latest version as a numerical value |
int zend_eapi_exists(char *ext_name, char *version)
Checks if the API is available
^ ''ext_name'' | Extension name |
^ ''version'' | Version |
int zend_eapi_get(char *ext_name, char *version, void **api)
Retrieves the API
^ ''ext_name'' | Extension name |
^ ''version'' | Version |
^ ''api'' | API will be loaded here if it is available |
int zend_eapi_set_empty_callback(int type, int module_number, void (*callback)(EMPTY_CALLBACK_FUNC_ARGS))
Sets an empty callback - should be called during MINIT. The callback will be called after all extensions have been initialized. Use EAPI_SET_EMPTY_CALLBACK.
^ ''callback'' | Function pointer to the callback function |
int zend_eapi_set_callback(int type, int module_number, char *ext_name, char *version, void (*callback_func)(CALLBACK_FUNC_ARGS))
Sets a callback - with reference to a extension and a version - should be called during MINIT. The callback will be called after all extensions have been initialized. Callback will be called with a reference to the API of the specified extension. Use EAPI_SET_CALLBACK.
^ ''ext_name'' | Extension name |
^ ''version'' | Version - if a null value will is passed the callback will be called with the latest version |
^ ''callback'' | Function pointer to the callback function |
===== Timeline =====
20th April to 23rd May – Community bonding period
* Getting more familiarized with PHP core and Zend
* Submitting the proposed API and design for suggestions
* Getting ideas from the developer community on how this should be developed
* Finalizing the design
23rd May to 1st July – Implementing most important features
* The API registration and retrieval component will be developed
* The interface for setting up the callback function will not be implemented at this stage, instead a simpler interface (e.g. php_get_api) would be provided
* Code written will be unit tested
* This would be a standard to be distributed for testing
1st July to 10th July – Testing the implemented section
* The implemented features will be tested with help from the community
* Any bugs encountered will be fixed
* Any suggestions for improvements will be considered and implemented
10th July to 1st August – Completing the implementation of all features
* All the functionality described above will be completed
* Code written will be unit tested
* Behavior of the component in various scenarios with interdependencies among extensions, will be tested thoroughly
1st August to 4th August – Buffer
* Small buffer period so that any additional things that come up in the way could be implemented or if time taken for implementation exceeds time estimated
* The completed extension API and dependency interface will be made available for the developer community
* Any improvements suggested will be considered and implemented
4th August to 17th August – Testing
* Any bug fixes will be implemented
* All documentations will be completed
* It will be ready for distribution at the end of testing
===== Progress =====
== 12th May ==
* Setup the development environment
* Working on the GIT repository - [[git://github.com/vpj/PHP-Extension-API.git]]
* Made a few changes to the proposed design
* All the code will be a part of zend and hence all function will be prefixed with zend_ and not php_
* Prefixed all the functions with zend_ext_api instead of function names like php_register_api
== 15th May ==
* Discussing how different versions of API's should be maintained
* Coded the basic functionality
* Memory leaks and exception handling were not considered (TODO's were added to make sure these will be addressed later)
== 23rd May ==
* Two hashtables are used - one to store the API's and the other to store the available versions
* A simple list is used to store the set of versions available
* Versions are represented in major.minor[.build[.revision]] or major.minor[.maintenance[.build]] formats; i.e. "x.x.x.x"
* These are converted to a 32 bit integer for indexing
* Bit masks could be used to identify ranges of versions easily
== 31st May ==
* Included a function to get the latest version of an extension available
* Functions to convert version from major.minor[.build[.revision]] format to an uint and vice versa are provided.
* when representing the version in uint first 8 bits will be used for major and the next 8 for minor and so on
* A few memory leaks were fixed
== 5th June ==
* Added some documentation of the interface
* Did some testing
== 27th June ==
* Coded the callback registration
* Callbacks are called from php_module_startup (main/main.c)
* Tested callbacks
* Update sample usage code
== 10th July ==
* Callbacks
* Module number is passed to the callback
* Callbacks can be registered for the latest API version
* Testing
* Two extension with a set of standard unit test cases were added to the git repository
* API interface was tested with the extensions mbstring and exif
* Name
* eapi is used instead of ext_api
== 20th July ==
* Callbacks with no extension specified
* Used dependency interface on mbstring/exif
== 31st July ==
* Setting callbacks accept module_number / type (through macros)
* Callbacks are called with module_number / type. e.g. usage - INIs could be registered from the callback
* Functions to search versions of an extension
* Example usage of the dependency interface : [[http://www.xvpj.net/2009/06/26/how-to-use-php-extension-api-dependancy-interface/]]
* How dependency interface is implemented on mbstring / exif : [[http://www.xvpj.net/2009/07/29/eapi2/]]
== 16th August ==
* Received some suggestions from the community (mailing list)
* Fixed a problem with win32 build - included zend_eapi.c in config.w32
* TSRMLS parameters are passed to callbacks to improve performance
* Added support for extensions loaded through dl()
* When a extension (say ext_dl) is loaded through dl() the callbacks of other extensions (already loaded) are called, if they require the ext_dl and the versions match
* Callbacks of ext_dl are called if the required extensions are available
* Did some testing with dl()