現在位置: ホーム / みらくるブログ / パッチダウンロード / get_poller_status.c

get_poller_status.c

Pollerプロセスの状態を取得します。

C source code icon get_poller_status.c — C source code, 5 KB (5639 bytes)

ファイルコンテンツ

/*
 * Licensing:
 * Some parts of this code is imported from Zabbix-2.0.10 and
 * util-linux-ng-2.17.2/sys-utils/ipcs.c. But, licensing detail is
 * not written in ipcs.c... 
 * So, I decided the license to GPLv3.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/times.h>

#if defined (__GLIBC__) && __GLIBC__ >= 2
#define KEY __key
#else
#define KEY key
#endif

#ifndef HAVE_UNION_SEMUN
/* according to X/OPEN we have to define it ourselves */
union semun {
  int val;
  struct semid_ds *buf;
  unsigned short int *array;
  struct seminfo *__buf;
};
#endif

#define ZBX_PROCESS_STATE_COUNT 2
#define ZBX_PROCESS_TYPE_POLLER 0
#define ZBX_PROCESS_TYPE_COUNT 21 /* number of process types */

#define MAX_HISTORY 60

typedef struct {
  unsigned short h_counter[ZBX_PROCESS_STATE_COUNT][MAX_HISTORY];
  unsigned short counter[ZBX_PROCESS_STATE_COUNT];
  clock_t last_ticks;
  unsigned char last_state;
}
zbx_stat_process_t;

typedef struct {
  zbx_stat_process_t **process;
  int first;
  int count;
}
zbx_selfmon_collector_t;

#define CONFIG_FILE "/etc/zabbix/zabbix_server.conf"
#define ZBX_IPC_SELFMON_ID 'S'

void mutex_lock(int semid, int mutex_selfmon)
{
  struct sembuf sem_lock;

  sem_lock.sem_num = mutex_selfmon;
  sem_lock.sem_op = -1;
  sem_lock.sem_flg = SEM_UNDO;

  if (semop(semid, &sem_lock, 1) == -1) {
    fprintf(stderr, "cannnot access semaphore\n");
    exit(EXIT_FAILURE);
  }
}

void mutex_unlock(int semid, int mutex_selfmon)
{
  struct sembuf sem_unlock;

  sem_unlock.sem_num = mutex_selfmon;
  sem_unlock.sem_op = 1;
  sem_unlock.sem_flg = SEM_UNDO;

  if (semop(semid, &sem_unlock, 1) == -1) {
    fprintf(stderr, "cannnot access semaphore\n");
    exit(EXIT_FAILURE);
  }
}

int get_shmid(char *conf)
{
  key_t shm_key;
  int maxid, id, shmid = -1;
  struct shmid_ds shmseg;
  struct shminfo shminfo;
  struct ipc_perm *ipcp = &shmseg.shm_perm;

  if ((shm_key = ftok(conf, ZBX_IPC_SELFMON_ID)) == -1) {
    fprintf(stderr, "cannot create IPC key for a self-monitoring collector\n");
    goto out;
  }

  fprintf(stdout, "shm_key = 0x%08x\n", shm_key);

  if ((maxid = shmctl(0, SHM_INFO, (struct shmid_ds *) (void *) &shminfo)) < 0) {
    fprintf(stderr, "kernel not configured for shared memory\n");
    goto out;
  }

  for (id = 0; id <= maxid; id++) {
    shmid = shmctl(id, SHM_STAT, &shmseg);
    if (shmid < 0)
      continue;
    if (shm_key == ipcp->KEY)
      break;
  }
  if (shmid < 0 || id > maxid) {
    fprintf(stdout, "cannot find shared memory for a self-monitoring collector\n");
    shmid = -1;
  }
  fprintf(stdout, "shmid = %-10d\n", shmid);

out:
  return shmid;
}

int get_semid(char *conf)
{
  key_t sem_key;
  int maxid, semid = -1, id;
  struct semid_ds semary;
  struct seminfo seminfo;
  struct ipc_perm *ipcp = &semary.sem_perm;
  union semun arg;

  if ((sem_key = ftok(conf, (int)'z')) == -1) {
    fprintf(stderr, "cannot create IPC key for a self-monitoring collector\n");
    goto out;
  }

  fprintf(stdout, "sem_key = 0x%08x\n", sem_key);

  arg.array = (ushort *)  (void *) &seminfo;
  maxid = semctl(0, 0, SEM_INFO, arg);

  if (maxid < 0) {
    fprintf(stderr, "kernel not configured for semaphores\n");
    goto out;
  }

  for (id = 0; id <= maxid; id++) {
    arg.buf = (struct semid_ds *) &semary;
    semid = semctl(id, 0, SEM_STAT, arg);
    if (semid < 0)
      continue;
    if (sem_key == ipcp->KEY)
      break;
  }
  if (semid < 0 || id > maxid) {
    fprintf(stdout, "cannot find semaphore for a self-monitoring collector\n");
    semid = -1;
  }
  fprintf(stdout, "semid = %-10d\n", semid);

out:
  return semid;
}

void usage(char *prog)
{
  fprintf(stderr, "Usage: %s [-c config_file] [-p poller_process] -z zabbix_version\n", prog);
}

int get_mutex_selfmon(char *zop)
{
  int zver;
  zop += 4;

  zver = atoi(zop);
  if (zver < 0) return -1;
  else if (zver < 7) return 7;
  else return 6;
}

int main(int argc, char *argv[])
{
  int retval = 1, i, opt;
  static char *conf_file = CONFIG_FILE;
  int poller_process = 5;
  int mutex_selfmon, zflag = 0;

  int shmid, semid;
  zbx_selfmon_collector_t *collector;
  char *p;
  zbx_stat_process_t *process;

  while ((opt = getopt(argc, argv, "c:p:z:")) != -1) {
    switch (opt) {
    case 'c':
      conf_file = optarg;
      break;
    case 'p':
      poller_process = atoi(optarg);
      break;
    case 'z':
      if (strncmp(optarg, "2.0.", 4) != 0) {
        usage(argv[0]);
        exit(EXIT_FAILURE);
      }
      if ((mutex_selfmon = get_mutex_selfmon(optarg)) == -1) {
        fprintf(stderr, "incorrect zabbix version\n");
        exit(EXIT_FAILURE);
      }
      zflag = 1;
      break;
    default: /* '?' */
      usage(argv[0]);
      exit(EXIT_FAILURE);
    }
  }
  if (zflag == 0) {
    usage(argv[0]);
    exit(EXIT_FAILURE);
  }

  if ((shmid = get_shmid(conf_file)) == -1) goto out;
  if ((semid = get_semid(conf_file)) == -1) goto out;

  if ((p = (char *)shmat(shmid, NULL, 0)) == (void *)(-1)) {
    fprintf(stderr, "cannot attach shared memory for a self-monitoring collector\n");
    goto out;
  }

  mutex_lock(semid, mutex_selfmon);

  collector = (zbx_selfmon_collector_t *)p;
  p += sizeof(zbx_selfmon_collector_t);
  p += sizeof(zbx_stat_process_t *) * ZBX_PROCESS_TYPE_COUNT;
  process = (zbx_stat_process_t *)p;

  for (i = 0; i < poller_process; i++) {
    fprintf(stdout, "Poller[%d] last_ticks = %ld\n", i, process[i].last_ticks);
  }

  mutex_unlock(semid, mutex_selfmon);

  shmdt(collector);

  retval = 0;
out:
  return retval;
}