source: trunk/athena/etc/larvnetd/report.c @ 12057

Revision 12057, 6.7 KB checked in by ghudson, 26 years ago (diff)
Support specification of explicit printer locations.
Line 
1/* Copyright 1998 by the Massachusetts Institute of Technology.
2 *
3 * Permission to use, copy, modify, and distribute this
4 * software and its documentation for any purpose and without
5 * fee is hereby granted, provided that the above copyright
6 * notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting
8 * documentation, and that the name of M.I.T. not be used in
9 * advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission.
11 * M.I.T. makes no representations about the suitability of
12 * this software for any purpose.  It is provided "as is"
13 * without express or implied warranty.
14 */
15
16/* This file is part of larvnetd, a monitoring server.  It implements
17 * the generation of reports.
18 */
19
20static const char rcsid[] = "$Id: report.c,v 1.3 1998-10-21 20:02:06 ghudson Exp $";
21
22#include <sys/types.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <syslog.h>
26#include "larvnetd.h"
27#include "larvnet.h"
28#include "timer.h"
29
30#define PATH_CGROUPS_NEW        LARVNET_PATH_CGROUPS ".new"
31#define PATH_CLUSTERS_NEW       LARVNET_PATH_CLUSTERS ".new"
32#define PATH_PRINTERS_NEW       LARVNET_PATH_PRINTERS ".new"
33
34struct outof {
35  int nfree;
36  int total;
37};
38
39static void report_cgroups(struct config *config);
40static void report_clusters(struct config *config);
41static void report_printers(struct config *config);
42static int find_arch(struct config *config, const char *archname);
43
44void report(void *arg)
45{
46  struct config *config = (struct config *) arg;
47
48  timer_set_rel(60, report, config);
49  syslog(LOG_DEBUG, "report");
50
51  report_cgroups(config);
52  report_clusters(config);
53  report_printers(config);
54}
55
56static void report_cgroups(struct config *config)
57{
58  FILE *fp;
59  int i, j;
60  struct cgroup *cgroup;
61  struct cluster *cluster;
62  struct printer *printer;
63
64  fp = fopen(PATH_CGROUPS_NEW, "w");
65  if (fp)
66    {
67      for (i = 0 ; i < config->ncgroups; i++)
68        {
69          cgroup = &config->cgroups[i];
70          fprintf(fp, "%s %d %d", cgroup->name, cgroup->x, cgroup->y);
71          for (j = 0; j < config->nclusters; j++)
72            {
73              cluster = &config->clusters[j];
74              if (cluster->cgroup == i)
75                fprintf(fp, " %s %s", cluster->name, cluster->phone);
76            }
77          fprintf(fp, " ---");
78          for (j = 0; j < config->nprinters; j++)
79            {
80              printer = &config->printers[j];
81              cluster = &config->clusters[printer->cluster];
82              if (cluster->cgroup == i)
83                fprintf(fp, " %s", printer->name);
84            }
85          fprintf(fp, "\n");
86        }
87      fclose(fp);
88      if (rename(PATH_CGROUPS_NEW, LARVNET_PATH_CGROUPS) == -1)
89        {
90          syslog(LOG_ERR, "report: can't replace %s with %s: %m",
91                 LARVNET_PATH_CGROUPS, PATH_CGROUPS_NEW);
92        }
93    }
94  else
95    {
96      syslog(LOG_ERR, "report: can't open %s for writing: %m",
97             PATH_CGROUPS_NEW);
98    }
99}
100
101static void report_clusters(struct config *config)
102{
103  FILE *fp;
104  int i, j;
105  struct cluster *cluster;
106  struct machine *machine;
107  struct outof **entries, *ent;
108
109  /* For each cluster and architecture, we need to compute the number
110   * of free machines and total number of machines.  Allocate and
111   * initialize a matrix of outof structures to store the data.
112   * Leave an extra two entries at the end of each row for other and
113   * unknown architectures.
114   */
115  entries = emalloc(config->nclusters * sizeof(struct outof *));
116  for (i = 0; i < config->nclusters; i++)
117    {
118      entries[i] = emalloc((config->narch + 2) * sizeof(struct outof));
119      for (j = 0; j < config->narch + 2; j++)
120        {
121          entries[i][j].nfree = 0;
122          entries[i][j].total = 0;
123        }
124    }
125
126  /* Now compute the free machines and total machines for each cluster
127   * and architecture.
128   */
129  for (i = 0; i < config->nmachines; i++)
130    {
131      machine = &config->machines[i];
132      ent = &entries[machine->cluster][find_arch(config, machine->arch)];
133      if (machine->busy == FREE)
134        ent->nfree++;
135      ent->total++;
136    }
137
138  /* Write out the cluster status file. */
139  fp = fopen(PATH_CLUSTERS_NEW, "w");
140  if (fp)
141    {
142      /* Write out the architecture names and a divider. */
143      for (i = 0; i < config->narch; i++)
144        fprintf(fp, "%s\n", config->arches[i].reportname);
145      if (config->report_other)
146        fprintf(fp, "%s\n", config->report_other);
147      if (config->report_unknown)
148        fprintf(fp, "%s\n", config->report_unknown);
149      fprintf(fp, "---\n");
150
151      /* Write out the data for each cluster. */
152      for (i = 0; i < config->nclusters; i++)
153        {
154          /* Start with the cluster configuration information. */
155          cluster = &config->clusters[i];
156          fprintf(fp, "%s %s %s", cluster->name,
157                  (cluster->cgroup == -1) ? "private" : "public",
158                  cluster->phone);
159
160          /* Write out the totals for each defined architecture. */
161          for (j = 0; j < config->narch; j++)
162            fprintf(fp, " %d %d", entries[i][j].nfree, entries[i][j].total);
163          if (config->report_other)
164            {
165              fprintf(fp, " %d %d", entries[i][config->narch].nfree,
166                      entries[i][config->narch].total);
167            }
168          if (config->report_unknown)
169            {
170              fprintf(fp, " %d %d", entries[i][config->narch + 1].nfree,
171                      entries[i][config->narch + 1].total);
172            }
173          fprintf(fp, "\n");
174        }
175      fclose(fp);
176      if (rename(PATH_CLUSTERS_NEW, LARVNET_PATH_CLUSTERS) == -1)
177        {
178          syslog(LOG_ERR, "report: can't replace %s with %s: %m",
179                 LARVNET_PATH_CLUSTERS, PATH_CLUSTERS_NEW);
180        }
181    }
182  else
183    {
184      syslog(LOG_ERR, "report: can't open %s for writing: %m",
185             PATH_CLUSTERS_NEW);
186    }
187
188  /* Free the matrix we allocated above. */
189  for (i = 0; i < config->nclusters; i++)
190    free(entries[i]);
191  free(entries);
192}
193
194static void report_printers(struct config *config)
195{
196  FILE *fp;
197  int i;
198  struct printer *printer;
199
200  fp = fopen(PATH_PRINTERS_NEW, "w");
201  if (fp)
202    {
203      for (i = 0; i < config->nprinters; i++)
204        {
205          printer = &config->printers[i];
206          fprintf(fp, "%s %s %s %d\n", printer->name, printer->location,
207                  (printer->up) ? "up" : "down", printer->jobs);
208        }
209      fclose(fp);
210      if (rename(PATH_PRINTERS_NEW, LARVNET_PATH_PRINTERS) == -1)
211        {
212          syslog(LOG_ERR, "report: can't replace %s with %s: %m",
213                 LARVNET_PATH_PRINTERS, PATH_PRINTERS_NEW);
214        }
215    }
216  else
217    {
218      syslog(LOG_ERR, "report: can't open %s for writing: %m",
219             PATH_PRINTERS_NEW);
220    }
221}
222
223static int find_arch(struct config *config, const char *archname)
224{
225  int i, j;
226  struct archname *arch;
227
228  /* If the workstation has not reported an architecture or reported
229   * an empty string, return config->narch + 1 for "unknown".
230   */
231  if (!archname || !*archname)
232    return config->narch + 1;
233
234  /* Look for the name in the list of defined architectures. */
235  for (i = 0; i < config->narch; i++)
236    {
237      arch = &config->arches[i];
238      for (j = 0; j < arch->nnetnames; j++)
239        {
240          if (strcmp(arch->netnames[j], archname) == 0)
241            return i;
242        }
243    }
244
245  /* Return config->narch for "other". */
246  return config->narch;
247}
Note: See TracBrowser for help on using the repository browser.