diff options
author | Kaleb S. KEITHLEY <kkeithle@redhat.com> | 2015-02-03 04:05:08 -0500 |
---|---|---|
committer | Kaleb KEITHLEY <kkeithle@redhat.com> | 2015-03-10 10:21:50 -0700 |
commit | d83ff159679095eedfdd9f42b2ed801d048493ce (patch) | |
tree | 4838478e79313cca0ed81d377ba5533670bbbec6 | |
parent | 4f2b49eefd1a56469770534d7941fa37ae759f11 (diff) |
doc: convert gfapi symbol version to markdown and move to doc
Change-Id: Iaa0dd288b24240660594023e04a7fd84e7e62a5e
BUG: 1188557
Signed-off-by: Kaleb S. KEITHLEY <kkeithle@redhat.com>
Reviewed-on: http://review.gluster.org/9561
-rw-r--r-- | api/src/README.Symbol_Versions | 227 | ||||
-rw-r--r-- | doc/gfapi-symbol-versions/gfapi-symbol-versions.md | 270 |
2 files changed, 271 insertions, 226 deletions
diff --git a/api/src/README.Symbol_Versions b/api/src/README.Symbol_Versions index d69c364bb07..d5cdedd826b 100644 --- a/api/src/README.Symbol_Versions +++ b/api/src/README.Symbol_Versions @@ -1,228 +1,3 @@ -1. Symbol Versions and SO_NAMEs - - In general, adding new APIs to a shared library does not require that -symbol versions be used or the the SO_NAME be "bumped." These actions -are usually reserved for when a major change is introduced, e.g. many -APIs change or a signficant change in the functionality occurs. - - Over the normal lifetime of a When a new API is added, the library is -recompiled, consumers of the new API are able to do so, and existing, -legacy consumers of the original API continue as before. If by some -chance an old copy of the library is installed on a system, it's unlikely -that most applications will be affected. New applications that use the -new API will incur a run-time error terminate. - - Bumping the SO_NAME, i.e. changing the shared lib's file name, e.g. -from libfoo.so.0 to libfoo.so.1, which also changes the ELF SO_NAME -attribute inside the file, works a little differently. libfoo.so.0 -contains only the old APIs. libfoo.so.1 contains both the old and new -APIs. Legacy software that was linked with libfoo.so.0 continues to work -as libfoo.so.0 is usually left installed on the system. New software that -uses the new APIs is linked with libfoo.so.1, and works as long as -long as libfoo.so.1 is installed on the system. Accidentally (re)installing -libfoo.so.0 doesn't break new software as long as reinstalling doesn't -erase libfoo.so.1. - - Using symbol versions is somewhere in the middle. The shared library -file remains libfoo.so.0 forever. Legacy APIs may or may not have an -associated symbol version. New APIs may or may not have an associated -symbol version either. In general symbol versions are reserved for APIs -that have changed. Either the function's signature has changed, i.e. the -return time or the number of paramaters, and/or the parameter types have -changed. Another reason for using symbol versions on an API is when the -behaviour or functionality of the API changes dramatically. As with a -library that doesn't use versioned symbols, old and new applications -either find or don't find the versioned symbols they need. If the versioned -symbol doesn't exist in the installed library, the application incurs a -run-time error and terminates. - - GlusterFS wanted to keep tight control over the APIs in libgfapi. -Originally bumping the SO_NAME was considered, and GlusterFS-3.6.0 was -released with libgfapi.so.7. Not only was "7" a mistake (it should have -been "6"), but it was quickly pointed out that many dependent packages -that use libgfapi would be forced to be recompiled/relinked. Thus no -packages of 3.6.0 were ever released and 3.6.1 was quickly released with -libgfapi.so.0, but with symbol versions. There's no strong technical -reason for either; the APIs have not changed, only new APIs have been -added. It's merely being done in anticipation that some APIs might change -sometime in the future. - - Enough about that now, let's get into the nitty gritty—— - -2. Adding new APIs - -2.1. Adding a public API. - - This is the default, and the easiest thing to do. Public APIs have -declarations in either glfs.h, glfs-handles.h, or, at your discretion, -in a new header file intended for consumption by other developers. - -Here's what you need to do to add a new public API: - -+ Write the declaration, e.g. in glfs.h: - - int glfs_dtrt (const char *volname, void *stuff) __THROW - -+ Write the definition, e.g. in glfs-dtrt.c: - - int - pub_glfs_dtrt (const char *volname, void *stuff) - { - ... - return 0; - } - -+ Add the symbol version magic for ELF, gnu toolchain to the definition. - - following the definition of your new function in glfs-dtrtops.c, add a - line like this: - - GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_dtrt, 3.7.0) - - The whole thing should look like: - - int - pub_glfs_dtrt (const char *volname, void *stuff) - { - ... - } - GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_dtrt, 3.7.0); - - In this example, 3.7.0 refers to the Version the symbol will first - appear in. There's nothing magic about it, it's just a string token. - The current versions we have are 3.4.0, 3.4.2, 3.5.0, 3.5.1, and 3.6.0. - They are to be considered locked or closed. You can not, must not add - any new APIs and use these versions. Most new APIs will use 3.7.0. If - you add a new API appearing in 3.6.2 (and mainline) then you would use - 3.6.2. - -+ Add the symbol version magic for OS X to the declaration. - - following the declaration in glfs.h, add a line like this: - - GFAPI_PUBLIC(glfs_dtrt, 3.7.0) - - The whole thing should look like: - - int glfs_dtrt (const char *volname, void *stuff) __THROW - GFAPI_PUBLIC(glfs_dtrt, 3.7.0); - - The version here must match the version associated with the definition. - -+ Add the new API to the ELF, gnu toolchain link map file, gfapi.map - - Most new public APIs will probably be added to a new section that - looks like this: - - GFAPI_3.7.0 { - global: - glfs_dtrt; - } GFAPI_PRIVATE_3.7.0; - - if you're adding your new API to, e.g. 3.6.2, it'll look like this: - - GFAPI_3.6.2 { - global: - glfs_dtrt; - } GFAPI_3.6.0; - - and you must change the - GFAPI_PRIVATE_3.7.0 { ...} GFAPI_3.6.0; - section to: - GFAPI_PRIVATE_3.7.0 { ...} GFAPI_3.6.2; - -+ Add the new API to the OS X alias list file, gfapi.aliases. - - Most new APIs will use a line that looks like this: - - _pub_glfs_dtrt _glfs_dtrt$GFAPI_3.7.0 - - if you're adding your new API to, e.g. 3.6.2, it'll look like this: - - _pub_glfs_dtrt _glfs_dtrt$GFAPI_3.6.2 - -And that's it. - - -2.2. Adding a private API. - - If you're thinking about adding a private API that isn't declared in -one of the header files, then you should seriously rethink what you're -doing and figure out how to put it in libglusterfs instead. - -If that hasn't convinced you, follow the instructions above, but use the -_PRIVATE versions of macros, symbol versions, and aliases. If you're 1337 -enough to ignore this advice, then you're 1337 enough to figure out how -to do it. - - -3. Changing an API. - -3.1 Changing a public API. - - There are two ways an API might change, 1) its signature has changed, or -2) its new functionality or behavior is substantially different than the -old. An APIs signature consists of the function return type, and the number -and/or type of its parameters. E.g. the original API: - - int glfs_dtrt (const char *volname, void *stuff); - -and the changed API: - - void *glfs_dtrt (const char *volname, glfs_t *ctx, void *stuff); - - One way to avoid a change like this, and which is preferable in many -ways, is to leave the legacy glfs_dtrt() function alone, document it as -deprecated, and simply add a new API, e.g. glfs_dtrt2(). Practically -speaking, that's effectively what we'll be doing anyway, the difference -is only that we'll use a versioned symbol to do it. - - On the assumption that adding a new API is undesirable for some reason, -perhaps the use of glfs_gnu() is just so pervasive that we really don't -want to add glfs_gnu2(). - -+ change the declaration in glfs.h: - - glfs_t *glfs_gnu (const char *volname, void *stuff) __THROW - GFAPI_PUBLIC(glfs_gnu, 3.7.0); - -Note that there is only the single, new declaration. - -+ change the old definition of glfs_gnu() in glfs.c: - - struct glfs * - pub_glfs_gnu340 (const char * volname) - { - ... - } - GFAPI_SYMVER_PUBLIC(glfs_gnu340, glfs_gnu, 3.4.0); - -+ create the new definition of glfs_gnu in glfs.c: - - struct glfs * - pub_glfs_gnu (const char * volname, void *stuff) - { - ... - } - GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_gnu, 3.7.0); - -+ Add the new API to the ELF, gnu toolchain link map file, gfapi.map - - GFAPI_3.7.0 { - global: - glfs_gnu; - } GFAPI_PRIVATE_3.7.0; - -+ Update the OS X alias list file, gfapi.aliases, for both versions: - -Change the old line: - _pub_glfs_gnu _glfs_gnu$GFAPI_3.4.0 -to: - _pub_glfs_gnu340 _glfs_gnu$GFAPI_3.4.0 - -Add a new line: - _pub_glfs_gnu _glfs_gnu$GFAPI_3.7.0 - -+ Lastly, change all gfapi internal calls glfs_gnu to the new API. +See .../doc/gfapi-symbol-versions/gfapi-symbol-versions.md diff --git a/doc/gfapi-symbol-versions/gfapi-symbol-versions.md b/doc/gfapi-symbol-versions/gfapi-symbol-versions.md new file mode 100644 index 00000000000..e4f4fe9f052 --- /dev/null +++ b/doc/gfapi-symbol-versions/gfapi-symbol-versions.md @@ -0,0 +1,270 @@ + +## Symbol Versions and SO_NAMEs + + In general, adding new APIs to a shared library does not require that +symbol versions be used or the the SO_NAME be "bumped." These actions +are usually reserved for when a major change is introduced, e.g. many +APIs change or a signficant change in the functionality occurs. + + Over the normal lifetime of a When a new API is added, the library is +recompiled, consumers of the new API are able to do so, and existing, +legacy consumers of the original API continue as before. If by some +chance an old copy of the library is installed on a system, it's unlikely +that most applications will be affected. New applications that use the +new API will incur a run-time error terminate. + + Bumping the SO_NAME, i.e. changing the shared lib's file name, e.g. +from libfoo.so.0 to libfoo.so.1, which also changes the ELF SO_NAME +attribute inside the file, works a little differently. libfoo.so.0 +contains only the old APIs. libfoo.so.1 contains both the old and new +APIs. Legacy software that was linked with libfoo.so.0 continues to work +as libfoo.so.0 is usually left installed on the system. New software that +uses the new APIs is linked with libfoo.so.1, and works as long as +long as libfoo.so.1 is installed on the system. Accidentally (re)installing +libfoo.so.0 doesn't break new software as long as reinstalling doesn't +erase libfoo.so.1. + + Using symbol versions is somewhere in the middle. The shared library +file remains libfoo.so.0 forever. Legacy APIs may or may not have an +associated symbol version. New APIs may or may not have an associated +symbol version either. In general symbol versions are reserved for APIs +that have changed. Either the function's signature has changed, i.e. the +return time or the number of paramaters, and/or the parameter types have +changed. Another reason for using symbol versions on an API is when the +behaviour or functionality of the API changes dramatically. As with a +library that doesn't use versioned symbols, old and new applications +either find or don't find the versioned symbols they need. If the versioned +symbol doesn't exist in the installed library, the application incurs a +run-time error and terminates. + + GlusterFS wanted to keep tight control over the APIs in libgfapi. +Originally bumping the SO_NAME was considered, and GlusterFS-3.6.0 was +released with libgfapi.so.7. Not only was "7" a mistake (it should have +been "6"), but it was quickly pointed out that many dependent packages +that use libgfapi would be forced to be recompiled/relinked. Thus no +packages of 3.6.0 were ever released and 3.6.1 was quickly released with +libgfapi.so.0, but with symbol versions. There's no strong technical +reason for either; the APIs have not changed, only new APIs have been +added. It's merely being done in anticipation that some APIs might change +sometime in the future. + + Enough about that now, let's get into the nitty gritty—— + +## Adding new APIs + +### Adding a public API. + + This is the default, and the easiest thing to do. Public APIs have +declarations in either glfs.h, glfs-handles.h, or, at your discretion, +in a new header file intended for consumption by other developers. + +Here's what you need to do to add a new public API: + ++ Write the declaration, e.g. in glfs.h: + +```C + int glfs_dtrt (const char *volname, void *stuff) __THROW +``` + ++ Write the definition, e.g. in glfs-dtrt.c: + +```C + int + pub_glfs_dtrt (const char *volname, void *stuff) + { + ... + return 0; + } +``` + ++ Add the symbol version magic for ELF, gnu toolchain to the definition. + + following the definition of your new function in glfs-dtrtops.c, add a + line like this: + +```C + GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_dtrt, 3.7.0) +``` + + The whole thing should look like: + +```C + int + pub_glfs_dtrt (const char *volname, void *stuff) + { + ... + } + GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_dtrt, 3.7.0); +``` + + In this example, 3.7.0 refers to the Version the symbol will first + appear in. There's nothing magic about it, it's just a string token. + The current versions we have are 3.4.0, 3.4.2, 3.5.0, 3.5.1, and 3.6.0. + They are to be considered locked or closed. You can not, must not add + any new APIs and use these versions. Most new APIs will use 3.7.0. If + you add a new API appearing in 3.6.2 (and mainline) then you would use + 3.6.2. + ++ Add the symbol version magic for OS X to the declaration. + + following the declaration in glfs.h, add a line like this: + +```C + GFAPI_PUBLIC(glfs_dtrt, 3.7.0) +``` + + The whole thing should look like: + +```C + int glfs_dtrt (const char *volname, void *stuff) __THROW + GFAPI_PUBLIC(glfs_dtrt, 3.7.0); +``` + + The version here must match the version associated with the definition. + ++ Add the new API to the ELF, gnu toolchain link map file, gfapi.map + + Most new public APIs will probably be added to a new section that + looks like this: + +``` + GFAPI_3.7.0 { + global: + glfs_dtrt; + } GFAPI_PRIVATE_3.7.0; +``` + + if you're adding your new API to, e.g. 3.6.2, it'll look like this: + +``` + GFAPI_3.6.2 { + global: + glfs_dtrt; + } GFAPI_3.6.0; +``` + + and you must change the +``` + GFAPI_PRIVATE_3.7.0 { ...} GFAPI_3.6.0; +``` + section to: +``` + GFAPI_PRIVATE_3.7.0 { ...} GFAPI_3.6.2; +``` + ++ Add the new API to the OS X alias list file, gfapi.aliases. + + Most new APIs will use a line that looks like this: + +```C + _pub_glfs_dtrt _glfs_dtrt$GFAPI_3.7.0 +``` + + if you're adding your new API to, e.g. 3.6.2, it'll look like this: + +```C + _pub_glfs_dtrt _glfs_dtrt$GFAPI_3.6.2 +``` + +And that's it. + + +### Adding a private API. + + If you're thinking about adding a private API that isn't declared in +one of the header files, then you should seriously rethink what you're +doing and figure out how to put it in libglusterfs instead. + +If that hasn't convinced you, follow the instructions above, but use the +_PRIVATE versions of macros, symbol versions, and aliases. If you're 1337 +enough to ignore this advice, then you're 1337 enough to figure out how +to do it. + + +## Changing an API. + +### Changing a public API. + + There are two ways an API might change, 1) its signature has changed, or +2) its new functionality or behavior is substantially different than the +old. An APIs signature consists of the function return type, and the number +and/or type of its parameters. E.g. the original API: + +```C + int glfs_dtrt (const char *volname, void *stuff); +``` + +and the changed API: + +```C + void *glfs_dtrt (const char *volname, glfs_t *ctx, void *stuff); +``` + + One way to avoid a change like this, and which is preferable in many +ways, is to leave the legacy glfs_dtrt() function alone, document it as +deprecated, and simply add a new API, e.g. glfs_dtrt2(). Practically +speaking, that's effectively what we'll be doing anyway, the difference +is only that we'll use a versioned symbol to do it. + + On the assumption that adding a new API is undesirable for some reason, +perhaps the use of glfs_gnu() is just so pervasive that we really don't +want to add glfs_gnu2(). + ++ change the declaration in glfs.h: + +```C + glfs_t *glfs_gnu (const char *volname, void *stuff) __THROW + GFAPI_PUBLIC(glfs_gnu, 3.7.0); +```` + +Note that there is only the single, new declaration. + ++ change the old definition of glfs_gnu() in glfs.c: + +```C + struct glfs * + pub_glfs_gnu340 (const char * volname) + { + ... + } + GFAPI_SYMVER_PUBLIC(glfs_gnu340, glfs_gnu, 3.4.0); +``` + ++ create the new definition of glfs_gnu in glfs.c: + +```C + struct glfs * + pub_glfs_gnu (const char * volname, void *stuff) + { + ... + } + GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_gnu, 3.7.0); +``` + ++ Add the new API to the ELF, gnu toolchain link map file, gfapi.map + +``` + GFAPI_3.7.0 { + global: + glfs_gnu; + } GFAPI_PRIVATE_3.7.0; +``` + ++ Update the OS X alias list file, gfapi.aliases, for both versions: + +Change the old line: +```C + _pub_glfs_gnu _glfs_gnu$GFAPI_3.4.0 +``` +to: +```C + _pub_glfs_gnu340 _glfs_gnu$GFAPI_3.4.0 +``` + +Add a new line: +```C + _pub_glfs_gnu _glfs_gnu$GFAPI_3.7.0 +``` + ++ Lastly, change all gfapi internal calls glfs_gnu to the new API. + |