3939import  org .apache .hadoop .hbase .util .HFileArchiveUtil ;
4040import  org .apache .hadoop .hbase .util .MockServer ;
4141import  org .apache .hadoop .hbase .zookeeper .ZKWatcher ;
42+ import  org .junit .After ;
4243import  org .junit .AfterClass ;
44+ import  org .junit .Before ;
4345import  org .junit .BeforeClass ;
4446import  org .junit .ClassRule ;
4547import  org .junit .Rule ;
@@ -57,9 +59,28 @@ public class TestHFileLinkCleaner {
5759  public  static  final  HBaseClassTestRule  CLASS_RULE  =
5860    HBaseClassTestRule .forClass (TestHFileLinkCleaner .class );
5961
62+   private  Configuration  conf ;
63+   private  Path  rootDir ;
64+   private  FileSystem  fs ;
65+   private  TableName  tableName ;
66+   private  TableName  tableLinkName ;
67+   private  String  hfileName ;
68+   private  String  familyName ;
69+   private  RegionInfo  hri ;
70+   private  RegionInfo  hriLink ;
71+   private  Path  archiveDir ;
72+   private  Path  archiveStoreDir ;
73+   private  Path  familyPath ;
74+   private  Path  hfilePath ;
75+   private  Path  familyLinkPath ;
76+   private  String  hfileLinkName ;
77+   private  Path  linkBackRefDir ;
78+   private  Path  linkBackRef ;
79+   private  FileStatus [] backRefs ;
80+   private  HFileCleaner  cleaner ;
6081  private  final  static  HBaseTestingUtil  TEST_UTIL  = new  HBaseTestingUtil ();
61- 
6282  private  static  DirScanPool  POOL ;
83+   private  static  final  long  TTL  = 1000 ;
6384
6485  @ Rule 
6586  public  TestName  name  = new  TestName ();
@@ -74,49 +95,71 @@ public static void tearDown() {
7495    POOL .shutdownNow ();
7596  }
7697
77-   @ Test 
78-   public  void  testHFileLinkCleaning () throws  Exception  {
79-     Configuration   conf  = TEST_UTIL .getConfiguration ();
98+   @ Before 
99+   public  void  configureDirectoriesAndLinks () throws  IOException  {
100+     conf  = TEST_UTIL .getConfiguration ();
80101    CommonFSUtils .setRootDir (conf , TEST_UTIL .getDataTestDir ());
81102    conf .set (HFileCleaner .MASTER_HFILE_CLEANER_PLUGINS , HFileLinkCleaner .class .getName ());
82-     Path   rootDir  = CommonFSUtils .getRootDir (conf );
83-     FileSystem   fs  = FileSystem .get (conf );
103+     rootDir  = CommonFSUtils .getRootDir (conf );
104+     fs  = FileSystem .get (conf );
84105
85-     final   TableName   tableName  = TableName .valueOf (name .getMethodName ());
86-     final   TableName   tableLinkName  = TableName .valueOf (name .getMethodName () + "-link" );
87-     final   String   hfileName  = "1234567890" ;
88-     final   String   familyName  = "cf" ;
106+     tableName  = TableName .valueOf (name .getMethodName ());
107+     tableLinkName  = TableName .valueOf (name .getMethodName () + "-link" );
108+     hfileName  = "1234567890" ;
109+     familyName  = "cf" ;
89110
90-     RegionInfo   hri  = RegionInfoBuilder .newBuilder (tableName ).build ();
91-     RegionInfo   hriLink  = RegionInfoBuilder .newBuilder (tableLinkName ).build ();
111+     hri  = RegionInfoBuilder .newBuilder (tableName ).build ();
112+     hriLink  = RegionInfoBuilder .newBuilder (tableLinkName ).build ();
92113
93-     Path   archiveDir  = HFileArchiveUtil .getArchivePath (conf );
94-     Path   archiveStoreDir  =
114+     archiveDir  = HFileArchiveUtil .getArchivePath (conf );
115+     archiveStoreDir  =
95116      HFileArchiveUtil .getStoreArchivePath (conf , tableName , hri .getEncodedName (), familyName );
96117
97118    // Create hfile /hbase/table-link/region/cf/getEncodedName.HFILE(conf); 
98-     Path   familyPath  = getFamilyDirPath (archiveDir , tableName , hri .getEncodedName (), familyName );
119+     familyPath  = getFamilyDirPath (archiveDir , tableName , hri .getEncodedName (), familyName );
99120    fs .mkdirs (familyPath );
100-     Path   hfilePath  = new  Path (familyPath , hfileName );
121+     hfilePath  = new  Path (familyPath , hfileName );
101122    fs .createNewFile (hfilePath );
102123
124+     createLink (true );
125+ 
126+     // Initialize cleaner 
127+     conf .setLong (TimeToLiveHFileCleaner .TTL_CONF_KEY , TTL );
128+     Server  server  = new  DummyServer ();
129+     cleaner  = new  HFileCleaner (1000 , server , conf , fs , archiveDir , POOL );
130+   }
131+ 
132+   private  void  createLink (boolean  createBackReference ) throws  IOException  {
103133    // Create link to hfile 
104-     Path  familyLinkPath  =
105-       getFamilyDirPath (rootDir , tableLinkName , hriLink .getEncodedName (), familyName );
134+     familyLinkPath  = getFamilyDirPath (rootDir , tableLinkName , hriLink .getEncodedName (), familyName );
106135    fs .mkdirs (familyLinkPath );
107-     HFileLink .create (conf , fs , familyLinkPath , hri , hfileName );
108-     Path   linkBackRefDir  = HFileLink .getBackReferencesDir (archiveStoreDir , hfileName );
136+     hfileLinkName  =  HFileLink .create (conf , fs , familyLinkPath , hri , hfileName ,  createBackReference );
137+     linkBackRefDir  = HFileLink .getBackReferencesDir (archiveStoreDir , hfileName );
109138    assertTrue (fs .exists (linkBackRefDir ));
110-     FileStatus []  backRefs  = fs .listStatus (linkBackRefDir );
139+     backRefs  = fs .listStatus (linkBackRefDir );
111140    assertEquals (1 , backRefs .length );
112-     Path  linkBackRef  = backRefs [0 ].getPath ();
141+     linkBackRef  = backRefs [0 ].getPath ();
142+   }
113143
114-     // Initialize cleaner 
115-     final  long  ttl  = 1000 ;
116-     conf .setLong (TimeToLiveHFileCleaner .TTL_CONF_KEY , ttl );
117-     Server  server  = new  DummyServer ();
118-     HFileCleaner  cleaner  = new  HFileCleaner (1000 , server , conf , fs , archiveDir , POOL );
144+   @ After 
145+   public  void  cleanup () throws  IOException , InterruptedException  {
146+     // HFile can be removed 
147+     Thread .sleep (TTL  * 2 );
148+     cleaner .chore ();
149+     assertFalse ("HFile should be deleted" , fs .exists (hfilePath ));
150+     // Remove everything 
151+     for  (int  i  = 0 ; i  < 4 ; ++i ) {
152+       Thread .sleep (TTL  * 2 );
153+       cleaner .chore ();
154+     }
155+     assertFalse ("HFile should be deleted" ,
156+       fs .exists (CommonFSUtils .getTableDir (archiveDir , tableName )));
157+     assertFalse ("Link should be deleted" ,
158+       fs .exists (CommonFSUtils .getTableDir (archiveDir , tableLinkName )));
159+   }
119160
161+   @ Test 
162+   public  void  testHFileLinkCleaning () throws  Exception  {
120163    // Link backref cannot be removed 
121164    cleaner .chore ();
122165    assertTrue (fs .exists (linkBackRef ));
@@ -127,21 +170,28 @@ public void testHFileLinkCleaning() throws Exception {
127170      CommonFSUtils .getTableDir (archiveDir , tableLinkName ));
128171    cleaner .chore ();
129172    assertFalse ("Link should be deleted" , fs .exists (linkBackRef ));
173+   }
130174
131-     // HFile can be removed 
132-     Thread .sleep (ttl  * 2 );
175+   @ Test 
176+   public  void  testHFileLinkByRemovingReference () throws  Exception  {
177+     // Link backref cannot be removed 
133178    cleaner .chore ();
134-     assertFalse ("HFile should be deleted" , fs .exists (hfilePath ));
179+     assertTrue (fs .exists (linkBackRef ));
180+     assertTrue (fs .exists (hfilePath ));
135181
136-     // Remove everything 
137-     for  (int  i  = 0 ; i  < 4 ; ++i ) {
138-       Thread .sleep (ttl  * 2 );
139-       cleaner .chore ();
140-     }
141-     assertFalse ("HFile should be deleted" ,
142-       fs .exists (CommonFSUtils .getTableDir (archiveDir , tableName )));
143-     assertFalse ("Link should be deleted" ,
144-       fs .exists (CommonFSUtils .getTableDir (archiveDir , tableLinkName )));
182+     // simulate after removing the reference in data directory, the Link backref can be removed 
183+     fs .delete (new  Path (familyLinkPath , hfileLinkName ), false );
184+     cleaner .chore ();
185+     assertFalse ("Link should be deleted" , fs .exists (linkBackRef ));
186+   }
187+ 
188+   @ Test 
189+   public  void  testHFileLinkEmptyBackReferenceDirectory () throws  Exception  {
190+     // simulate and remove the back reference 
191+     fs .delete (linkBackRef , false );
192+     assertTrue ("back reference directory still exists" , fs .exists (linkBackRefDir ));
193+     cleaner .chore ();
194+     assertFalse ("back reference directory should be deleted" , fs .exists (linkBackRefDir ));
145195  }
146196
147197  private  static  Path  getFamilyDirPath (final  Path  rootDir , final  TableName  table ,
0 commit comments