Browse code

journald/read: simplify walking backwards

In case Tail=N parameter is requested, we need to show N lines.
It does not make sense to walk backwards one by one if we can
do it at once. Now, if Since=T is also provided, make sure we
haven't jumped too far (before T), and if we did, move forward.

The primary motivation for this was to make the code simpler.

This also fixes a tiny bug in the "since" implementation.

Before this commit:
> $ docker logs -t --tail=6000 --since="2019-03-10T03:54:25.00" $ID | head
> 2019-03-10T03:54:24.999821000Z 95981

After:
> $ docker logs -t --tail=6000 --since="2019-03-10T03:54:25.00" $ID | head
> 2019-03-10T03:54:25.000013000Z 95982

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit ff3cd167ea4d089b7695a263ba2fc4caa0a0750c)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>

Kir Kolyshkin authored on 2019/03/10 12:49:06
Showing 1 changed files
... ...
@@ -361,7 +361,6 @@ func (s *journald) readLogs(logWatcher *logger.LogWatcher, config logger.ReadCon
361 361
 		untilUnixMicro = uint64(nano / 1000)
362 362
 	}
363 363
 	if config.Tail > 0 {
364
-		lines := config.Tail
365 364
 		// If until time provided, start from there.
366 365
 		// Otherwise start at the end of the journal.
367 366
 		if untilUnixMicro != 0 && C.sd_journal_seek_realtime_usec(j, C.uint64_t(untilUnixMicro)) < 0 {
... ...
@@ -371,29 +370,13 @@ func (s *journald) readLogs(logWatcher *logger.LogWatcher, config logger.ReadCon
371 371
 			logWatcher.Err <- fmt.Errorf("error seeking to end of journal")
372 372
 			return
373 373
 		}
374
-		if C.sd_journal_previous(j) < 0 {
375
-			logWatcher.Err <- fmt.Errorf("error backtracking to previous journal entry")
376
-			return
377
-		}
378
-		// Walk backward.
379
-		for lines > 0 {
380
-			// Stop if the entry time is before our cutoff.
381
-			// We'll need the entry time if it isn't, so go
382
-			// ahead and parse it now.
383
-			if C.sd_journal_get_realtime_usec(j, &stamp) != 0 {
384
-				break
385
-			} else {
386
-				// Compare the timestamp on the entry to our threshold value.
387
-				if sinceUnixMicro != 0 && sinceUnixMicro > uint64(stamp) {
388
-					break
389
-				}
390
-			}
391
-			lines--
392
-			// If we're at the start of the journal, or
393
-			// don't need to back up past any more entries,
394
-			// stop.
395
-			if lines == 0 || C.sd_journal_previous(j) <= 0 {
396
-				break
374
+		// (Try to) skip backwards by the requested number of lines...
375
+		if C.sd_journal_previous_skip(j, C.uint64_t(config.Tail)) > 0 {
376
+			// ...but not before "since"
377
+			if sinceUnixMicro != 0 &&
378
+				C.sd_journal_get_realtime_usec(j, &stamp) == 0 &&
379
+				uint64(stamp) < sinceUnixMicro {
380
+				C.sd_journal_seek_realtime_usec(j, C.uint64_t(sinceUnixMicro))
397 381
 			}
398 382
 		}
399 383
 	} else {