OpenSAF Developer's Handbook
1 Introduction
This document gives basic guidelines to community for making contributions to OpenSAF code. This document is divided in to following sections:
- Usability Requirements
- Base infrastructure usage
- Coding guidelines
- Feature Contribution Guideline
2 Terminology
In this the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" are to be interpreted as described in RFC 2119 [2].
3 Usability Requirements
This section lists the requirements imposed on OpenSAF from it’s usage perspective.
- OpenSAF users shall be able to migrate their applications from another SAF AIS implementation by simply modifying the build system and doing the configuration changes.
- OpenSAF management interface shall end with SAF IMM interface. Different management clients like SNMP, CLI or CIM might interface with OpenSAF using the IMM interface.
- Note: At this point of time IMM is not part of OpenSAF
- OpenSAF by default should provide CLI as the management client.
- OpenSAF should follow the LSB (Linux Standard base) and Linux FHS guidelines for it’s deliverables(code, directory structure, packaging etc)
- OpenSAF contributions shall be in-service upgradeable. In a running cluster, upgrade from current release to the next release and downgrade from current release to the previous release shall be supported at a minimum.
- Note: Upgrade mechanisms are not in the scope of OpenSAF at this point of time.
- OpenSAF contributions shall follow the current OpenSAF architecture.
- OpenSAF contributions shall be made highly available using OpenSAF AMF implementation (availability service)
- Software components running on the system controller shall use 2N redundancy model
- Software components running on the payload nodes should be restart capable.
- Open SAF contributions shall provide test code to cover functional test cases. New test contributions shall use existing test framework rather than contributing different test frameworks.
4 Base Infrastructure Usage
OpenSAF offers implementations for SAF AIS services and complementary middleware services where there are no SAF services defined. OpenSAF uses these complementary services (going forward we call them as OpenSAF infrastructure) for implementing the AIS services. The following are the guidelines for using opensaf infrastructure service for new opensaf contributions.
- Shall use Message distribution service or MDS for intra-cluster messaging.
- Shall use either OpenSAF checkpoint service of OpenSAF MBCSv for data replication (check pointing) needs.
- Shall use DTSv for tracing purposes, SAF log service for logging purposes.(when available)
- Shall not use MASv for distributed management, but should use IMM once the service is part of openSAF.
- Shall use POSIX for OS abstraction (LEAP where POSIX alternative not available)
5 C Coding Guidelines
The following coding guidelines needs to be followed when making contributions to OpenSAF.
- License
- All files (source files, header files, scripts, and make files) should begin with OpenSAF license.
- File Naming Convention
- File name shall use lowercase letters and underbars as appropriate.
- File names shall reflect functional partitioning through filename prefixes.
- File names shall be short, but there is no rule governing file name length.
- All public header files shall be placed in /opensaf/include folder.
- Function Naming Convention
- Function names shall be descriptive of the service provided.
- Function names shall use lower case characters and underscore for separators.
- Function names shall be unique on a system wide basis across all OpenSAF Services.
- Function names are formed as <svc-name>_<noun>_<verb>.
- <svc-name> service or sub-part of opensaf.
- <noun> what this function represents.
- <verb> what the function does.
- Note: For non SAF service, public APIs prefix the function name with opensaf_.
- Function signatures should look like the following unless they exceed 80 characters when the parameters can be placed in different lines.
static void foo(arg1, arg2, arg3, ...)
{
}
- Naming of structures & Variables
- Structure names should be in lowercase and tag names should be in uppercase.
- Variable name should be in lowercases, separated by underbars (do not use Hungarian notation). It is recommended to use following prefix guidelines for the variables:
- p_ for pointer variables
- s_ for static variables gl_ for global variables
- i_ for function input arguments
- o_ for function output arguments
- io_ for function input-output arguments
- Library Naming & Versioning conventions
- Shall follow Auto tools library naming convention libOpenSAF.so.<CURRENT>.<REVISION>.<AGE>
- There is no direct correlation between SAF AIS specifications and openSAF library versions. Initially opensaf libraries starts with 1.0.0
- Indentation and Bracing Style
The recommended bracing style for OpenSAF code is the Allman Style. This is the style where the opening brace is lined up with the first character of the control statement.
if (<cond>)
{ /* lines up with first char of the ctl statement */
<body> /* body indented 4 characters (no TABS!! */
} /* lines up with opening brace */
Same bracing style is used for control statements as well for functions.
- Comment Style
- Use the standard C comment for /* */ only. Double slash comments // are forbidden, since some C compilers do not accept them.
- The comments should follow the Doxygen comment format for C. This is mandatory for all public header files located in /opensaf/include, as the user documentation is generated using Doxygen.
- Indentation: Indentation shall be 4 characters wide, with white spaces and no tabs are allowed.
6 Script Coding Guidelines
This chapter describes the coding style for scripts.
- bash (or sh) is the preferred shell
- indentation, 4 spaces, no tabs
- avoid global variables
- use local variables and arguments in functions
- local variables should be lowercase
- exported (to sub shells) variables should be uppercase
- Comments are indented as commands
- Flow control, place a semi colon on the opening line together with the next keyword, examples:
if [ -n $x ]; then for x := 1 to 10; do
- case statements should include a catch all default pattern, example:
case expr in pattern1 ) statements ;; pattern2 ) statements ;; * ) statements ;; esac
7 Feature Contribution Guideline
All new OpenSAF contributions shall be subject to the process as outlined in the OpenSAF Technical Development Process document before being accepted into the OpenSAF code repository.
8 Guidelines for Patch Contribution to OpenSAF
While submitting patches to OpenSAF the following procedure should be followed.
8.1 Introduction to Mercurial
The OpenSAF project uses the Mercurial distributed revision control system (aka 'hg'), for patching, branching and tagging source code.
See Links for more details on Mercurial:
http://www.selenic.com/mercurial/wiki/
http://devel.opensaf.org/wiki/DevelGuide
8.2 Submitting a patch to the OpenSAF Project
- If your patch is extensive, discuss it first on the devel@… mailing list. In fact, for extensive changes, it's a good idea to have this discussion before you invest too much time in coding. It's possible that your idea overlaps with something else already in the works, or that your idea is unlikely to be accepted because it would conflict with planned directions for OpenSAF.
- It's better to submit multiple patches with separate bits of functionality than a big patch containing lots of changes. Big, intertwined sets of changes increase the chances of unintended side effects that could cause the entire patch to be rejected. If you submit separate functional changes in separate patches, those change that meet all the criteria can still be integrated even though other pieces might be held up for one reason or another. The patches must be self-contained even in a series and the system must build after each patch. For those big major changes that affect too many files the developer should publish a repository with all the relevant changes preferably based on the latest Beta/Milestone/Release Candidate/General Availability.
- Submit your patch in "hg diff" format. In particular, do not submit whole source files, or diff output without any kind of context information. It is more difficult to integrate whole source files or plain diff output with other changes to the OpenSAF code base, especially other changes that might be integrated after you've submitted your patch.
hg diff > patch.file
diff -r 6556b700c674 services/mds/src/mds_c_db.c
--- a/services/mds/src/mds_c_db.c Mon Feb 11 02:38:53 2008 -0700
+++ b/services/mds/src/mds_c_db.c Wed Mar 05 13:22:11 2008 -0500
@@ -225,7 +225,7 @@
else
{
m_MDS_LOG_DBG("MCM_DB : Leaving : S : mds_vdest_tbl_query");
- return NCSCC_RC_SUCCESS;
+ return NCSCC_RC_FAILURE;
}
}
- With the preference being (c) above, the project will also accept patches generated using the "diff - Naurp" format. This will allow submitters who choose not to use Mercurial for source control.
diff -Naurp services/mds/src/mds_c_db.c services/mds/src/mds_c_db.c.mod
--- services/mds/src/mds_c_db.c 2008-03-03 14:45:08.000000000 -0500
+++ services/mds/src/mds_c_db.c.mod 2008-02-25 12:28:22.000000000 -0500
@@ -225,7 +225,7 @@ uns32 mds_vdest_tbl_query (MDS_VDEST_ID
else
{
m_MDS_LOG_DBG("MCM_DB : Leaving : S : mds_vdest_tbl_query");
- return NCSCC_RC_SUCCESS;
+ return NCSCC_RC_FAILURE;
}
}
- Submit a test case Your patch must include test case before it can be integrated! THIS IS THE SINGLE MOST COMMON REASON FOR DELAYS IN INTEGRATING PATCHES AND THE SINGLE MOST IMPORTANT THING YOU CAN DO TO INCREASE THE CHANCES OF YOUR PATCH BEING INTEGRATED QUICKLY.
The OpenSAF development methodology requires that each change be accompanied by one or more new or modified test cases that get added to our extensive regression test suite. This is to make sure that the behavior added by your patch doesn't get inadvertently broken by other changes in the future. Patches that fix bugs should contain at least one test case that demonstrates the behavior being fixed by the patch. For example, if you're fixing a configuration that causes OpenSAF to exit with an error and a stack trace, the test case should trigger that stack trace when run against the current code. Patches that add new features or enhancements should contain test cases that use the new behavior being added to OpenSAF.
You can do any of the following to supply test cases with your patch:
Include actual new or modified OpenSAF test scripts in your patch. This is the best option because it's the easiest to integrate, and therefore maximizes the chances of your patch being accepted quickly. (Note that, yes, there's a curve to learning how to write test scripts in the OpenSAF testing harness. We're working on documentation to deal with that.)
Include a .tar.gz or .zip file containing test configurations. If you can't quite figure out how to deal with the OpenSAF test scripts, the next best option is to include with your patch an archive file containing one or more actual test configurations (OpenSAF script files, input files, etc.). It will be relatively straightforward for someone integrating your patch, and who's presumably familiar with the OpenSAF testing harness, to turn this into an appropriate test script. Be sure to include a description of how to run your recommended test scenario, or a script for doing so.
Describe how to go about testing the patch. If you really can't cook up a test configuration to include with the patch, the lowest-common-denominator approach is to just describe how to go about testing the patch. Be as specific as possible, even if you think it should be obvious how to test the patch. It might be clear to you while you're writing the code, but it might still take someone else 15 or more minutes of making sure they understand your intent. The point is you're trying to use your knowledge to save time during the integration process, thereby increasing the chance of your patch making it into the OpenSAF code base.
If you don't supply any sort of testing information with your patch, well, you're still welcome to submit the code. Just be aware that the patch will likely stay in the queue until someone has time to reverse- engineer a test case.
- Ensure that your patch does not add new trailing whitespace. The below script will fix up your patch by stripping off such whitespace.
#!/bin/sh
strip1()
{
TMP=$(mktemp /tmp/XXXXXX)
cp "$1" "$TMP"
sed -e '/^+/s/[ ]*$//' <"$TMP" >"$1"
rm "$TMP"
}
for i in "$@"
do
strip1 "$i"
done
8.3 Patch Delivery
- Patches are delivered via email only.
- One patch per email, with the changelog in the body of the email.
- A regression test should be submitted along with a patch to verify the patch.
8.3.1 E-mail Subject of the patch
- The email's Subject: should concisely describe the patch which that email contains. The Subject: should not be a filename. Use different Subject:'s for each patch in a patch series. The 'Service' should be added to retain the change in the changelog.
Bear in mind that the Subject: of your email becomes a globally-unique identifier for that patch. It propagates all the way into the revision control system. The Subject: may later be used in developer discussions which refer to the patch. People will want to google for the patch's Subject: to read discussion regarding that patch.
If patch is related to an Ticket add "(ticket #<num>)" to the end of the subject.
- Example Subject: [PATCH]: PSS - reformat pss early (ticket #269)
- Module owners must use subject content (except content within square brackets [] as commit message when committing a patch to a Mercurial branch.
- Note that various patch receiving scripts will strip away Subject: text which is inside brackets []. Information which has no long-term relevance to the patch is inside brackets. This includes the word "patch" and any sequence numbering. The 'LEAP:' is the Service name the patch applies to. Other Service names might be AvSv, GLSV or PSSv for example. Make sure this is outside the [] brackets.
8.3.2 Attribution
If someone else wrote the patch, they should be credited for it. To communicate this, add a line:
From: John Doe <jdoe@…>
as the very first line of the email. Patch tools will pick this up and jdoe will get the credit.
8.3.3 Changelog
- Bear in mind that the Subject: and changelog which you provide will propagate all the way into the permanent record. Other developers will want to read and understand your patch and changelog years in the future.
So the changelog should describe the patch fully:
Why is the patch needed
The overall design approach in the patch
Implementation details
Test results
- Do not refer to earlier patches when changelogging a new version of a patch. It's not very useful to have a final changelog which says "OK, this fixes the things you mentioned yesterday". Each iteration of the patch should contain a standalone changelog.
- Add a Signed-off-by: line.
Signed-off-by: implies that you had some part in the development of the patch, or that you handled it and passed it on to another developer for merging.
8.3.4 Patch Series
- When sending a series of patches, number them in the Subject:s thusly:
[PATCH 1/10 1.0-2-leap-ncs_os_task]: LEAP: optimize/add new stack [PATCH 2/10 1.0-2-leap-ncs_os_task]: LEAP: optimize to use stack etc.
- If your patch series includes non-runtime-affecting things such as cleanups, whitespace fixes, file renames, moving functions around, etc. then this work should be done in the initial patches in the series. The functional changes should come later in the series.
NOTE:
Each patch in a series must be self-containing. It's desirable that the system would work or at least compile in the middle of the series.
8.3.5 Overall
- Avoid MIME and attachments if possible. Make sure that your email client does not wordwrap your patch. Make sure that your email client does not replace tabs with spaces. Mail yourself a decent-sized patch and check that it still applies.
- MIME attachments are an acceptable. You must ensure that the attached patches have text/plain mimetypes.
