1919import com .google .common .base .Optional ;
2020import org .apache .hadoop .hdds .conf .OzoneConfiguration ;
2121import org .apache .hadoop .hdds .protocol .StorageType ;
22+ import org .apache .hadoop .hdds .protocol .proto .HddsProtos ;
2223import org .apache .hadoop .hdds .utils .db .cache .CacheKey ;
2324import org .apache .hadoop .hdds .utils .db .cache .CacheValue ;
2425import org .apache .hadoop .ozone .om .helpers .OmBucketInfo ;
26+ import org .apache .hadoop .ozone .om .helpers .OmKeyInfo ;
2527import org .apache .hadoop .ozone .om .request .TestOMRequestUtils ;
2628import org .junit .Assert ;
2729import org .junit .Before ;
@@ -188,4 +190,228 @@ private void addBucketsToCache(String volumeName, String bucketName) {
188190 new CacheValue <>(Optional .of (omBucketInfo ), 1 ));
189191 }
190192
193+ @ Test
194+ public void testListKeys () throws Exception {
195+
196+ String volumeNameA = "volumeA" ;
197+ String volumeNameB = "volumeB" ;
198+ String ozoneBucket = "ozoneBucket" ;
199+ String hadoopBucket = "hadoopBucket" ;
200+
201+
202+ // Create volumes and buckets.
203+ TestOMRequestUtils .addVolumeToDB (volumeNameA , omMetadataManager );
204+ TestOMRequestUtils .addVolumeToDB (volumeNameB , omMetadataManager );
205+ addBucketsToCache (volumeNameA , ozoneBucket );
206+ addBucketsToCache (volumeNameB , hadoopBucket );
207+
208+
209+ String prefixKeyA = "key-a" ;
210+ String prefixKeyB = "key-b" ;
211+ TreeSet <String > keysASet = new TreeSet <>();
212+ TreeSet <String > keysBSet = new TreeSet <>();
213+ for (int i =1 ; i <= 100 ; i ++) {
214+ if (i % 2 == 0 ) {
215+ keysASet .add (
216+ prefixKeyA + i );
217+ addKeysToOM (volumeNameA , ozoneBucket , prefixKeyA + i , i );
218+ } else {
219+ keysBSet .add (
220+ prefixKeyB + i );
221+ addKeysToOM (volumeNameA , hadoopBucket , prefixKeyB + i , i );
222+ }
223+ }
224+
225+
226+ TreeSet <String > keysAVolumeBSet = new TreeSet <>();
227+ TreeSet <String > keysBVolumeBSet = new TreeSet <>();
228+ for (int i =1 ; i <= 100 ; i ++) {
229+ if (i % 2 == 0 ) {
230+ keysAVolumeBSet .add (
231+ prefixKeyA + i );
232+ addKeysToOM (volumeNameB , ozoneBucket , prefixKeyA + i , i );
233+ } else {
234+ keysBVolumeBSet .add (
235+ prefixKeyB + i );
236+ addKeysToOM (volumeNameB , hadoopBucket , prefixKeyB + i , i );
237+ }
238+ }
239+
240+
241+ // List all keys which have prefix "key-a"
242+ List <OmKeyInfo > omKeyInfoList =
243+ omMetadataManager .listKeys (volumeNameA , ozoneBucket ,
244+ null , prefixKeyA , 100 );
245+
246+ Assert .assertEquals (omKeyInfoList .size (), 50 );
247+
248+ for (OmKeyInfo omKeyInfo : omKeyInfoList ) {
249+ Assert .assertTrue (omKeyInfo .getKeyName ().startsWith (
250+ prefixKeyA ));
251+ }
252+
253+
254+ String startKey = prefixKeyA + 10 ;
255+ omKeyInfoList =
256+ omMetadataManager .listKeys (volumeNameA , ozoneBucket ,
257+ startKey , prefixKeyA , 100 );
258+
259+ Assert .assertEquals (keysASet .tailSet (
260+ startKey ).size () - 1 , omKeyInfoList .size ());
261+
262+ startKey = prefixKeyA + 38 ;
263+ omKeyInfoList =
264+ omMetadataManager .listKeys (volumeNameA , ozoneBucket ,
265+ startKey , prefixKeyA , 100 );
266+
267+ Assert .assertEquals (keysASet .tailSet (
268+ startKey ).size () - 1 , omKeyInfoList .size ());
269+
270+ for (OmKeyInfo omKeyInfo : omKeyInfoList ) {
271+ Assert .assertTrue (omKeyInfo .getKeyName ().startsWith (
272+ prefixKeyA ));
273+ Assert .assertFalse (omKeyInfo .getBucketName ().equals (
274+ prefixKeyA + 38 ));
275+ }
276+
277+
278+
279+ omKeyInfoList = omMetadataManager .listKeys (volumeNameB , hadoopBucket ,
280+ null , prefixKeyB , 100 );
281+
282+ Assert .assertEquals (omKeyInfoList .size (), 50 );
283+
284+ for (OmKeyInfo omKeyInfo : omKeyInfoList ) {
285+ Assert .assertTrue (omKeyInfo .getKeyName ().startsWith (
286+ prefixKeyB ));
287+ }
288+
289+ // Try to get keys by count 10, like that get all keys in the
290+ // volumeB/ozoneBucket with "key-a".
291+ startKey = null ;
292+ TreeSet <String > expectedKeys = new TreeSet <>();
293+ for (int i =0 ; i <5 ; i ++) {
294+
295+ omKeyInfoList = omMetadataManager .listKeys (volumeNameB , hadoopBucket ,
296+ startKey , prefixKeyB , 10 );
297+
298+ Assert .assertEquals (10 , omKeyInfoList .size ());
299+
300+ for (OmKeyInfo omKeyInfo : omKeyInfoList ) {
301+ expectedKeys .add (omKeyInfo .getKeyName ());
302+ Assert .assertTrue (omKeyInfo .getKeyName ().startsWith (
303+ prefixKeyB ));
304+ startKey = omKeyInfo .getKeyName ();
305+ }
306+ }
307+
308+ Assert .assertEquals (expectedKeys , keysBVolumeBSet );
309+
310+
311+ // As now we have iterated all 50 buckets, calling next time should
312+ // return empty list.
313+ omKeyInfoList = omMetadataManager .listKeys (volumeNameB , hadoopBucket ,
314+ startKey , prefixKeyB , 10 );
315+
316+ Assert .assertEquals (omKeyInfoList .size (), 0 );
317+
318+ }
319+
320+ @ Test
321+ public void testListKeysWithFewDeleteEntriesInCache () throws Exception {
322+ String volumeNameA = "volumeA" ;
323+ String ozoneBucket = "ozoneBucket" ;
324+
325+ // Create volumes and bucket.
326+ TestOMRequestUtils .addVolumeToDB (volumeNameA , omMetadataManager );
327+
328+ addBucketsToCache (volumeNameA , ozoneBucket );
329+
330+ String prefixKeyA = "key-a" ;
331+ TreeSet <String > keysASet = new TreeSet <>();
332+ TreeSet <String > deleteKeySet = new TreeSet <>();
333+
334+
335+ for (int i =1 ; i <= 100 ; i ++) {
336+ if (i % 2 == 0 ) {
337+ keysASet .add (
338+ prefixKeyA + i );
339+ addKeysToOM (volumeNameA , ozoneBucket , prefixKeyA + i , i );
340+ } else {
341+ addKeysToOM (volumeNameA , ozoneBucket , prefixKeyA + i , i );
342+ String key = omMetadataManager .getOzoneKey (volumeNameA ,
343+ ozoneBucket , prefixKeyA + i );
344+ // Mark as deleted in cache.
345+ omMetadataManager .getKeyTable ().addCacheEntry (
346+ new CacheKey <>(key ),
347+ new CacheValue <>(Optional .absent (), 100L ));
348+ deleteKeySet .add (key );
349+ }
350+ }
351+
352+ // Now list keys which match with prefixKeyA.
353+ List <OmKeyInfo > omKeyInfoList =
354+ omMetadataManager .listKeys (volumeNameA , ozoneBucket ,
355+ null , prefixKeyA , 100 );
356+
357+ // As in total 100, 50 are marked for delete. It should list only 50 keys.
358+ Assert .assertEquals (50 , omKeyInfoList .size ());
359+
360+ TreeSet <String > expectedKeys = new TreeSet <>();
361+
362+ for (OmKeyInfo omKeyInfo : omKeyInfoList ) {
363+ expectedKeys .add (omKeyInfo .getKeyName ());
364+ Assert .assertTrue (omKeyInfo .getKeyName ().startsWith (prefixKeyA ));
365+ }
366+
367+ Assert .assertEquals (expectedKeys , keysASet );
368+
369+
370+ // Now get key count by 10.
371+ String startKey = null ;
372+ expectedKeys = new TreeSet <>();
373+ for (int i =0 ; i <5 ; i ++) {
374+
375+ omKeyInfoList = omMetadataManager .listKeys (volumeNameA , ozoneBucket ,
376+ startKey , prefixKeyA , 10 );
377+
378+ System .out .println (i );
379+ Assert .assertEquals (10 , omKeyInfoList .size ());
380+
381+ for (OmKeyInfo omKeyInfo : omKeyInfoList ) {
382+ expectedKeys .add (omKeyInfo .getKeyName ());
383+ Assert .assertTrue (omKeyInfo .getKeyName ().startsWith (
384+ prefixKeyA ));
385+ startKey = omKeyInfo .getKeyName ();
386+ }
387+ }
388+
389+ Assert .assertEquals (keysASet , expectedKeys );
390+
391+
392+ // As now we have iterated all 50 buckets, calling next time should
393+ // return empty list.
394+ omKeyInfoList = omMetadataManager .listKeys (volumeNameA , ozoneBucket ,
395+ startKey , prefixKeyA , 10 );
396+
397+ Assert .assertEquals (omKeyInfoList .size (), 0 );
398+
399+
400+
401+ }
402+
403+ private void addKeysToOM (String volumeName , String bucketName ,
404+ String keyName , int i ) throws Exception {
405+
406+ if (i %2 == 0 ) {
407+ TestOMRequestUtils .addKeyToTable (false , volumeName , bucketName , keyName ,
408+ 1000L , HddsProtos .ReplicationType .RATIS ,
409+ HddsProtos .ReplicationFactor .ONE , omMetadataManager );
410+ } else {
411+ TestOMRequestUtils .addKeyToTableCache (volumeName , bucketName , keyName ,
412+ HddsProtos .ReplicationType .RATIS , HddsProtos .ReplicationFactor .ONE ,
413+ omMetadataManager );
414+ }
415+ }
416+
191417}
0 commit comments