Mercurial > emacs
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 { |