SCORPIO  1.7.0
Guide for Contributors

Introduction

This document describes the code style to be used when contributing to the SCORPIO library.

C Code

Backward Compatibility

We cannot remove or change a function in the public C API. Please create a github issue if a new API is required.

Indentation and Spacing

  • Use spaces not tabs.
  • 4 spaces is the unit of intendation for C sources.
  • Indentation as defined by the "Linux" style in emacs (see below).
  • Use spaces around most operators not pointer or prefix/postfix
  • Spaces after most keywords (if, for, while, etc.)
  • No spaces after function name.

Braces

Put braces on their own line in the C sources.

Documentation

  • Every function must be documented using doxygen.
  • Keep internal functions in separate code files, so that Doxygen can easily build user and development builds of the documentation.
  • Use the doxygen @ingroup to put public functions in the correct group.
  • Use C (not C++) comment delimiters.

Emacs

Put this in your .emacs file:

(setq c-default-style "linux"
          c-basic-offset 4)

The tab key (used anywhere on the line) will indent a line correctly. M-x indent-region will indent a selected region of code.

M-x untabify will convert all the tabs in a file to spaces.

Code Review

  • Each pull request should be focused on a single issue.

  • Please ensure that all tests pass in the development branch in your development environment before submitting a pull request.

  • All non-trivial pull requests need to be associated with a github issue. The issue is where discussion of requirements and implementation details can be worked out.

Merge Proceedure

  • Programmers begin work on a feature or fix by branching from the master branch

  • When a branch is ready, it is submitted to code review.

  • When code review is complete, and the changes are approved, the PR is merged into the develop branch.

  • The develop branch is tested automatically by Jenkins.

  • After all jenkins and Cdash builds complete successfully, with all tests passing, the PR is merged into master by the integrator.

  • Multiple PRs may be merged to master between test cycles.

  • The branch is then deleted by whomever merged it to master.

Formatting Example

/** 
   @ingroup PIOc_inq_attname
   The PIO-C interface for the NetCDF function nc_inq_attname.

   This routine is called collectively by all tasks in the communicator 
   ios.union_comm. For more information on the underlying NetCDF commmand
   please read about this function in the NetCDF documentation at: 
   http://www.unidata.ucar.edu/software/netcdf/docs/group__attributes.html

   @param ncid the ncid of the open file, obtained from
   PIOc_openfile() or PIOc_createfile().
   @param varid the variable ID.
   @param attnum the attribute ID.
   @return PIO_NOERR for success, error code otherwise.  See PIOc_Set_File_Error_Handling
 */
int PIOc_inq_attname(int ncid, int varid, int attnum, char *name) 
{
    iosystem_desc_t *ios;  /* Pointer to io system information. */
    file_desc_t *file;     /* Pointer to file information. */
    int ierr = PIO_NOERR;  /* Return code from function calls. */
    int mpierr = MPI_SUCCESS, mpierr2;  /* Return code from MPI function codes. */

    LOG((1, "PIOc_inq_attname ncid = %d varid = %d attnum = %d", ncid, varid,
         attnum));

    /* Find the info about this file. */
    if (!(file = pio_get_file_from_id(ncid)))
        return PIO_EBADID;
    ios = file->iosystem;

    /* If async is in use, and this is not an IO task, bcast the parameters. */
    if (ios->async_interface)
    {
        if (!ios->ioproc)
        {
            int msg = PIO_MSG_INQ_ATTNAME;
            char name_present = name ? true : false;

            if(ios->compmaster) 
                mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm);

            if (!mpierr)
                mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm);
            if (!mpierr)
                mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm);
            if (!mpierr)
                mpierr = MPI_Bcast(&attnum, 1, MPI_INT, ios->compmaster, ios->intercomm);
            if (!mpierr)
                mpierr = MPI_Bcast(&name_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm);
        }

        /* Handle MPI errors. */
        if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm)))
            check_mpi(file, mpierr2, __FILE__, __LINE__);
        if (mpierr)
            return check_mpi(file, mpierr, __FILE__, __LINE__);
    }

    /* If this is an IO task, then call the netCDF function. */
    if (ios->ioproc)
    {
#ifdef _PNETCDF
        if (file->iotype == PIO_IOTYPE_PNETCDF)
            ierr = ncmpi_inq_attname(file->fh, varid, attnum, name);
#endif /* _PNETCDF */
#ifdef _NETCDF
        if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io)
            ierr = nc_inq_attname(file->fh, varid, attnum, name);
#endif /* _NETCDF */
        LOG((2, "PIOc_inq_attname netcdf call returned %d", ierr));
    }

    /* Broadcast and check the return code. */
    if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm)))
    {
        check_mpi(file, mpierr, __FILE__, __LINE__);            
        return PIO_EIO;
    }
    check_netcdf(file, ierr, __FILE__, __LINE__);

    /* Broadcast results to all tasks. Ignore NULL parameters. */
    if (!ierr)
        if (name)
        {
            int namelen = strlen(name);
            if ((mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->ioroot, ios->my_comm)))
                check_mpi(file, mpierr, __FILE__, __LINE__);
            if ((mpierr = MPI_Bcast((void *)name, namelen + 1, MPI_CHAR, ios->ioroot,
                                    ios->my_comm)))
                check_mpi(file, mpierr, __FILE__, __LINE__);
        }

    return ierr;
}

#

Further Information

For style issues not already covered in this document, see this style guide.

Last updated: 05-16-2016