1919package org .apache .paimon .table .source .snapshot ;
2020
2121import org .apache .paimon .CoreOptions ;
22- import org .apache .paimon .Snapshot ;
2322import org .apache .paimon .utils .ChangelogManager ;
24- import org .apache .paimon .utils .FunctionWithException ;
2523import org .apache .paimon .utils .SnapshotManager ;
2624
2725import org .slf4j .Logger ;
2826import org .slf4j .LoggerFactory ;
2927
30- import javax .annotation .Nullable ;
31-
32- import java .io .FileNotFoundException ;
33-
34- import static org .apache .paimon .utils .SnapshotManager .EARLIEST_SNAPSHOT_DEFAULT_RETRY_NUM ;
35-
3628/**
3729 * {@link StartingScanner} for the {@link CoreOptions.StartupMode#FROM_TIMESTAMP} startup mode of a
3830 * streaming read.
@@ -56,7 +48,7 @@ public ContinuousFromTimestampStartingScanner(
5648 this .startupMillis = startupMillis ;
5749 this .startFromChangelog = changelogDecoupled ;
5850 this .startingSnapshotId =
59- earlierThanTimeMills (
51+ TimeTravelUtil . earlierThanTimeMills (
6052 snapshotManager , changelogManager , startupMillis , startFromChangelog );
6153 }
6254
@@ -71,113 +63,15 @@ public StartingContext startingContext() {
7163
7264 @ Override
7365 public Result scan (SnapshotReader snapshotReader ) {
74- Long startingSnapshotId =
75- earlierThanTimeMills (
76- snapshotManager , changelogManager , startupMillis , startFromChangelog );
66+ if (startingSnapshotId == null ) {
67+ startingSnapshotId =
68+ TimeTravelUtil .earlierThanTimeMills (
69+ snapshotManager , changelogManager , startupMillis , startFromChangelog );
70+ }
7771 if (startingSnapshotId == null ) {
7872 LOG .debug ("There is currently no snapshot. Waiting for snapshot generation." );
7973 return new NoSnapshot ();
8074 }
8175 return new NextSnapshot (startingSnapshotId + 1 );
8276 }
83-
84- /**
85- * Returns the latest snapshot earlier than the timestamp mills. A non-existent snapshot may be
86- * returned if all snapshots are equal to or later than the timestamp mills.
87- */
88- public static @ Nullable Long earlierThanTimeMills (
89- SnapshotManager snapshotManager ,
90- ChangelogManager changelogManager ,
91- long timestampMills ,
92- boolean startFromChangelog ) {
93- Long latest = snapshotManager .latestSnapshotId ();
94- if (latest == null ) {
95- return null ;
96- }
97-
98- Snapshot earliestSnapshot =
99- earliestSnapshot (snapshotManager , changelogManager , startFromChangelog , latest );
100- if (earliestSnapshot == null ) {
101- return latest - 1 ;
102- }
103-
104- if (earliestSnapshot .timeMillis () >= timestampMills ) {
105- return earliestSnapshot .id () - 1 ;
106- }
107-
108- long earliest = earliestSnapshot .id ();
109- while (earliest < latest ) {
110- long mid = (earliest + latest + 1 ) / 2 ;
111- Snapshot snapshot =
112- startFromChangelog
113- ? changelogOrSnapshot (snapshotManager , changelogManager , mid )
114- : snapshotManager .snapshot (mid );
115- if (snapshot .timeMillis () < timestampMills ) {
116- earliest = mid ;
117- } else {
118- latest = mid - 1 ;
119- }
120- }
121- return earliest ;
122- }
123-
124- private static @ Nullable Snapshot earliestSnapshot (
125- SnapshotManager snapshotManager ,
126- ChangelogManager changelogManager ,
127- boolean includeChangelog ,
128- @ Nullable Long stopSnapshotId ) {
129- Long snapshotId = null ;
130- if (includeChangelog ) {
131- snapshotId = changelogManager .earliestLongLivedChangelogId ();
132- }
133- if (snapshotId == null ) {
134- snapshotId = snapshotManager .earliestSnapshotId ();
135- }
136- if (snapshotId == null ) {
137- return null ;
138- }
139-
140- if (stopSnapshotId == null ) {
141- stopSnapshotId = snapshotId + EARLIEST_SNAPSHOT_DEFAULT_RETRY_NUM ;
142- }
143-
144- FunctionWithException <Long , Snapshot , FileNotFoundException > snapshotFunction =
145- includeChangelog
146- ? s -> tryGetChangelogOrSnapshot (snapshotManager , changelogManager , s )
147- : snapshotManager ::tryGetSnapshot ;
148-
149- do {
150- try {
151- return snapshotFunction .apply (snapshotId );
152- } catch (FileNotFoundException e ) {
153- snapshotId ++;
154- if (snapshotId > stopSnapshotId ) {
155- return null ;
156- }
157- LOG .warn (
158- "The earliest snapshot or changelog was once identified but disappeared. "
159- + "It might have been expired by other jobs operating on this table. "
160- + "Searching for the second earliest snapshot or changelog instead. " );
161- }
162- } while (true );
163- }
164-
165- private static Snapshot tryGetChangelogOrSnapshot (
166- SnapshotManager snapshotManager , ChangelogManager changelogManager , long snapshotId )
167- throws FileNotFoundException {
168- if (changelogManager .longLivedChangelogExists (snapshotId )) {
169- return changelogManager .tryGetChangelog (snapshotId );
170- } else {
171- return snapshotManager .tryGetSnapshot (snapshotId );
172- }
173- }
174-
175- private static Snapshot changelogOrSnapshot (
176- SnapshotManager snapshotManager , ChangelogManager changelogManager , long snapshotId ) {
177- if (changelogManager .longLivedChangelogExists (snapshotId )) {
178- return changelogManager .changelog (snapshotId );
179- } else {
180- return snapshotManager .snapshot (snapshotId );
181- }
182- }
18377}
0 commit comments