@@ -67,6 +67,8 @@ class TieredStorageTest : public BaseFamilyTest {
6767TEST_F (TieredStorageTest, SimpleGetSet) {
6868 absl::FlagSaver saver;
6969 SetFlag (&FLAGS_tiered_offload_threshold, 0 .0f ); // disable offloading
70+ UpdateFromFlags ();
71+
7072 const int kMin = 256 ;
7173 const int kMax = tiering::kPageSize + 10 ;
7274
@@ -122,16 +124,58 @@ TEST_F(TieredStorageTest, MGET) {
122124 EXPECT_EQ (elements[i], values[i]);
123125}
124126
125- TEST_F (TieredStorageTest, SimpleAppend) {
126- // TODO: use pipelines to issue APPEND/GET/APPEND sequence,
127- // currently it's covered only for op_manager_test
128- for (size_t sleep : {0 , 100 , 500 , 1000 }) {
129- Run ({" SET" , " k0" , BuildString (3000 )});
130- if (sleep)
131- util::ThisFiber::SleepFor (sleep * 1us);
132- EXPECT_THAT (Run ({" APPEND" , " k0" , " B" }), IntArg (3001 ));
133- ASSERT_EQ (Run ({" GET" , " k0" }), BuildString (3000 ) + ' B' ) << sleep;
127+ // Issue many APPEND commands to an offloaded value that are executed at once (with CLIENT PAUSE).
128+ // They should all finish within the same io completion loop.
129+ TEST_F (TieredStorageTest, AppendStorm) {
130+ const size_t kAppends = 20 ;
131+
132+ absl::FlagSaver saver;
133+ absl::SetFlag (&FLAGS_tiered_offload_threshold, 1.0 );
134+ absl::SetFlag (&FLAGS_tiered_upload_threshold, 0.0 );
135+ absl::SetFlag (&FLAGS_tiered_experimental_cooling, false );
136+ UpdateFromFlags ();
137+
138+ // Offload single value
139+ string base_value (4096 , ' a' );
140+ Run ({" SET" , " key" , base_value});
141+ ExpectConditionWithinTimeout ([this ] { return GetMetrics ().tiered_stats .total_stashes == 1 ; });
142+
143+ // Accumulate APPENDs
144+ Run ({" CLIENT" , " pause" , " 1000" });
145+ vector<Fiber> fibs;
146+ for (size_t i = 0 ; i < kAppends ; i++) {
147+ fibs.emplace_back (pp_->at (0 )->LaunchFiber ([this , i] {
148+ Run (absl::StrCat (i), {" APPEND" , " key" , string (96 , ' b' )});
149+ }));
134150 }
151+
152+ // Throw in a SETRANGE
153+ fibs.emplace_back (pp_->at (0 )->LaunchFiber ([this ] {
154+ Run (" range" , {" SETRANGE" , " key" , " 0" , string (96 , ' x' )});
155+ }));
156+
157+ // Throw in a GETRANGE to a range that keeps constant
158+ string get_range;
159+ fibs.emplace_back (pp_->at (0 )->LaunchFiber ([this , &get_range] {
160+ get_range = Run (" get" , {" GETRANGE" , " key" , " 96" , " 191" }).GetString ();
161+ }));
162+
163+ // Unlock and wait
164+ Run ({" CLIENT" , " unpause" });
165+ for (auto & f : fibs)
166+ f.JoinIfNeeded ();
167+
168+ // Check partial result is right
169+ EXPECT_EQ (get_range, string (96 , ' a' ));
170+
171+ // Get value and verify it
172+ auto value = Run ({" GET" , " key" });
173+ EXPECT_EQ (value, string (96 , ' x' ) + string (4000 , ' a' ) + string (kAppends * 96 , ' b' ));
174+
175+ // Check value was read no more than once for APPENDs and once for GET
176+ auto metrics = GetMetrics ();
177+ EXPECT_LE (metrics.tiered_stats .total_fetches , 2u );
178+ EXPECT_LE (metrics.tiered_stats .total_uploads , 2u );
135179}
136180
137181TEST_F (TieredStorageTest, Ranges) {
@@ -207,6 +251,7 @@ TEST_F(TieredStorageTest, Defrag) {
207251TEST_F (TieredStorageTest, BackgroundOffloading) {
208252 absl::FlagSaver saver;
209253 SetFlag (&FLAGS_tiered_offload_threshold, 1 .0f ); // offload all values
254+ SetFlag (&FLAGS_tiered_upload_threshold, 0 .0f ); // upload all values
210255 SetFlag (&FLAGS_tiered_experimental_cooling, false ); // The setup works without cooling buffers
211256 UpdateFromFlags ();
212257
@@ -247,7 +292,6 @@ TEST_F(TieredStorageTest, BackgroundOffloading) {
247292 // should be re-stashed again.
248293 EXPECT_EQ (metrics.tiered_stats .total_stashes , kNum + metrics.tiered_stats .total_uploads )
249294 << resp.GetString ();
250- EXPECT_EQ (metrics.tiered_stats .total_fetches , kNum * 2 );
251295 EXPECT_EQ (metrics.tiered_stats .allocated_bytes , kNum * 4096 );
252296}
253297
0 commit comments