Solaris Containers: Resource Management and Solaris Zones Developer's Guide

Chapter 3 Using the C Interface to Extended Accounting

This chapter describes the C interface to extended accounting and covers the following topics:

Overview of the C Interface to Extended Accounting

Projects and tasks are used to label and separate workloads. The extended accounting subsystem is used to monitor resource consumption by workloads that are running on the system. Extended accounting produces accounting records for the workload tasks and processes.

For an overview of extended accounting and example procedures for administering extended accounting, see Chapter 4, Extended Accounting (Overview), in System Administration Guide: Solaris Containers-Resource Management and Solaris Zones and Chapter 5, Administering Extended Accounting (Tasks), in System Administration Guide: Solaris Containers-Resource Management and Solaris Zones.

The extended accounting framework has been expanded for zones. Each zone has its own extended accounting files for task and process-based accounting. The extended accounting files in the global zone contain accounting records for the global zone and for all non-global zones. The accounting records contain a zone name tag. The global zone administrator can use the tag during the extraction of per zone accounting data from the accounting files in the global zone.

Extended Accounting API Functions

The extended accounting API contains functions that perform the following:

exacct System Calls

 

 

 

The following table lists the system calls that interact with the extended accounting subsystem.

Table 3–1 Extended Accounting System Calls

Function 

Description 

putacct(2)

Provides privileged processes with the ability to tag accounting records with additional data that is specific to the process 

getacct(2)

Enables privileged processes to request extended accounting buffers from the kernel for currently executing tasks and processes 

wracct(2)

Requests the kernel to write resource usage data for a specified task or process 

Operations on the exacct File

These functions provide access to the exacct files:

Table 3–2 exacct File Functions

Function 

Description 

ea_open(3EXACCT)

Opens an exacct file.

ea_close(3EXACCT)

Closes an exacct file.

ea_get_object(3EXACCT)

First time use on a group of objects reads data into an ea_object_t structure. Subsequent use on the group cycles through the objects in the group.

ea_write_object(3EXACCT)

Appends the specified object to the open exacct file.

ea_next_object(3EXACCT)

Reads the basic fields (eo_catalog and eo_type) into an ea_object_t structure and rewinds to the head of the record.

ea_previous_object(3EXACCT)

Skips back one object in the exacct file and reads the basic fields (eo_catalog and eo_type) into an ea_object_t.

ea_get_hostname(3EXACCT)

Gets the name of the host on which the exacct file was created.

ea_get_creator(3EXACCT)

Determines the creator of the exacct file.

Operations on exacct Objects

These functions are used to access exacct objects:

Table 3–3 exacct Object Functions

Function 

Description 

ea_set_item(3EXACCT)

Assigns an exacct object and sets the value(s).

ea_set_group(3EXACCT)

Sets the values of a group of exacct objects.

ea_match_object_catalog(3EXACCT)

Checks an exacct object's mask to see if that object has a specific catalog tag.

ea_attach_to_object(3EXACCT)

Attaches an exacct object to a specified exacct object.

ea_attach_to_group(3EXACCT)

Attaches a chain of exacct objects as member items of a specified group.

ea_free_item(3EXACCT)

Frees the value fields in the specified exacct object.

ea_free_object(3EXACCT)

Frees the specified exacct object and any attached hierarchies of objects.

Memory Management

The following table lists the functions associated with extended accounting memory management. The function name is a link to its man page.

Table 3–4 Extended Accounting Memory Management Functions

Link to man page 

Description 

ea_pack_object(3EXACCT)

Converts an exacct object from unpacked (in-memory) representation to packed (in-file) representation.

ea_unpack_object(3EXACCT)

Converts an exacct object from packed (in-file) representation to unpacked (in-memory) representation.

ea_strdup(3EXACCT)

Duplicates a string that is to be stored inside an ea_object_t structure.

ea_strfree(3EXACCT)

Frees a string previously copied by ea_strdup().

ea_alloc(3EXACCT)

Allocates a block of memory of the requested size. This block can be safely passed to libexacct functions, and can be safely freed by any of the ea_free functions.

ea_free(3EXACCT)

Frees a block of memory previously allocated by ea_alloc().

ea_free_object(3EXACCT)

Frees variable-length data in object hierarchy. 

ea_free_item(3EXACCT)

Frees value fields of designated object, if EUP_ALLOC is specified. The object is not freed. ea_free_object() frees the specified object and any attached hierarchy of objects. If the flag argument is set to EUP_ALLOC, ea_free_object() also frees any variable-length data in the object hierarchy. If the flag argument is set to EUP_NOALLOC, ea_free_object() does not free the variable-length data. In particular, these flags should correspond to the flags specified in calls to ea_unpack_object(3EXACCT).

ea_copy_object(3EXACCT)

Copies an ea_object_t. If the source object is part of a chain, only the current object is copied. If the source object is a group, only the group object is copied without its list of members. The group object eg_nobjs and eg_objs fields are set to 0 and NULL respectively. Use ea_copy_tree() to copy recursively a group or a list of items.

ea_copy_object_tree(3EXACCT)

ea_copy_object_tree recursively copies an ea_object_t. All elements in the eo_next list are copied. Any group objects are recursively copied. The returned object can be completely freed with ea_free_object(3EXACCT) by specifying the EUP_ALLOC flag.

ea_get_object_tree()

Reads in nobj top-level objects from the file, returning the same data structure that would have originally been passed to ea_write_object(). On encountering a group object,ea_get_object() reads only the group header part of the group. ea_get_object_tree() reads the group and all its member items, recursing into subrecords if necessary. The returned object data structure can be completely freed with ea_free_object() by specifying the EUP_ALLOC flag.

Miscellaneous Operations

These functions are associated with miscellaneous operations:

ea_error(3EXACCT)

ea_match_object_catalog(3EXACCT)

C Code Examples for Accessing exacct Files

This section provides code examples for accessing exacct files.


Example 3–1 Displaying exacct Data for a Designated pid

This example displays a specific pid's exacct data snapshot from the kernel.

...
  ea_object_t *scratch;
  int unpk_flag = EUP_ALLOC;  /* use the same allocation flag */
                              /* for unpack and free */

  /* Omit return value checking, to keep code samples short */

  bsize = getacct(P_PID, pid, NULL, 0);
  buf = malloc(bsize);

  /* Retrieve exacct object and unpack */
  getacct(P_PID, pid, buf, bsize);
  ea_unpack_object(&scratch, unpk_flag, buf, bsize);

  /* Display the exacct record */
  disp_obj(scratch);
  if (scratch->eo_type == EO_GROUP) {
         disp_group(scratch);
  }
  ea_free_object(scratch, unpk_flag);
		...	


Example 3–2 Identifying Individual Tasks During a Kernel Build

This example evaluates kernel builds and displays a string that describes the portion of the source tree being built by this task make. Display the portion of the source being built to aid in the per-source-directory analysis.

The key points for this example include the following:

  ...
/* Omit return value checking and error processing */
/* to keep code sample short */
ptid = gettaskid();	/* Save "parent" task-id */
tid = settaskid(getprojid(), TASK_NORMAL);	/* Create new task */

/* Set data for item objects ptskid and cwd */
ea_set_item(&ptskid, EXT_UINT32 | EXC_LOCAL | MY_PTID, &ptid, 0);
ea_set_item(&cwd, EXT_STRING | EXC_LOCAL | MY_CWD, cwdbuf, strlen(cwdbuf));

/* Set grp object and attach ptskid and cwd to grp */
ea_set_group(&grp, EXT_GROUP | EXC_LOCAL |  EXD_GROUP_HEADER);
ea_attach_to_group(&grp, &ptskid);
ea_attach_to_group(&grp, &cwd);

/* Pack the object and put it back into the accounting stream */
ea_buflen = ea_pack_object(&grp, ea_buf, sizeof(ea_buf));
putacct(P_TASKID, tid, ea_buf, ea_buflen, EP_EXACCT_OBJECT);

/* Memory management: free memory allocate in ea_set_item */
ea_free_item(&cwd, EUP_ALLOC);
  ...


Example 3–3 Reading and Displaying the Contents of a System exacct File

This example shows how to read and display a system exacct file for a process or a task.

The key points for this example include the following:

/* Omit return value checking and error processing */
/* to keep code sample short */
main(int argc, char *argv)
{
  ea_file_t ef;
  ea_object_t scratch;
  char *fname;
		
  fname = argv[1];
  ea_open(&ef, fname, NULL,  EO_NO_VALID_HDR, O_RDONLY, 0);
  bzero(&scratch, sizeof (ea_object_t));
  while (ea_get_object(&ef, &scratch)  != -1) {
	     disp_obj(&scratch);
	     if (scratch.eo_type == EO_GROUP)
	         disp_group(&ef, scratch.eo_group.eg_nobjs);
	     bzero(&scratch, sizeof (ea_object_t));
  }
  ea_close(&ef);
}

struct catalog_item {   /* convert Solaris catalog's type ID */
                        /* to a meaningful string */
	 int	type;
	 char *name;
 } catalog[] = {
	 { EXD_VERSION, 	"version\t" },
	 ...
	 { EXD_PROC_PID,	"  pid\t" },
	 ...
   };

 static char *
 catalog_name(int type)
 {
	 int i = 0;
	 while (catalog[i].type != EXD_NONE) {
		 if (catalog[i].type == type)
			 return (catalog[i].name);	
		 else
			 i++;
	 }
	 return ("unknown\t");
 }

 static void disp_obj(ea_object_t *o)
 {
	 printf("%s\t", catalog_name(o->eo_catalog & 0xffffff));
	 switch(o->eo_catalog & EXT_TYPE_MASK) {
	 case EXT_UINT8:
		 printf(" 8: %u", o->eo_item.ei_uint8);
		 break;
	 case EXT_UINT16:
	 ...
 }
 static void disp_group(ea_file_t *ef, uint_t nobjs)
 {
	 for (i = 0; i < nobjs; i++) {
		 ea_get_object(ef, &scratch));
             	 disp_obj(&scratch);
		 if (scratch.eo_type == EO_GROUP)
                disp_group(ef, scratch.eo_group.eg_nobjs);
        }
 }

Programming Issues With exacct Files