11
11
* Portions Copyright (c) 1994, Regents of the University of California
12
12
*
13
13
* IDENTIFICATION
14
- * $PostgreSQL: pgsql/src/backend/storage/ipc/standby.c,v 1.20 2010/04/28 16 :10:42 heikki Exp $
14
+ * $PostgreSQL: pgsql/src/backend/storage/ipc/standby.c,v 1.21 2010/05/02 02 :10:33 tgl Exp $
15
15
*
16
16
*-------------------------------------------------------------------------
17
17
*/
@@ -124,31 +124,24 @@ static int standbyWait_us = STANDBY_INITIAL_WAIT_US;
124
124
static bool
125
125
WaitExceedsMaxStandbyDelay (void )
126
126
{
127
- long delay_secs ;
128
- int delay_usecs ;
129
-
130
- if (MaxStandbyDelay == -1 )
131
- return false;
132
-
133
127
/* Are we past max_standby_delay? */
134
- TimestampDifference ( GetLatestXLogTime (), GetCurrentTimestamp (),
135
- & delay_secs , & delay_usecs );
136
- if ( delay_secs > MaxStandbyDelay )
128
+ if ( MaxStandbyDelay >= 0 &&
129
+ TimestampDifferenceExceeds ( GetLatestXLogTime (), GetCurrentTimestamp (),
130
+ MaxStandbyDelay ) )
137
131
return true;
138
132
139
133
/*
140
- * Sleep, then do bookkeeping .
134
+ * Sleep a bit (this is essential to avoid busy-waiting) .
141
135
*/
142
136
pg_usleep (standbyWait_us );
143
137
144
138
/*
145
- * Progressively increase the sleep times.
139
+ * Progressively increase the sleep times, but not to more than 1s,
140
+ * since pg_usleep isn't interruptable on some platforms.
146
141
*/
147
142
standbyWait_us *= 2 ;
148
143
if (standbyWait_us > 1000000 )
149
144
standbyWait_us = 1000000 ;
150
- if (standbyWait_us > MaxStandbyDelay * 1000000 / 4 )
151
- standbyWait_us = MaxStandbyDelay * 1000000 / 4 ;
152
145
153
146
return false;
154
147
}
@@ -163,50 +156,41 @@ static void
163
156
ResolveRecoveryConflictWithVirtualXIDs (VirtualTransactionId * waitlist ,
164
157
ProcSignalReason reason )
165
158
{
166
- char waitactivitymsg [100 ];
167
- char oldactivitymsg [101 ];
168
-
169
159
while (VirtualTransactionIdIsValid (* waitlist ))
170
160
{
171
- long wait_s ;
172
- int wait_us ; /* wait in microseconds (us) */
173
161
TimestampTz waitStart ;
174
- bool logged ;
162
+ char * new_status ;
163
+
164
+ pgstat_report_waiting (true);
175
165
176
166
waitStart = GetCurrentTimestamp ();
167
+ new_status = NULL ; /* we haven't changed the ps display */
168
+
169
+ /* reset standbyWait_us for each xact we wait for */
177
170
standbyWait_us = STANDBY_INITIAL_WAIT_US ;
178
- logged = false;
179
171
180
172
/* wait until the virtual xid is gone */
181
173
while (!ConditionalVirtualXactLockTableWait (* waitlist ))
182
174
{
183
175
/*
184
- * Report if we have been waiting for a while now...
176
+ * Report via ps if we have been waiting for more than 500 msec
177
+ * (should that be configurable?)
185
178
*/
186
- TimestampTz now = GetCurrentTimestamp ();
187
-
188
- TimestampDifference (waitStart , now , & wait_s , & wait_us );
189
- if (!logged && (wait_s > 0 || wait_us > 500000 ))
179
+ if (update_process_title && new_status == NULL &&
180
+ TimestampDifferenceExceeds (waitStart , GetCurrentTimestamp (),
181
+ 500 ))
190
182
{
191
- const char * oldactivitymsgp ;
183
+ const char * old_status ;
192
184
int len ;
193
185
194
- oldactivitymsgp = get_ps_display (& len );
195
-
196
- if (len > 100 )
197
- len = 100 ;
198
-
199
- memcpy (oldactivitymsg , oldactivitymsgp , len );
200
- oldactivitymsg [len ] = 0 ;
201
-
202
- snprintf (waitactivitymsg , sizeof (waitactivitymsg ),
203
- "waiting for max_standby_delay (%u s)" ,
186
+ old_status = get_ps_display (& len );
187
+ new_status = (char * ) palloc (len + 50 );
188
+ memcpy (new_status , old_status , len );
189
+ snprintf (new_status + len , 50 ,
190
+ " waiting for max_standby_delay (%d ms)" ,
204
191
MaxStandbyDelay );
205
- set_ps_display (waitactivitymsg , false);
206
-
207
- pgstat_report_waiting (true);
208
-
209
- logged = true;
192
+ set_ps_display (new_status , false);
193
+ new_status [len ] = '\0' ; /* truncate off " waiting" */
210
194
}
211
195
212
196
/* Is it time to kill it? */
@@ -225,16 +209,17 @@ ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist,
225
209
* unresponsive backend when system is heavily loaded.
226
210
*/
227
211
if (pid != 0 )
228
- pg_usleep (5000 );
212
+ pg_usleep (5000L );
229
213
}
230
214
}
231
215
232
- /* Reset ps display */
233
- if (logged )
216
+ /* Reset ps display if we changed it */
217
+ if (new_status )
234
218
{
235
- set_ps_display (oldactivitymsg , false);
236
- pgstat_report_waiting (false );
219
+ set_ps_display (new_status , false);
220
+ pfree ( new_status );
237
221
}
222
+ pgstat_report_waiting (false);
238
223
239
224
/* The virtual transaction is gone now, wait for the next one */
240
225
waitlist ++ ;
@@ -401,7 +386,7 @@ ResolveRecoveryConflictWithBufferPin(void)
401
386
*/
402
387
SendRecoveryConflictWithBufferPin (PROCSIG_RECOVERY_CONFLICT_BUFFERPIN );
403
388
}
404
- else if (MaxStandbyDelay == -1 )
389
+ else if (MaxStandbyDelay < 0 )
405
390
{
406
391
/*
407
392
* Send out a request to check for buffer pin deadlocks before we
@@ -412,17 +397,11 @@ ResolveRecoveryConflictWithBufferPin(void)
412
397
}
413
398
else
414
399
{
415
- TimestampTz now ;
416
- long standby_delay_secs ; /* How far Startup process is lagging */
417
- int standby_delay_usecs ;
418
-
419
- now = GetCurrentTimestamp ();
400
+ TimestampTz then = GetLatestXLogTime ();
401
+ TimestampTz now = GetCurrentTimestamp ();
420
402
421
403
/* Are we past max_standby_delay? */
422
- TimestampDifference (GetLatestXLogTime (), now ,
423
- & standby_delay_secs , & standby_delay_usecs );
424
-
425
- if (standby_delay_secs >= MaxStandbyDelay )
404
+ if (TimestampDifferenceExceeds (then , now , MaxStandbyDelay ))
426
405
{
427
406
/*
428
407
* We're already behind, so clear a path as quickly as possible.
@@ -434,7 +413,7 @@ ResolveRecoveryConflictWithBufferPin(void)
434
413
TimestampTz fin_time ; /* Expected wake-up time by timer */
435
414
long timer_delay_secs ; /* Amount of time we set timer
436
415
* for */
437
- int timer_delay_usecs = 0 ;
416
+ int timer_delay_usecs ;
438
417
439
418
/*
440
419
* Send out a request to check for buffer pin deadlocks before we
@@ -446,12 +425,10 @@ ResolveRecoveryConflictWithBufferPin(void)
446
425
/*
447
426
* How much longer we should wait?
448
427
*/
449
- timer_delay_secs = MaxStandbyDelay - standby_delay_secs ;
450
- if (standby_delay_usecs > 0 )
451
- {
452
- timer_delay_secs -= 1 ;
453
- timer_delay_usecs = 1000000 - standby_delay_usecs ;
454
- }
428
+ fin_time = TimestampTzPlusMilliseconds (then , MaxStandbyDelay );
429
+
430
+ TimestampDifference (now , fin_time ,
431
+ & timer_delay_secs , & timer_delay_usecs );
455
432
456
433
/*
457
434
* It's possible that the difference is less than a microsecond;
@@ -460,13 +437,6 @@ ResolveRecoveryConflictWithBufferPin(void)
460
437
if (timer_delay_secs == 0 && timer_delay_usecs == 0 )
461
438
timer_delay_usecs = 1 ;
462
439
463
- /*
464
- * When is the finish time? We recheck this if we are woken early.
465
- */
466
- fin_time = TimestampTzPlusMilliseconds (now ,
467
- (timer_delay_secs * 1000 ) +
468
- (timer_delay_usecs / 1000 ));
469
-
470
440
if (enable_standby_sig_alarm (timer_delay_secs , timer_delay_usecs , fin_time ))
471
441
sig_alarm_enabled = true;
472
442
else
0 commit comments