Exemplo n.º 1
0
//! Collect values in counters
static void intel_snb_cbo_collect(struct stats_type *type)
{

  int i;

  for (i = 0; i < nr_cpus; i++) {
    char cpu[80];
    char core_id_path[80];

    char socket[80];
    char socket_id_path[80];

    char cpu_box[80];

    int socket_id = -1;
    int core_id = -1;
    int box;

    /* Only collect uncore counters on core 0 of a socket. */
    snprintf(core_id_path, sizeof(core_id_path), 
	     "/sys/devices/system/cpu/cpu%d/topology/core_id", i);
    if (pscanf(core_id_path, "%d", &core_id) != 1) {
      ERROR("cannot read core id file `%s': %m\n", core_id_path);
      continue;
    }
    if (core_id != 0)
      continue;

    /* Get socket number. */
    snprintf(socket_id_path, sizeof(socket_id_path), 
	     "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i);
    if (pscanf(socket_id_path, "%d", &socket_id) != 1) {
      ERROR("cannot read socket id file `%s': %m\n", socket_id_path);
      continue;
    }

    snprintf(cpu, sizeof(cpu), "%d", i);
    snprintf(socket, sizeof(socket), "%d", socket_id);

    if (cpu_is_sandybridge(cpu))
      {
	for (box = 0; box < 8; box++)
	  {
	    snprintf(cpu_box, sizeof(cpu_box), "%d/%d", socket_id, box);
	    intel_snb_cbo_collect_box(type, cpu, cpu_box, box);
	  }
      }
  }
}
Exemplo n.º 2
0
	const char *
	cpu_perc(void)
	{
		static long double a[7];
		long double b[7], sum;

		memcpy(b, a, sizeof(b));
		/* cpu user nice system idle iowait irq softirq */
		if (pscanf("/proc/stat", "%*s %Lf %Lf %Lf %Lf %Lf %Lf %Lf",
		           &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6])
		    != 7) {
			return NULL;
		}
		if (b[0] == 0) {
			return NULL;
		}

		sum = (b[0] + b[1] + b[2] + b[3] + b[4] + b[5] + b[6]) -
		      (a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6]);

		if (sum == 0) {
			return NULL;
		}

		return bprintf("%d", (int)(100 *
		               ((b[0] + b[1] + b[2] + b[5] + b[6]) -
		                (a[0] + a[1] + a[2] + a[5] + a[6])) / sum));
	}
Exemplo n.º 3
0
Arquivo: 7-4.c Projeto: 1sps/knr
/* main: test pscanf */
int main(void) 
{
	int i;
	float f;
	char c, str[100];

	pscanf("%c%d  %f	%s", &c, &i, &f, str);
	printf("c: %c, i: %d, f: %f, str: %s\n", c, i, f, str);
	return 0;
}
Exemplo n.º 4
0
//! Collect values of counters
static void intel_snb_pcu_collect(struct stats_type *type)
{
    // CPUs 0 and 8 have core_id 0 on Stampede at least

    int i;
    for (i = 0; i < nr_cpus; i++) {
        char cpu[80];
        char core_id_path[80];
        int core_id = -1;

        char socket[80];
        char socket_id_path[80];
        int socket_id = -1;

        char pcu[80];

        /* Only collect uncore counters on core 0 of a socket. */
        snprintf(core_id_path, sizeof(core_id_path),
                 "/sys/devices/system/cpu/cpu%d/topology/core_id", i);
        if (pscanf(core_id_path, "%d", &core_id) != 1) {
            ERROR("cannot read core id file `%s': %m\n", core_id_path); /* errno */
            continue;
        }
        if (core_id != 0)
            continue;

        /* Get socket number. */
        snprintf(socket_id_path, sizeof(socket_id_path),
                 "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i);
        if (pscanf(socket_id_path, "%d", &socket_id) != 1) {
            ERROR("cannot read socket id file `%s': %m\n", socket_id_path);
            continue;
        }

        snprintf(cpu, sizeof(cpu), "%d", i);
        snprintf(socket, sizeof(socket), "%d", socket_id);
        if (cpu_is_sandybridge(cpu))
        {
            snprintf(pcu, sizeof(pcu), "%d", socket_id);
            intel_snb_pcu_collect_socket(type, cpu, pcu);
        }
    }
}
Exemplo n.º 5
0
	const char *
	ram_total(void)
	{
		uintmax_t total;

		if (pscanf("/proc/meminfo", "MemTotal: %ju kB\n", &total)
		    != 1) {
			return NULL;
		}

		return fmt_human(total * 1024, 1024);
	}
Exemplo n.º 6
0
	const char *
	cpu_freq(void)
	{
		uintmax_t freq;

		/* in kHz */
		if (pscanf("/sys/devices/system/cpu/cpu0/cpufreq/"
		           "scaling_cur_freq", "%ju", &freq) != 1) {
			return NULL;
		}

		return fmt_human(freq * 1000, 1000);
	}
Exemplo n.º 7
0
static int
find_ib_device_events(ib_device_t *dev, int extended)
{
   int nevents = 0;
   DIR *cnt_dir = NULL;
   char counters_path[128];
   snprintf(counters_path, sizeof(counters_path), "%s/%s/ports/%d/counters%s", 
          ib_dir_path, dev->dev_name, dev->dev_port, (extended?"_ext":""));
   
   cnt_dir = opendir(counters_path);
   if (cnt_dir == NULL) {
      SUBDBG("cannot open counters directory `%s'\n", counters_path);
      goto out;
   }
   
   struct dirent *ev_ent;
   /* iterate over all the events */
   while ((ev_ent = readdir(cnt_dir)) != NULL) {
      char *ev_name = ev_ent->d_name;
      long long value = -1;
      char event_path[160];
      char counter_name[80];

      if (ev_name[0] == '.')
         continue;

      /* Check that we can read an integer from the counter file */
      snprintf(event_path, sizeof(event_path), "%s/%s", counters_path, ev_name);
      if (pscanf(event_path, "%lld", &value) != 1) {
        SUBDBG("cannot read value for event '%s'\n", ev_name);
        continue;
      }

      /* Create new counter */
      snprintf(counter_name, sizeof(counter_name), "%s_%d%s:%s", 
            dev->dev_name, dev->dev_port, (extended?"_ext":""), ev_name);
      if (add_ib_counter(counter_name, ev_name, extended, dev))
      {
         SUBDBG("Added new counter `%s'\n", counter_name);
         nevents += 1;
      }
   }

 out:
  if (cnt_dir != NULL)
    closedir(cnt_dir);

  return (nevents);
}
Exemplo n.º 8
0
	const char *
	ram_free(void)
	{
		uintmax_t free;

		if (pscanf("/proc/meminfo",
		           "MemTotal: %ju kB\n"
		           "MemFree: %ju kB\n"
		           "MemAvailable: %ju kB\n",
		           &free, &free, &free) != 3) {
			return NULL;
		}

		return fmt_human(free * 1024, 1024);
	}
Exemplo n.º 9
0
int stats_wr_hdr(struct stats_buffer *sf)
{
  struct utsname uts_buf;
  unsigned long long uptime = 0;
  
  uname(&uts_buf);
  pscanf("/proc/uptime", "%llu", &uptime);
  
  sf->sf_data = "";
  sf_printf(sf, "%c%s %s\n", SF_PROPERTY_CHAR, STATS_PROGRAM, STATS_VERSION);

  sf_printf(sf, "%chostname %s\n", SF_PROPERTY_CHAR, uts_buf.nodename);
  sf_printf(sf, "%cuname %s %s %s %s\n", SF_PROPERTY_CHAR, uts_buf.sysname,
            uts_buf.machine, uts_buf.release, uts_buf.version);
  sf_printf(sf, "%cuptime %llu\n", SF_PROPERTY_CHAR, uptime);

  size_t i = 0;
  struct stats_type *type;
  while ((type = stats_type_for_each(&i)) != NULL) {
    if (!type->st_enabled)
      continue;

    TRACE("type %s, schema_len %zu\n", type->st_name, type->st_schema.sc_len);

    /* Write schema. */
    sf_printf(sf, "%c%s", SF_SCHEMA_CHAR, type->st_name);

    /* MOVEME */
    size_t j;
    for (j = 0; j < type->st_schema.sc_len; j++) {
      struct schema_entry *se = type->st_schema.sc_ent[j];
      sf_printf(sf, " %s", se->se_key);
      if (se->se_type == SE_CONTROL)
        sf_printf(sf, ",C");
      if (se->se_type == SE_EVENT)
        sf_printf(sf, ",E");
      if (se->se_unit != NULL)
        sf_printf(sf, ",U=%s", se->se_unit);
      if (se->se_width != 0)
        sf_printf(sf, ",W=%u", se->se_width);
    }
    sf_printf(sf, "\n");
  }

  send(sf);

  return 0;
}
Exemplo n.º 10
0
	const char *
	ram_used(void)
	{
		uintmax_t total, free, buffers, cached;

		if (pscanf("/proc/meminfo",
		           "MemTotal: %ju kB\n"
		           "MemFree: %ju kB\n"
		           "MemAvailable: %ju kB\n"
		           "Buffers: %ju kB\n"
		           "Cached: %ju kB\n",
		           &total, &free, &buffers, &buffers, &cached) != 5) {
			return NULL;
		}

		return fmt_human((total - free - buffers - cached) * 1024,
		                 1024);
	}
Exemplo n.º 11
0
//! Configure and start counters
static int intel_snb_cbo_begin(struct stats_type *type)
{
  int nr = 0;

  uint64_t cbo_events[8][4] = {
    { RxR_OCCUPANCY, LLC_LOOKUP, COUNTER0_OCCUPANCY, CLOCK_TICKS, },
    { RxR_OCCUPANCY, LLC_LOOKUP, COUNTER0_OCCUPANCY, CLOCK_TICKS, },
    { RxR_OCCUPANCY, LLC_LOOKUP, COUNTER0_OCCUPANCY, CLOCK_TICKS, },
    { RxR_OCCUPANCY, LLC_LOOKUP, COUNTER0_OCCUPANCY, CLOCK_TICKS, },
    { RxR_OCCUPANCY, LLC_LOOKUP, COUNTER0_OCCUPANCY, CLOCK_TICKS, },
    { RxR_OCCUPANCY, LLC_LOOKUP, COUNTER0_OCCUPANCY, CLOCK_TICKS, },
    { RxR_OCCUPANCY, LLC_LOOKUP, COUNTER0_OCCUPANCY, CLOCK_TICKS, },
    { RxR_OCCUPANCY, LLC_LOOKUP, COUNTER0_OCCUPANCY, CLOCK_TICKS, },
  };

  int i;
  for (i = 0; i < nr_cpus; i++) {
    char cpu[80];
    char core_id_path[80];
    int core_id = -1;
    int box;
    /* Only program uncore counters on core 0 of a socket. */

    snprintf(core_id_path, sizeof(core_id_path), "/sys/devices/system/cpu/cpu%d/topology/core_id", i);
    if (pscanf(core_id_path, "%d", &core_id) != 1) {
      ERROR("cannot read core id file `%s': %m\n", core_id_path); /* errno */
      continue;
    }

    if (core_id != 0)
      continue;

    snprintf(cpu, sizeof(cpu), "%d", i);
    
    if (cpu_is_sandybridge(cpu))      
      {
	for (box = 0; box < 8; box++)
	  if (intel_snb_cbo_begin_box(cpu, box, cbo_events[box], 4) == 0)
	    nr++;
      }
  }

  return nr > 0 ? 0 : -1;
}
Exemplo n.º 12
0
static long long
read_ib_counter_value(int index)
{
   char ev_file[128];
   long long value = 0ll;
   infiniband_native_event_entry_t *iter = &infiniband_native_events[index];
   snprintf(ev_file, sizeof(ev_file), "%s/%s/ports/%d/counters%s/%s",
           ib_dir_path, iter->device->dev_name,
           iter->device->dev_port, (iter->extended?"_ext":""),
           iter->file_name);

   if (pscanf(ev_file, "%lld", &value) != 1) {
      PAPIERROR("cannot read value for counter '%s'\n", iter->name);
   } else
   {
      SUBDBG("Counter '%s': %lld\n", iter->name, value);
   }
   return (value);
}
Exemplo n.º 13
0
	const char *
	ram_perc(void)
	{
		uintmax_t total, free, buffers, cached;

		if (pscanf("/proc/meminfo",
		           "MemTotal: %ju kB\n"
		           "MemFree: %ju kB\n"
		           "MemAvailable: %ju kB\n"
		           "Buffers: %ju kB\n"
		           "Cached: %ju kB\n",
		           &total, &free, &buffers, &buffers, &cached) != 5) {
			return NULL;
		}

		if (total == 0) {
			return NULL;
		}

		return bprintf("%d", 100 * ((total - free) - (buffers + cached))
                               / total);
	}
Exemplo n.º 14
0
//! Configure and start counters
static int intel_snb_pcu_begin(struct stats_type *type)
{
    int nr = 0;

    uint64_t pcu_events[4] = {FREQ_MAX_TEMP_CYCLES,
                              FREQ_MAX_POWER_CYCLES,
                              FREQ_MIN_IO_CYCLES,
                              FREQ_MIN_SNOOP_CYCLES
                             };


    int i;
    for (i = 0; i < nr_cpus; i++) {
        char cpu[80];
        char core_id_path[80];
        int core_id = -1;
        /* Only program uncore counters on core 0 of a socket. */

        snprintf(core_id_path, sizeof(core_id_path), "/sys/devices/system/cpu/cpu%d/topology/core_id", i);
        if (pscanf(core_id_path, "%d", &core_id) != 1) {
            ERROR("cannot read core id file `%s': %m\n", core_id_path); /* errno */
            continue;
        }

        if (core_id != 0)
            continue;

        snprintf(cpu, sizeof(cpu), "%d", i);

        if (cpu_is_sandybridge(cpu))
        {
            if (intel_snb_pcu_begin_socket(cpu, pcu_events,4) == 0)
                nr++; /* HARD */
        }
    }

    return nr > 0 ? 0 : -1;
}
Exemplo n.º 15
0
static void ps_collect_loadavg(struct stats *stats)
{
  const char *path = "/proc/loadavg";
  unsigned long long load[3][2];
  unsigned long long nr_running = 0, nr_threads = 0;

  memset(load, 0, sizeof(load));

  /* Ignore last_pid (sixth field). */
  if (pscanf(path, "%llu.%llu %llu.%llu %llu.%llu %llu/%llu",
             &load[0][0], &load[0][1],
             &load[1][0], &load[1][1],
             &load[2][0], &load[2][1],
             &nr_running, &nr_threads) != 8) {
    /* XXX */
    return;
  }

  stats_set(stats, "load_1",  load[0][0] * 100 + load[0][1]);
  stats_set(stats, "load_5",  load[1][0] * 100 + load[1][1]);
  stats_set(stats, "load_15", load[2][0] * 100 + load[2][1]);
  stats_set(stats, "nr_running", nr_running);
  stats_set(stats, "nr_threads", nr_threads);
}
Exemplo n.º 16
0
static int 
find_ib_devices() 
{
  DIR *ib_dir = NULL;
  int result = PAPI_OK;
  num_events = 0;

  ib_dir = opendir(ib_dir_path);
  if (ib_dir == NULL) {
     SUBDBG("cannot open `%s'\n", ib_dir_path);
     strncpy(_infiniband_vector.cmp_info.disabled_reason,
                 "Infiniband sysfs interface not found", PAPI_MAX_STR_LEN);
     result = PAPI_ENOSUPP;
     goto out;
  }

  struct dirent *hca_ent;
  while ((hca_ent = readdir(ib_dir)) != NULL) {
     char *hca = hca_ent->d_name;
     char ports_path[80];
     DIR *ports_dir = NULL;

     if (hca[0] == '.')
        goto next_hca;

     snprintf(ports_path, sizeof(ports_path), "%s/%s/ports", ib_dir_path, hca);
     ports_dir = opendir(ports_path);
     if (ports_dir == NULL) {
        SUBDBG("cannot open `%s'\n", ports_path);
        goto next_hca;
     }

     struct dirent *port_ent;
     while ((port_ent = readdir(ports_dir)) != NULL) {
        int port = atoi(port_ent->d_name);
        if (port <= 0)
           continue;

        /* Check that port is active. .../HCA/ports/PORT/state should read "4: ACTIVE." */
        int state = -1;
        char state_path[80];
        snprintf(state_path, sizeof(state_path), "%s/%s/ports/%d/state", ib_dir_path, hca, port);
        if (pscanf(state_path, "%d", &state) != 1) {
           SUBDBG("cannot read state of IB HCA `%s' port %d\n", hca, port);
           continue;
        }

        if (state != 4) {
           SUBDBG("skipping inactive IB HCA `%s', port %d, state %d\n", hca, port, state);
           continue;
        }

        /* Create dev name (HCA/PORT) and get stats for dev. */
        SUBDBG("Found IB device `%s', port %d\n", hca, port);
        ib_device_t *dev = add_ib_device(hca, port);
        if (!dev)
           continue;
        // do we want to check for short counters only if no extended counters found?
        num_events += find_ib_device_events(dev, 1);  // check if we have extended (64bit) counters
        num_events += find_ib_device_events(dev, 0);  // check also for short counters
     }

   next_hca:
      if (ports_dir != NULL)
         closedir(ports_dir);
   }

   if (root_device == 0)  // no active devices found
   {
     strncpy(_infiniband_vector.cmp_info.disabled_reason,
                 "No active Infiniband ports found", PAPI_MAX_STR_LEN);
     result = PAPI_ENOIMPL;
   } else if (num_events == 0)
   {
     strncpy(_infiniband_vector.cmp_info.disabled_reason,
                 "No supported Infiniband events found", PAPI_MAX_STR_LEN);
     result = PAPI_ENOIMPL;
   } else
   {
      // Events are stored in a linked list, in reverse order than how I found them
      // Revert them again, so that they are in finding order, not that it matters.
      int i = num_events - 1;
      // now allocate memory to store the counters into the native table
      infiniband_native_events = (infiniband_native_event_entry_t*)
           papi_calloc(sizeof(infiniband_native_event_entry_t), num_events);
      ib_counter_t *iter = root_counter;
      while (iter != 0)
      {
         infiniband_native_events[i].name = iter->ev_name;
         infiniband_native_events[i].file_name = iter->ev_file_name;
         infiniband_native_events[i].device = iter->ev_device;
         infiniband_native_events[i].extended = iter->extended;
         infiniband_native_events[i].resources.selector = i + 1;
         infiniband_native_events[i].description = 
                  make_ib_event_description(iter->ev_file_name, iter->extended);
         
         ib_counter_t *tmp = iter;
         iter = iter->next;
         papi_free(tmp);
         -- i;
      }
      root_counter = 0;
   }
   
   out:
      if (ib_dir != NULL)
         closedir(ib_dir);
    
   return (result);
}
Exemplo n.º 17
0
static void collect_ib_sw(struct stats_type *type)
{
  const char *ib_dir_path = "/sys/class/infiniband";
  DIR *ib_dir = NULL;

  ib_dir = opendir(ib_dir_path);
  if (ib_dir == NULL) {
    ERROR("cannot open `%s': %m\n", ib_dir_path);
    goto out;
  }

  struct dirent *hca_ent;
  while ((hca_ent = readdir(ib_dir)) != NULL) {
    char *hca = hca_ent->d_name;
    char ports_path[80];
    DIR *ports_dir = NULL;

    if (hca[0] == '.')
      goto next_hca;

    snprintf(ports_path, sizeof(ports_path), "%s/%s/ports", ib_dir_path, hca);
    ports_dir = opendir(ports_path);
    if (ports_dir == NULL) {
      ERROR("cannot open `%s': %m\n", ports_path);
      goto next_hca;
    }

    struct dirent *port_ent;
    while ((port_ent = readdir(ports_dir)) != NULL) {
      int port = atoi(port_ent->d_name);
      if (port <= 0)
        continue;

      /* Check that port is active. .../HCA/ports/PORT/state should read "4: ACTIVE." */
      int state = -1;
      char state_path[80];
      snprintf(state_path, sizeof(state_path), "/sys/class/infiniband/%s/ports/%d/state", hca, port);
      if (pscanf(state_path, "%d", &state) != 1) {
        ERROR("cannot read state of IB HCA `%s' port %d: %m\n", hca, port);
        continue;
      }

      if (state != 4) {
        TRACE("skipping inactive IB HCA `%s', port %d, state %d\n", hca, port, state);
        continue;
      }

      /* Create dev name (HCA/PORT) and get stats for dev. */
      char dev[80];
      snprintf(dev, sizeof(dev), "%s/%d", hca, port);
      TRACE("IB HCA `%s', port %d, dev `%s'\n", hca, port, dev);

      struct stats *stats = get_current_stats(type, dev);
      if (stats == NULL)
        continue;

      collect_hca_port(stats, hca, port);
    }

  next_hca:
    if (ports_dir != NULL)
      closedir(ports_dir);
  }

 out:
  if (ib_dir != NULL)
    closedir(ib_dir);
}
Exemplo n.º 18
0
int main(int argc, char *argv[])
{
  int lock_fd = -1;
  int lock_timeout = 30;
  const char *current_path = STATS_DIR_PATH"/current";
  const char *mark = NULL;
  int rc = 0;

  struct option opts[] = {
    { "help", 0, 0, 'h' },
    { "mark", 0, 0, 'm' },
    { NULL, 0, 0, 0 },
  };

  int c;
  while ((c = getopt_long(argc, argv, "hm:", opts, 0)) != -1) {
    switch (c) {
    case 'h':
      usage();
      exit(0);
    case 'm':
      mark = optarg;
      break;
    case '?':
      fprintf(stderr, "Try `%s --help' for more information.\n", program_invocation_short_name);
      exit(1);
    }
  }

  umask(022);

  if (!(optind < argc))
    FATAL("must specify a command\n");

  const char *cmd_str = argv[optind];
  char **arg_list = argv + optind + 1;
  size_t arg_count = argc - optind - 1;

  enum {
    cmd_begin,
    cmd_collect,
    cmd_end,
    cmd_rotate,
  } cmd;

  if (strcmp(cmd_str, "begin") == 0)
    cmd = cmd_begin;
  else if (strcmp(cmd_str, "collect") == 0)
    cmd = cmd_collect;
  else if (strcmp(cmd_str, "end") == 0)
    cmd = cmd_end;
  else if (strcmp(cmd_str, "rotate") == 0)
    cmd = cmd_rotate;
  else
    FATAL("invalid command `%s'\n", cmd_str);

  lock_fd = open_lock_timeout(STATS_LOCK_PATH, lock_timeout);
  if (lock_fd < 0)
    FATAL("cannot acquire lock\n");

  if (cmd == cmd_rotate) {
    if (unlink(current_path) < 0 && errno != ENOENT) {
        ERROR("cannot unlink `%s': %m\n", current_path);
        rc = 1;
    }
    goto out;
  }

  current_time = time(NULL);
  pscanf(JOBID_FILE_PATH, "%79s", current_jobid);
  nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);

  if (mkdir(STATS_DIR_PATH, 0777) < 0) {
    if (errno != EEXIST)
      FATAL("cannot create directory `%s': %m\n", STATS_DIR_PATH);
  }

  struct stats_file sf;
  if (stats_file_open(&sf, current_path) < 0) {
    rc = 1;
    goto out;
  }

  int enable_all = 0;
  int select_all = cmd != cmd_collect || arg_count == 0;

  if (sf.sf_empty) {
    char *link_path = strf("%s/%ld", STATS_DIR_PATH, current_time);
    if (link_path == NULL)
      ERROR("cannot create path: %m\n");
    else if (link(current_path, link_path) < 0)
      ERROR("cannot link `%s' to `%s': %m\n", current_path, link_path);
    free(link_path);
    enable_all = 1;
    select_all = 1;
  }

  size_t i;
  struct stats_type *type;

  if (cmd == cmd_collect) {
    /* If arg_count is zero then we select all below. */
    for (i = 0; i < arg_count; i++) {
      type = stats_type_get(arg_list[i]);
      if (type == NULL) {
        ERROR("unknown type `%s'\n", arg_list[i]);
        continue;
      }
      type->st_selected = 1;
    }
  }

  i = 0;
  while ((type = stats_type_for_each(&i)) != NULL) {
    if (enable_all)
      type->st_enabled = 1;

    if (!type->st_enabled)
      continue;

    if (stats_type_init(type) < 0) {
      type->st_enabled = 0;
      continue;
    }

    if (select_all)
      type->st_selected = 1;

    if (cmd == cmd_begin && type->st_begin != NULL)
      (*type->st_begin)(type);

    if (type->st_enabled && type->st_selected)
      (*type->st_collect)(type);
  }

  if (mark != NULL)
    stats_file_mark(&sf, "%s", mark);
  else if (cmd == cmd_begin || cmd == cmd_end)
    /* On begin set mark to "begin JOBID", and similar for end. */
    stats_file_mark(&sf, "%s %s", cmd_str, arg_count > 0 ? arg_list[0] : "-");

  if (stats_file_close(&sf) < 0)
    rc = 1;

  /* Cleanup. */
  i = 0;
  while ((type = stats_type_for_each(&i)) != NULL)
    stats_type_destroy(type);

 out:
  return rc;
}