comparison src/filelock.c @ 24744:0e99bc70cf07

Fix performance bug on hosts with large /var/adm/wtmp files with no boot records. (boot_time_initialized): New var. (init_filelock): Initialize it. (get_boot_time): Use it, instead of nonzero boot_time, to test whether boot_time is initialized. Don't invoke utmp routines when dumping. (get_boot_time): First, try to get the boot time from the current utmp file, as this can be much faster. Don't try to get the boot time from utmp and/or wtmp more than once. (get_boot_time_1): When passed null pointer, don't invoke utmpname. New arg LATEST. All uses changed.
author Richard M. Stallman <rms@gnu.org>
date Wed, 19 May 1999 01:30:15 +0000
parents c5be96c5a5c1
children a7eb312629b4
comparison
equal deleted inserted replaced
24743:003fb3ca1618 24744:0e99bc70cf07
1 /* Copyright (C) 1985, 86, 87, 93, 94, 96 Free Software Foundation, Inc. 1 /* Lock files for editing.
2 Copyright (C) 1985, 86, 87, 93, 94, 96, 98, 1999 Free Software Foundation, Inc.
2 3
3 This file is part of GNU Emacs. 4 This file is part of GNU Emacs.
4 5
5 GNU Emacs is free software; you can redistribute it and/or modify 6 GNU Emacs is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by 7 it under the terms of the GNU General Public License as published by
102 103
103 104
104 /* Return the time of the last system boot. */ 105 /* Return the time of the last system boot. */
105 106
106 static time_t boot_time; 107 static time_t boot_time;
108 static int boot_time_initialized;
107 109
108 extern Lisp_Object Vshell_file_name; 110 extern Lisp_Object Vshell_file_name;
109 111
110 static time_t 112 static time_t
111 get_boot_time () 113 get_boot_time ()
113 struct utmp ut, *utp; 115 struct utmp ut, *utp;
114 int fd; 116 int fd;
115 EMACS_TIME time_before, after; 117 EMACS_TIME time_before, after;
116 int counter; 118 int counter;
117 119
118 if (boot_time) 120 if (boot_time_initialized)
119 return boot_time; 121 return boot_time;
122 boot_time_initialized = 1;
120 123
121 EMACS_GET_TIME (time_before); 124 EMACS_GET_TIME (time_before);
122 125
123 /* Try calculating the last boot time 126 /* Try calculating the last boot time
124 from the uptime as obtained from /proc/uptime. */ 127 from the uptime as obtained from /proc/uptime. */
164 } 167 }
165 } 168 }
166 #endif /* defined (CTL_KERN) && defined (KERN_BOOTTIME) */ 169 #endif /* defined (CTL_KERN) && defined (KERN_BOOTTIME) */
167 170
168 #if defined (BOOT_TIME) && ! defined (NO_WTMP_FILE) 171 #if defined (BOOT_TIME) && ! defined (NO_WTMP_FILE)
172 #ifndef CANNOT_DUMP
173 /* The utmp routines maintain static state.
174 Don't touch that state unless we are initialized,
175 since it might not survive dumping. */
176 if (! initialized)
177 return boot_time;
178 #endif /* not CANNOT_DUMP */
179
180 /* Try to get boot time from utmp before wtmp,
181 since utmp is typically much smaller than wtmp.
182 Passing a null pointer causes get_boot_time_1
183 to inspect the default file, namely utmp. */
184 get_boot_time_1 ((char *) 0, 0);
185 if (boot_time)
186 return boot_time;
187
169 /* Try to get boot time from the current wtmp file. */ 188 /* Try to get boot time from the current wtmp file. */
170 get_boot_time_1 (WTMP_FILE); 189 get_boot_time_1 (WTMP_FILE, 1);
171 190
172 /* If we did not find a boot time in wtmp, look at wtmp, and so on. */ 191 /* If we did not find a boot time in wtmp, look at wtmp, and so on. */
173 for (counter = 0; counter < 20 && boot_time == 1; counter++) 192 for (counter = 0; counter < 20 && ! boot_time; counter++)
174 { 193 {
175 char cmd_string[100]; 194 char cmd_string[100];
176 Lisp_Object tempname, filename; 195 Lisp_Object tempname, filename;
177 int delete_flag = 0; 196 int delete_flag = 0;
178 197
204 } 223 }
205 } 224 }
206 225
207 if (! NILP (filename)) 226 if (! NILP (filename))
208 { 227 {
209 get_boot_time_1 (XSTRING (filename)->data); 228 get_boot_time_1 (XSTRING (filename)->data, 1);
210 if (delete_flag) 229 if (delete_flag)
211 unlink (XSTRING (filename)->data); 230 unlink (XSTRING (filename)->data);
212 } 231 }
213 } 232 }
214 233
219 } 238 }
220 239
221 #ifdef BOOT_TIME 240 #ifdef BOOT_TIME
222 /* Try to get the boot time from wtmp file FILENAME. 241 /* Try to get the boot time from wtmp file FILENAME.
223 This succeeds if that file contains a reboot record. 242 This succeeds if that file contains a reboot record.
224 Success is indicated by setting BOOT_TIME. */ 243
225 244 If FILENAME is zero, use the same file as before;
226 get_boot_time_1 (filename) 245 if no FILENAME has ever been specified, this is the utmp file.
246 Use the newest reboot record if NEWEST is nonzero,
247 the first reboot record otherwise.
248 Ignore all reboot records on or before BOOT_TIME.
249 Success is indicated by setting BOOT_TIME to a larger value. */
250
251 get_boot_time_1 (filename, newest)
227 char *filename; 252 char *filename;
253 int newest;
228 { 254 {
229 struct utmp ut, *utp; 255 struct utmp ut, *utp;
230 int desc; 256 int desc;
231 257
232 /* On some versions of IRIX, opening a nonexistent file name 258 if (filename)
233 is likely to crash in the utmp routines. */ 259 {
234 desc = open (filename, O_RDONLY); 260 /* On some versions of IRIX, opening a nonexistent file name
235 if (desc < 0) 261 is likely to crash in the utmp routines. */
236 return; 262 desc = open (filename, O_RDONLY);
237 263 if (desc < 0)
238 close (desc); 264 return;
239 265
240 utmpname (filename); 266 close (desc);
267
268 utmpname (filename);
269 }
270
241 setutent (); 271 setutent ();
272
242 while (1) 273 while (1)
243 { 274 {
244 /* Find the next reboot record. */ 275 /* Find the next reboot record. */
245 ut.ut_type = BOOT_TIME; 276 ut.ut_type = BOOT_TIME;
246 utp = getutid (&ut); 277 utp = getutid (&ut);
247 if (! utp) 278 if (! utp)
248 break; 279 break;
249 /* Compare reboot times and use the newest one. */ 280 /* Compare reboot times and use the newest one. */
250 if (utp->ut_time > boot_time) 281 if (utp->ut_time > boot_time)
251 boot_time = utp->ut_time; 282 {
283 boot_time = utp->ut_time;
284 if (! newest)
285 break;
286 }
252 /* Advance on element in the file 287 /* Advance on element in the file
253 so that getutid won't repeat the same one. */ 288 so that getutid won't repeat the same one. */
254 utp = getutent (); 289 utp = getutent ();
255 if (! utp) 290 if (! utp)
256 break; 291 break;
682 717
683 void 718 void
684 init_filelock () 719 init_filelock ()
685 { 720 {
686 boot_time = 0; 721 boot_time = 0;
722 boot_time_initialized = 0;
687 } 723 }
688 724
689 void 725 void
690 syms_of_filelock () 726 syms_of_filelock ()
691 { 727 {