Skip to content

Commit 502274f

Browse files
sachinpkaleSachin Kale
authored andcommitted
Change pinned timestamp file format stored in remote store (opensearch-project#15526)
--------- Signed-off-by: Sachin Kale <[email protected]> Co-authored-by: Sachin Kale <[email protected]>
1 parent 1778020 commit 502274f

File tree

8 files changed

+233
-508
lines changed

8 files changed

+233
-508
lines changed

server/src/internalClusterTest/java/org/opensearch/remotestore/RemoteStorePinnedTimestampsIT.java

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
package org.opensearch.remotestore;
1010

11+
import org.opensearch.action.LatchedActionListener;
1112
import org.opensearch.common.collect.Tuple;
1213
import org.opensearch.common.settings.Settings;
1314
import org.opensearch.common.unit.TimeValue;
@@ -17,6 +18,7 @@
1718
import org.opensearch.test.OpenSearchIntegTestCase;
1819

1920
import java.util.Set;
21+
import java.util.concurrent.CountDownLatch;
2022

2123
@OpenSearchIntegTestCase.ClusterScope(scope = OpenSearchIntegTestCase.Scope.TEST, numDataNodes = 0)
2224
public class RemoteStorePinnedTimestampsIT extends RemoteStoreBaseIntegTestCase {
@@ -75,10 +77,25 @@ public void testTimestampPinUnpin() throws Exception {
7577

7678
remoteStorePinnedTimestampService.rescheduleAsyncUpdatePinnedTimestampTask(TimeValue.timeValueMinutes(3));
7779

78-
// This should be a no-op as pinning entity is different
79-
remoteStorePinnedTimestampService.unpinTimestamp(timestamp1, "no-snapshot", noOpActionListener);
8080
// Unpinning already pinned entity
8181
remoteStorePinnedTimestampService.unpinTimestamp(timestamp2, "ss3", noOpActionListener);
82+
83+
// This should fail as timestamp is not pinned by pinning entity
84+
CountDownLatch latch = new CountDownLatch(1);
85+
remoteStorePinnedTimestampService.unpinTimestamp(timestamp1, "no-snapshot", new LatchedActionListener<>(new ActionListener<Void>() {
86+
@Override
87+
public void onResponse(Void unused) {
88+
// onResponse should not get called.
89+
fail();
90+
}
91+
92+
@Override
93+
public void onFailure(Exception e) {
94+
assertTrue(e instanceof IllegalArgumentException);
95+
}
96+
}, latch));
97+
latch.await();
98+
8299
// Adding different entity to already pinned timestamp
83100
remoteStorePinnedTimestampService.pinTimestamp(timestamp3, "ss5", noOpActionListener);
84101

@@ -93,4 +110,74 @@ public void testTimestampPinUnpin() throws Exception {
93110

94111
remoteStorePinnedTimestampService.rescheduleAsyncUpdatePinnedTimestampTask(TimeValue.timeValueMinutes(3));
95112
}
113+
114+
public void testPinnedTimestampClone() throws Exception {
115+
prepareCluster(1, 1, INDEX_NAME, 0, 2);
116+
ensureGreen(INDEX_NAME);
117+
118+
RemoteStorePinnedTimestampService remoteStorePinnedTimestampService = internalCluster().getInstance(
119+
RemoteStorePinnedTimestampService.class,
120+
primaryNodeName(INDEX_NAME)
121+
);
122+
123+
long timestamp1 = System.currentTimeMillis() + 30000L;
124+
long timestamp2 = System.currentTimeMillis() + 60000L;
125+
long timestamp3 = System.currentTimeMillis() + 900000L;
126+
remoteStorePinnedTimestampService.pinTimestamp(timestamp1, "ss2", noOpActionListener);
127+
remoteStorePinnedTimestampService.pinTimestamp(timestamp2, "ss3", noOpActionListener);
128+
remoteStorePinnedTimestampService.pinTimestamp(timestamp3, "ss4", noOpActionListener);
129+
130+
// Clone timestamp1
131+
remoteStorePinnedTimestampService.cloneTimestamp(timestamp1, "ss2", "ss2-2", noOpActionListener);
132+
133+
// With clone, set of pinned timestamp will not change
134+
remoteStorePinnedTimestampService.rescheduleAsyncUpdatePinnedTimestampTask(TimeValue.timeValueSeconds(1));
135+
assertBusy(
136+
() -> assertEquals(Set.of(timestamp1, timestamp2, timestamp3), RemoteStorePinnedTimestampService.getPinnedTimestamps().v2())
137+
);
138+
remoteStorePinnedTimestampService.rescheduleAsyncUpdatePinnedTimestampTask(TimeValue.timeValueMinutes(3));
139+
140+
// Clone timestamp1 but provide invalid existing entity
141+
CountDownLatch latch = new CountDownLatch(1);
142+
remoteStorePinnedTimestampService.cloneTimestamp(
143+
timestamp1,
144+
"ss3",
145+
"ss2-3",
146+
new LatchedActionListener<>(new ActionListener<Void>() {
147+
@Override
148+
public void onResponse(Void unused) {
149+
// onResponse should not get called.
150+
fail();
151+
}
152+
153+
@Override
154+
public void onFailure(Exception e) {
155+
assertTrue(e instanceof IllegalArgumentException);
156+
}
157+
}, latch)
158+
);
159+
latch.await();
160+
161+
remoteStorePinnedTimestampService.rescheduleAsyncUpdatePinnedTimestampTask(TimeValue.timeValueSeconds(1));
162+
assertBusy(
163+
() -> assertEquals(Set.of(timestamp1, timestamp2, timestamp3), RemoteStorePinnedTimestampService.getPinnedTimestamps().v2())
164+
);
165+
remoteStorePinnedTimestampService.rescheduleAsyncUpdatePinnedTimestampTask(TimeValue.timeValueMinutes(3));
166+
167+
// Now we have timestamp1 pinned by 2 entities, unpin 1, this should not change set of pinned timestamps
168+
remoteStorePinnedTimestampService.unpinTimestamp(timestamp1, "ss2", noOpActionListener);
169+
170+
remoteStorePinnedTimestampService.rescheduleAsyncUpdatePinnedTimestampTask(TimeValue.timeValueSeconds(1));
171+
assertBusy(
172+
() -> assertEquals(Set.of(timestamp1, timestamp2, timestamp3), RemoteStorePinnedTimestampService.getPinnedTimestamps().v2())
173+
);
174+
remoteStorePinnedTimestampService.rescheduleAsyncUpdatePinnedTimestampTask(TimeValue.timeValueMinutes(3));
175+
176+
// Now unpin second entity as well, set of pinned timestamp should be reduced by 1
177+
remoteStorePinnedTimestampService.unpinTimestamp(timestamp1, "ss2-2", noOpActionListener);
178+
179+
remoteStorePinnedTimestampService.rescheduleAsyncUpdatePinnedTimestampTask(TimeValue.timeValueSeconds(1));
180+
assertBusy(() -> assertEquals(Set.of(timestamp2, timestamp3), RemoteStorePinnedTimestampService.getPinnedTimestamps().v2()));
181+
remoteStorePinnedTimestampService.rescheduleAsyncUpdatePinnedTimestampTask(TimeValue.timeValueMinutes(3));
182+
}
96183
}

server/src/main/java/org/opensearch/gateway/remote/model/RemotePinnedTimestamps.java

Lines changed: 0 additions & 144 deletions
This file was deleted.

server/src/main/java/org/opensearch/gateway/remote/model/RemoteStorePinnedTimestampsBlobStore.java

Lines changed: 0 additions & 43 deletions
This file was deleted.

server/src/main/java/org/opensearch/index/remote/RemoteStoreUtils.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,8 +542,11 @@ public static List<String> filterOutMetadataFilesBasedOnAge(
542542
if (RemoteStoreSettings.isPinnedTimestampsEnabled() == false) {
543543
return new ArrayList<>(metadataFiles);
544544
}
545-
long maximumAllowedTimestamp = lastSuccessfulFetchOfPinnedTimestamps - RemoteStoreSettings.getPinnedTimestampsLookbackInterval()
546-
.getMillis();
545+
// We allow now() - loopback interval to be pinned. Also, the actual pinning can take at most loopback interval
546+
// This means the pinned timestamp can be available for read after at most (2 * loopback interval)
547+
long maximumAllowedTimestamp = lastSuccessfulFetchOfPinnedTimestamps - (2 * RemoteStoreSettings
548+
.getPinnedTimestampsLookbackInterval()
549+
.getMillis());
547550
List<String> metadataFilesWithMinAge = new ArrayList<>();
548551
for (String metadataFileName : metadataFiles) {
549552
long metadataTimestamp = getTimestampFunction.apply(metadataFileName);

0 commit comments

Comments
 (0)