DataStorage extends Storage { @VisibleForTesting synchronized List<StorageLocation> addStorageLocations(DataNode datanode, NamespaceInfo nsInfo, Collection<StorageLocation> dataDirs, StartupOption startOpt) throws IOException { final String bpid = nsInfo.getBlockPoolID(); List<StorageLocation> successVolumes = Lists.newArrayList(); for (StorageLocation dataDir : dataDirs) { File root = dataDir.getFile(); if (!containsStorageDir(root)) { try { StorageDirectory sd = loadStorageDirectory( datanode, nsInfo, root, startOpt); addStorageDir(sd); } catch (IOException e) { LOG.warn(e); continue; } } else { LOG.info("Storage directory " + dataDir + " has already been used."); } List<File> bpDataDirs = new ArrayList<File>(); bpDataDirs.add(BlockPoolSliceStorage.getBpRoot(bpid, new File(root, STORAGE_DIR_CURRENT))); try { makeBlockPoolDataDir(bpDataDirs, null); BlockPoolSliceStorage bpStorage = this.bpStorageMap.get(bpid); if (bpStorage == null) { bpStorage = new BlockPoolSliceStorage( nsInfo.getNamespaceID(), bpid, nsInfo.getCTime(), nsInfo.getClusterID()); } bpStorage.recoverTransitionRead(datanode, nsInfo, bpDataDirs, startOpt); addBlockPoolStorage(bpid, bpStorage); } catch (IOException e) { LOG.warn("Failed to add storage for block pool: " + bpid + " : " + e.getMessage()); continue; } successVolumes.add(dataDir); } return successVolumes; } DataStorage();  DataStorage(StorageInfo storageInfo); BlockPoolSliceStorage getBPStorage(String bpid); synchronized String getDatanodeUuid(); synchronized void setDatanodeUuid(String newDatanodeUuid); synchronized boolean createStorageID(
      StorageDirectory sd, boolean regenerateStorageIds); void enableTrash(String bpid); void restoreTrash(String bpid); boolean trashEnabled(String bpid); void setRollingUpgradeMarker(String bpid); void clearRollingUpgradeMarker(String bpid); String getTrashDirectoryForBlockFile(String bpid, File blockFile); VolumeBuilder prepareVolume(DataNode datanode, File volume,
      List<NamespaceInfo> nsInfos); @Override boolean isPreUpgradableLayout(StorageDirectory sd); final static String BLOCK_SUBDIR_PREFIX; final static String STORAGE_DIR_RBW; final static String STORAGE_DIR_FINALIZED; final static String STORAGE_DIR_TMP; }
@Test public void testAddStorageDirectories() throws IOException, URISyntaxException { final int numLocations = 3; final int numNamespace = 3; List<StorageLocation> locations = createStorageLocations(numLocations); List<NamespaceInfo> namespaceInfos = createNamespaceInfos(numNamespace); for (NamespaceInfo ni : namespaceInfos) { storage.addStorageLocations(mockDN, ni, locations, START_OPT); for (StorageLocation sl : locations) { checkDir(sl.getFile()); checkDir(sl.getFile(), ni.getBlockPoolID()); } } assertEquals(numLocations, storage.getNumStorageDirs()); locations = createStorageLocations(numLocations); List<StorageLocation> addedLocation = storage.addStorageLocations(mockDN, namespaceInfos.get(0), locations, START_OPT); assertTrue(addedLocation.isEmpty()); assertEquals(numLocations, storage.getNumStorageDirs()); locations = createStorageLocations(6); storage.addStorageLocations(mockDN, nsInfo, locations, START_OPT); assertEquals(6, storage.getNumStorageDirs()); }