usrdb.c (5f6f6b2933fa608f6dd5c8d9769eba8b8d5e9c2b) | usrdb.c (fdbe5babe4c36438757554fd0b61ff7ba19b0dc2) |
---|---|
1/* 2 * Copyright (c) 1994 Christopher G. Demetriou 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 35 unchanged lines hidden (view full) --- 44#include <string.h> 45#include "extern.h" 46#include "pathnames.h" 47 48static int uid_compare(const DBT *, const DBT *); 49 50static DB *usracct_db; 51 | 1/* 2 * Copyright (c) 1994 Christopher G. Demetriou 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 35 unchanged lines hidden (view full) --- 44#include <string.h> 45#include "extern.h" 46#include "pathnames.h" 47 48static int uid_compare(const DBT *, const DBT *); 49 50static DB *usracct_db; 51 |
52int 53usracct_init() | 52/* Legacy format in AHZV1 units. */ 53struct userinfov1 { 54 uid_t ui_uid; /* user id; for consistency */ 55 u_quad_t ui_calls; /* number of invocations */ 56 u_quad_t ui_utime; /* user time */ 57 u_quad_t ui_stime; /* system time */ 58 u_quad_t ui_mem; /* memory use */ 59 u_quad_t ui_io; /* number of disk i/o ops */ 60}; 61 62/* 63 * Convert a v1 data record into the current version. 64 * Return 0 if OK, -1 on error, setting errno. 65 */ 66static int 67v1_to_v2(DBT *key, DBT *data) |
54{ | 68{ |
55 DB *saved_usracct_db; 56 BTREEINFO bti; 57 int error; | 69 struct userinfov1 uiv1; 70 static struct userinfo uiv2; 71 static uid_t uid; |
58 | 72 |
59 bzero(&bti, sizeof bti); 60 bti.compare = uid_compare; 61 62 usracct_db = dbopen(NULL, O_RDWR, 0, DB_BTREE, &bti); 63 if (usracct_db == NULL) | 73 if (key->size != sizeof(u_long) || data->size != sizeof(uiv1)) { 74 errno = EFTYPE; |
64 return (-1); | 75 return (-1); |
76 } |
|
65 | 77 |
66 error = 0; 67 if (!iflag) { 68 DBT key, data; 69 int serr, nerr; | 78 /* Convert key. */ 79 key->size = sizeof(uid_t); 80 uid = (uid_t)*(u_long *)(key->data); 81 key->data = &uid; |
70 | 82 |
71 saved_usracct_db = dbopen(usrdb_file, O_RDONLY, 0, DB_BTREE, 72 &bti); 73 if (saved_usracct_db == NULL) { 74 error = (errno == ENOENT) ? 0 : -1; 75 if (error) 76 warn("retrieving user accounting summary"); 77 goto out; 78 } | 83 /* Convert data. */ 84 memcpy(&uiv1, data->data, data->size); 85 memset(&uiv2, 0, sizeof(uiv2)); 86 uiv2.ui_uid = uiv1.ui_uid; 87 uiv2.ui_calls = uiv1.ui_calls; 88 uiv2.ui_utime = ((double)uiv1.ui_utime / AHZV1) * 1000000; 89 uiv2.ui_stime = ((double)uiv1.ui_stime / AHZV1) * 1000000; 90 uiv2.ui_mem = uiv1.ui_mem; 91 uiv2.ui_io = uiv1.ui_io; 92 data->size = sizeof(uiv2); 93 data->data = &uiv2; |
79 | 94 |
80 serr = DB_SEQ(saved_usracct_db, &key, &data, R_FIRST); 81 if (serr < 0) { 82 warn("retrieving user accounting summary"); 83 error = -1; 84 goto closeout; 85 } 86 while (serr == 0) { 87 nerr = DB_PUT(usracct_db, &key, &data, 0); 88 if (nerr < 0) { 89 warn("initializing user accounting stats"); 90 error = -1; 91 break; 92 } | 95 return (0); 96} |
93 | 97 |
94 serr = DB_SEQ(saved_usracct_db, &key, &data, R_NEXT); 95 if (serr < 0) { 96 warn("retrieving user accounting summary"); 97 error = -1; 98 break; 99 } 100 } | 98/* Copy usrdb_file to in-memory usracct_db. */ 99int 100usracct_init() 101{ 102 BTREEINFO bti; |
101 | 103 |
102closeout: 103 if (DB_CLOSE(saved_usracct_db) < 0) { 104 warn("closing user accounting summary"); 105 error = -1; 106 } 107 } | 104 bzero(&bti, sizeof bti); 105 bti.compare = uid_compare; |
108 | 106 |
109out: 110 if (error != 0) 111 usracct_destroy(); 112 return (error); | 107 return (db_copy_in(&usracct_db, usrdb_file, "user accounting", 108 &bti, v1_to_v2)); |
113} 114 115void 116usracct_destroy() 117{ | 109} 110 111void 112usracct_destroy() 113{ |
118 if (DB_CLOSE(usracct_db) < 0) 119 warn("destroying user accounting stats"); | 114 db_destroy(usracct_db, "user accounting"); |
120} 121 122int 123usracct_add(const struct cmdinfo *ci) 124{ 125 DBT key, data; 126 struct userinfo newui; | 115} 116 117int 118usracct_add(const struct cmdinfo *ci) 119{ 120 DBT key, data; 121 struct userinfo newui; |
127 u_long uid; | 122 uid_t uid; |
128 int rv; 129 130 uid = ci->ci_uid; 131 key.data = &uid; 132 key.size = sizeof uid; 133 134 rv = DB_GET(usracct_db, &key, &data, 0); 135 if (rv < 0) { | 123 int rv; 124 125 uid = ci->ci_uid; 126 key.data = &uid; 127 key.size = sizeof uid; 128 129 rv = DB_GET(usracct_db, &key, &data, 0); 130 if (rv < 0) { |
136 warn("get key %lu from user accounting stats", uid); | 131 warn("get key %u from user accounting stats", uid); |
137 return (-1); 138 } else if (rv == 0) { /* it's there; copy whole thing */ 139 /* add the old data to the new data */ 140 bcopy(data.data, &newui, data.size); 141 if (newui.ui_uid != uid) { | 132 return (-1); 133 } else if (rv == 0) { /* it's there; copy whole thing */ 134 /* add the old data to the new data */ 135 bcopy(data.data, &newui, data.size); 136 if (newui.ui_uid != uid) { |
142 warnx("key %lu != expected record number %lu", | 137 warnx("key %u != expected record number %u", |
143 newui.ui_uid, uid); 144 warnx("inconsistent user accounting stats"); 145 return (-1); 146 } 147 } else { /* it's not there; zero it and copy the key */ 148 bzero(&newui, sizeof newui); 149 newui.ui_uid = ci->ci_uid; 150 } 151 152 newui.ui_calls += ci->ci_calls; 153 newui.ui_utime += ci->ci_utime; 154 newui.ui_stime += ci->ci_stime; 155 newui.ui_mem += ci->ci_mem; 156 newui.ui_io += ci->ci_io; 157 158 data.data = &newui; 159 data.size = sizeof newui; 160 rv = DB_PUT(usracct_db, &key, &data, 0); 161 if (rv < 0) { | 138 newui.ui_uid, uid); 139 warnx("inconsistent user accounting stats"); 140 return (-1); 141 } 142 } else { /* it's not there; zero it and copy the key */ 143 bzero(&newui, sizeof newui); 144 newui.ui_uid = ci->ci_uid; 145 } 146 147 newui.ui_calls += ci->ci_calls; 148 newui.ui_utime += ci->ci_utime; 149 newui.ui_stime += ci->ci_stime; 150 newui.ui_mem += ci->ci_mem; 151 newui.ui_io += ci->ci_io; 152 153 data.data = &newui; 154 data.size = sizeof newui; 155 rv = DB_PUT(usracct_db, &key, &data, 0); 156 if (rv < 0) { |
162 warn("add key %lu to user accounting stats", uid); | 157 warn("add key %u to user accounting stats", uid); |
163 return (-1); 164 } else if (rv != 0) { 165 warnx("DB_PUT returned 1"); 166 return (-1); 167 } 168 169 return (0); 170} 171 | 158 return (-1); 159 } else if (rv != 0) { 160 warnx("DB_PUT returned 1"); 161 return (-1); 162 } 163 164 return (0); 165} 166 |
167/* Copy in-memory usracct_db to usrdb_file. */ |
|
172int 173usracct_update() 174{ | 168int 169usracct_update() 170{ |
175 DB *saved_usracct_db; 176 DBT key, data; | |
177 BTREEINFO bti; | 171 BTREEINFO bti; |
178 int error, serr, nerr; | |
179 180 bzero(&bti, sizeof bti); 181 bti.compare = uid_compare; 182 | 172 173 bzero(&bti, sizeof bti); 174 bti.compare = uid_compare; 175 |
183 saved_usracct_db = dbopen(usrdb_file, O_RDWR|O_CREAT|O_TRUNC, 0644, 184 DB_BTREE, &bti); 185 if (saved_usracct_db == NULL) { 186 warn("creating user accounting summary"); 187 return (-1); 188 } 189 190 error = 0; 191 192 serr = DB_SEQ(usracct_db, &key, &data, R_FIRST); 193 if (serr < 0) { 194 warn("retrieving user accounting stats"); 195 error = -1; 196 } 197 while (serr == 0) { 198 nerr = DB_PUT(saved_usracct_db, &key, &data, 0); 199 if (nerr < 0) { 200 warn("saving user accounting summary"); 201 error = -1; 202 break; 203 } 204 205 serr = DB_SEQ(usracct_db, &key, &data, R_NEXT); 206 if (serr < 0) { 207 warn("retrieving user accounting stats"); 208 error = -1; 209 break; 210 } 211 } 212 213 if (DB_SYNC(saved_usracct_db, 0) < 0) { 214 warn("syncing process accounting summary"); 215 error = -1; 216 } 217 if (DB_CLOSE(saved_usracct_db) < 0) { 218 warn("closing process accounting summary"); 219 error = -1; 220 } 221 return error; | 176 return (db_copy_out(usracct_db, usrdb_file, "user accounting", 177 &bti)); |
222} 223 224void 225usracct_print() 226{ 227 DBT key, data; 228 struct userinfo uistore, *ui = &uistore; 229 double t; --- 4 unchanged lines hidden (view full) --- 234 warn("retrieving user accounting stats"); 235 236 while (rv == 0) { 237 memcpy(ui, data.data, sizeof(struct userinfo)); 238 239 printf("%-*s %9ju ", MAXLOGNAME - 1, 240 user_from_uid(ui->ui_uid, 0), (uintmax_t)ui->ui_calls); 241 | 178} 179 180void 181usracct_print() 182{ 183 DBT key, data; 184 struct userinfo uistore, *ui = &uistore; 185 double t; --- 4 unchanged lines hidden (view full) --- 190 warn("retrieving user accounting stats"); 191 192 while (rv == 0) { 193 memcpy(ui, data.data, sizeof(struct userinfo)); 194 195 printf("%-*s %9ju ", MAXLOGNAME - 1, 196 user_from_uid(ui->ui_uid, 0), (uintmax_t)ui->ui_calls); 197 |
242 t = (double) (ui->ui_utime + ui->ui_stime) / 243 (double) AHZ; 244 if (t < 0.0001) /* kill divide by zero */ 245 t = 0.0001; | 198 t = (ui->ui_utime + ui->ui_stime) / 1000000; 199 if (t < 0.000001) /* kill divide by zero */ 200 t = 0.000001; |
246 247 printf("%12.2f%s ", t / 60.0, "cpu"); 248 249 /* ui->ui_calls is always != 0 */ 250 if (dflag) | 201 202 printf("%12.2f%s ", t / 60.0, "cpu"); 203 204 /* ui->ui_calls is always != 0 */ 205 if (dflag) |
251 printf("%12ju%s", 252 (uintmax_t)(ui->ui_io / ui->ui_calls), "avio"); | 206 printf("%12.0f%s", 207 ui->ui_io / ui->ui_calls, "avio"); |
253 else | 208 else |
254 printf("%12ju%s", (uintmax_t)ui->ui_io, "tio"); | 209 printf("%12.0f%s", ui->ui_io, "tio"); |
255 | 210 |
256 /* t is always >= 0.0001; see above */ | 211 /* t is always >= 0.000001; see above. */ |
257 if (kflag) 258 printf("%12.0f%s", ui->ui_mem / t, "k"); 259 else | 212 if (kflag) 213 printf("%12.0f%s", ui->ui_mem / t, "k"); 214 else |
260 printf("%12ju%s", (uintmax_t)ui->ui_mem, "k*sec"); | 215 printf("%12.0f%s", ui->ui_mem, "k*sec"); |
261 262 printf("\n"); 263 264 rv = DB_SEQ(usracct_db, &key, &data, R_NEXT); 265 if (rv < 0) 266 warn("retrieving user accounting stats"); 267 } 268} 269 270static int 271uid_compare(const DBT *k1, const DBT *k2) 272{ | 216 217 printf("\n"); 218 219 rv = DB_SEQ(usracct_db, &key, &data, R_NEXT); 220 if (rv < 0) 221 warn("retrieving user accounting stats"); 222 } 223} 224 225static int 226uid_compare(const DBT *k1, const DBT *k2) 227{ |
273 u_long d1, d2; | 228 uid_t d1, d2; |
274 275 bcopy(k1->data, &d1, sizeof d1); 276 bcopy(k2->data, &d2, sizeof d2); 277 278 if (d1 < d2) 279 return -1; 280 else if (d1 == d2) 281 return 0; 282 else 283 return 1; 284} | 229 230 bcopy(k1->data, &d1, sizeof d1); 231 bcopy(k2->data, &d2, sizeof d2); 232 233 if (d1 < d2) 234 return -1; 235 else if (d1 == d2) 236 return 0; 237 else 238 return 1; 239} |