/* * Read ClusterID, StorageID, StorageType, CTime from * DataStorage VERSION file and verify them. */ @Override protected void setFieldsFromProperties(Properties props, StorageDirectory sd) throws IOException { setLayoutVersion(props, sd); setcTime(props, sd); setStorageType(props, sd); setClusterId(props, layoutVersion, sd); // Read NamespaceID in version before federation if (!LayoutVersion.supports(Feature.FEDERATION, layoutVersion)) { setNamespaceID(props, sd); } // valid storage id, storage id may be empty String ssid = props.getProperty("storageID"); if (ssid == null) { throw new InconsistentFSStateException( sd.getRoot(), "file " + STORAGE_FILE_VERSION + " is invalid."); } String sid = getStorageID(); if (!(sid.equals("") || ssid.equals("") || sid.equals(ssid))) { throw new InconsistentFSStateException(sd.getRoot(), "has incompatible storage Id."); } if (sid.equals("")) { // update id only if it was empty setStorageID(ssid); } }
private StorageDirectory loadStorageDirectory( DataNode datanode, NamespaceInfo nsInfo, File dataDir, StartupOption startOpt) throws IOException { StorageDirectory sd = new StorageDirectory(dataDir, null, false); try { StorageState curState = sd.analyzeStorage(startOpt, this); switch (curState) { case NORMAL: break; case NON_EXISTENT: LOG.info("Storage directory " + dataDir + " does not exist"); throw new IOException("Storage directory " + dataDir + " does not exist"); case NOT_FORMATTED: // format LOG.info( "Storage directory " + dataDir + " is not formatted for " + nsInfo.getBlockPoolID()); LOG.info("Formatting ..."); format(sd, nsInfo, datanode.getDatanodeUuid()); break; default: throw new RuntimeException("未实现"); } doTransition(datanode, sd, nsInfo, startOpt); writeProperties(sd); return sd; } catch (IOException ioe) { sd.unlock(); throw ioe; } }
/** Delete all files and directories in the trash directories. */ public void clearTrash() { for (StorageDirectory sd : storageDirs) { File trashRoot = getTrashRootDir(sd); Preconditions.checkState(!(trashRoot.exists() && sd.getPreviousDir().exists())); FileUtil.fullyDelete(trashRoot); LOG.info("Cleared trash for storage directory " + sd); } }
/** * Analize which and whether a transition of the fs state is required and perform it if necessary. * * <p>Rollback if previousLV >= LAYOUT_VERSION && prevCTime <= namenode.cTime Upgrade if this.LV > * LAYOUT_VERSION || this.cTime < namenode.cTime Regular startup if this.LV = LAYOUT_VERSION && * this.cTime = namenode.cTime * * @param datanode Datanode to which this storage belongs to * @param sd storage directory * @param nsInfo namespace info * @param startOpt startup option * @throws IOException */ private void doTransition( DataNode datanode, StorageDirectory sd, NamespaceInfo nsInfo, StartupOption startOpt) throws IOException { if (startOpt == StartupOption.ROLLBACK) { doRollback(sd, nsInfo); // rollback if applicable } readProperties(sd); checkVersionUpgradable(this.layoutVersion); assert this.layoutVersion >= HdfsConstants.LAYOUT_VERSION : "Future version is not allowed"; boolean federationSupported = LayoutVersion.supports(Feature.FEDERATION, layoutVersion); // For pre-federation version - validate the namespaceID if (!federationSupported && getNamespaceID() != nsInfo.getNamespaceID()) { throw new IOException( "Incompatible namespaceIDs in " + sd.getRoot().getCanonicalPath() + ": namenode namespaceID = " + nsInfo.getNamespaceID() + "; datanode namespaceID = " + getNamespaceID()); } // For version that supports federation, validate clusterID if (federationSupported && !getClusterID().equals(nsInfo.getClusterID())) { throw new IOException( "Incompatible clusterIDs in " + sd.getRoot().getCanonicalPath() + ": namenode clusterID = " + nsInfo.getClusterID() + "; datanode clusterID = " + getClusterID()); } // regular start up if (this.layoutVersion == HdfsConstants.LAYOUT_VERSION && this.cTime == nsInfo.getCTime()) return; // regular startup // verify necessity of a distributed upgrade UpgradeManagerDatanode um = datanode.getUpgradeManagerDatanode(nsInfo.getBlockPoolID()); verifyDistributedUpgradeProgress(um, nsInfo); // do upgrade if (this.layoutVersion > HdfsConstants.LAYOUT_VERSION || this.cTime < nsInfo.getCTime()) { doUpgrade(sd, nsInfo); // upgrade return; } // layoutVersion == LAYOUT_VERSION && this.cTime > nsInfo.cTime // must shutdown throw new IOException( "Datanode state: LV = " + this.getLayoutVersion() + " CTime = " + this.getCTime() + " is newer than the namespace state: LV = " + nsInfo.getLayoutVersion() + " CTime = " + nsInfo.getCTime()); }
private void format(StorageDirectory bpSdir, NamespaceInfo nsInfo) throws IOException { LOG.info("Formatting block pool " + blockpoolID + " directory " + bpSdir.getCurrentDir()); bpSdir.clearDirectory(); // create directory this.layoutVersion = HdfsConstants.DATANODE_LAYOUT_VERSION; this.cTime = nsInfo.getCTime(); this.namespaceID = nsInfo.getNamespaceID(); this.blockpoolID = nsInfo.getBlockPoolID(); writeProperties(bpSdir); }
void endCheckpoint() throws IOException { for (StorageDirectory sd : storageDirs) { File tmpCkptDir = sd.getLastCheckpointTmp(); File prevCkptDir = sd.getPreviousCheckpoint(); // delete previous dir if (prevCkptDir.exists()) deleteDir(prevCkptDir); // rename tmp to previous if (tmpCkptDir.exists()) rename(tmpCkptDir, prevCkptDir); } }
void finalizeUpgrade(String bpID) throws IOException { for (StorageDirectory sd : storageDirs) { File prevDir = sd.getPreviousDir(); if (prevDir.exists()) { throw new RuntimeException("未实现"); } else { BlockPoolSliceStorage bpStorage = bpStorageMap.get(bpID); bpStorage.doFinalize(sd.getCurrentDir()); } } }
/** * Remove block pool level storage directory. * * @param absPathToRemove the absolute path of the root for the block pool level storage to * remove. */ void remove(File absPathToRemove) { Preconditions.checkArgument(absPathToRemove.isAbsolute()); LOG.info("Removing block level storage: " + absPathToRemove); for (Iterator<StorageDirectory> it = this.storageDirs.iterator(); it.hasNext(); ) { StorageDirectory sd = it.next(); if (sd.getRoot().getAbsoluteFile().equals(absPathToRemove)) { it.remove(); break; } } }
/** * Prepare directories for a new checkpoint. * * <p>Rename <code>current</code> to <code>lastcheckpoint.tmp</code> and recreate <code>current * </code>. * * @throws IOException */ void startCheckpoint() throws IOException { for (StorageDirectory sd : storageDirs) { File curDir = sd.getCurrentDir(); File tmpCkptDir = sd.getLastCheckpointTmp(); assert !tmpCkptDir.exists() : tmpCkptDir.getName() + " directory must not exist."; if (curDir.exists()) { // rename current to tmp rename(curDir, tmpCkptDir); } if (!curDir.mkdir()) throw new IOException("Cannot create directory " + curDir); } }
public void clearRollingUpgradeMarkers(List<StorageDirectory> dnStorageDirs) throws IOException { for (StorageDirectory sd : dnStorageDirs) { File bpRoot = getBpRoot(blockpoolID, sd.getCurrentDir()); File markerFile = new File(bpRoot, ROLLING_UPGRADE_MARKER_FILE); if (!storagesWithoutRollingUpgradeMarker.contains(bpRoot.toString())) { if (markerFile.exists()) { throw new RuntimeException("未实现"); } storagesWithoutRollingUpgradeMarker.add(bpRoot.toString()); storagesWithRollingUpgradeMarker.remove(bpRoot.toString()); } } }
void format(StorageDirectory sd, NamespaceInfo nsInfo, String datanodeUuid) throws IOException { sd.clearDirectory(); this.layoutVersion = HdfsConstants.DATANODE_LAYOUT_VERSION; this.clusterID = nsInfo.getClusterID(); this.namespaceID = nsInfo.getNamespaceID(); this.cTime = 0; setDatanodeUuid(datanodeUuid); if (sd.getStorageUuid() == null) { // 分配新的 Storage UUID. sd.setStorageUuid(DatanodeStorage.generateUuid()); } writeProperties(sd); }
/** * Create a rolling upgrade marker file for each BP storage root, if it does not exist already. */ public void setRollingUpgradeMarkers(List<StorageDirectory> dnStorageDirs) throws IOException { for (StorageDirectory sd : dnStorageDirs) { File bpRoot = getBpRoot(blockpoolID, sd.getCurrentDir()); File markerFile = new File(bpRoot, ROLLING_UPGRADE_MARKER_FILE); if (!storagesWithRollingUpgradeMarker.contains(bpRoot.toString())) { if (!markerFile.exists() && markerFile.createNewFile()) { LOG.info("Created " + markerFile); } else { LOG.info(markerFile + " already exists."); } storagesWithRollingUpgradeMarker.add(bpRoot.toString()); storagesWithoutRollingUpgradeMarker.remove(bpRoot.toString()); } } }
/** * 鏄惁鍥犵┖闂翠笉瓒虫嫆鍐� * * @param fileType 璇锋眰鍐欐搷浣滅殑鏂囦欢绫诲瀷 * @return 杩斿洖婊¤冻鍐欐潯浠剁殑鏈�紭鐩綍锛涘鏋滆繑鍥瀗ull琛ㄧず娌℃湁鐩綍婊¤冻鏉′欢 */ private StorageDirectory limitSpaceUnwrite(int fileType, int type) { List<StorageDirectory> directories = getDirectorysByPriority(fileType); for (StorageDirectory directory : directories) { // 濡傛灉鍙鏌ュ缃瓨鍌ㄥ崱鍒欒繃婊や笅 if (type == 1 && directory.type != DIRECTORY_EXTERNAL_SDCARD) { continue; } long residualSpace = getResidualSpace(directory.rootDirectory); if (getFileMaxSize(fileType) <= residualSpace) { directory.residualSpace = residualSpace; return directory; } } return null; }
public synchronized boolean createStorageID(StorageDirectory sd, boolean regenerateStorageIds) { final String oldStorageID = sd.getStorageUuid(); if (oldStorageID == null || regenerateStorageIds) { sd.setStorageUuid(DatanodeStorage.generateUuid()); LOG.info( "Generated new storageID " + sd.getStorageUuid() + " for directory " + sd.getRoot() + (oldStorageID == null ? "" : (" to replace " + oldStorageID))); return true; } return false; }
/* * Finalize the upgrade for a block pool */ void finalizeUpgrade(String bpID) throws IOException { // To handle finalizing a snapshot taken at datanode level while // upgrading to federation, if datanode level snapshot previous exists, // then finalize it. Else finalize the corresponding BP. for (StorageDirectory sd : storageDirs) { File prevDir = sd.getPreviousDir(); if (prevDir.exists()) { // data node level storage finalize doFinalize(sd); } else { // block pool storage finalize using specific bpID BlockPoolSliceStorage bpStorage = bpStorageMap.get(bpID); bpStorage.doFinalize(sd.getCurrentDir()); } } }
/** * Check whether the rolling upgrade marker file exists for each BP storage root. If it does * exist, then the marker file is cleared and more importantly the layout upgrade is finalized. */ public void clearRollingUpgradeMarkers(List<StorageDirectory> dnStorageDirs) throws IOException { for (StorageDirectory sd : dnStorageDirs) { File bpRoot = getBpRoot(blockpoolID, sd.getCurrentDir()); File markerFile = new File(bpRoot, ROLLING_UPGRADE_MARKER_FILE); if (!storagesWithoutRollingUpgradeMarker.contains(bpRoot.toString())) { if (markerFile.exists()) { LOG.info("Deleting " + markerFile); doFinalize(sd.getCurrentDir()); if (!markerFile.delete()) { LOG.warn("Failed to delete " + markerFile); } } storagesWithoutRollingUpgradeMarker.add(bpRoot.toString()); storagesWithRollingUpgradeMarker.remove(bpRoot.toString()); } } }
@Override protected void setFieldsFromProperties(Properties props, StorageDirectory sd) throws IOException { setLayoutVersion(props, sd); setNamespaceID(props, sd); setcTime(props, sd); String sbpid = props.getProperty("blockpoolID"); setBlockPoolID(sd.getRoot(), sbpid); }
/** * Upgrade to any release after 0.22 (0.22 included) release e.g. 0.22 => 0.23 Upgrade procedure * is as follows: * * <ol> * <li>If <SD>/current/<bpid>/previous exists then delete it * <li>Rename <SD>/current/<bpid>/current to <SD>/current/bpid/current/previous.tmp * <li>Create new <SD>current/<bpid>/current directory * <ol> * <li>Hard links for block files are created from previous.tmp to current * <li>Save new version file in current directory * </ol> * <li>Rename previous.tmp to previous * </ol> * * @param bpSd storage directory <SD>/current/<bpid> * @param nsInfo Namespace Info from the namenode * @throws IOException on error */ void doUpgrade(DataNode datanode, StorageDirectory bpSd, NamespaceInfo nsInfo) throws IOException { // Upgrading is applicable only to release with federation or after if (!DataNodeLayoutVersion.supports(LayoutVersion.Feature.FEDERATION, layoutVersion)) { return; } LOG.info( "Upgrading block pool storage directory " + bpSd.getRoot() + ".\n old LV = " + this.getLayoutVersion() + "; old CTime = " + this.getCTime() + ".\n new LV = " + HdfsConstants.DATANODE_LAYOUT_VERSION + "; new CTime = " + nsInfo.getCTime()); // get <SD>/previous directory String dnRoot = getDataNodeStorageRoot(bpSd.getRoot().getCanonicalPath()); StorageDirectory dnSdStorage = new StorageDirectory(new File(dnRoot)); File dnPrevDir = dnSdStorage.getPreviousDir(); // If <SD>/previous directory exists delete it if (dnPrevDir.exists()) { deleteDir(dnPrevDir); } File bpCurDir = bpSd.getCurrentDir(); File bpPrevDir = bpSd.getPreviousDir(); assert bpCurDir.exists() : "BP level current directory must exist."; cleanupDetachDir(new File(bpCurDir, DataStorage.STORAGE_DIR_DETACHED)); // 1. Delete <SD>/current/<bpid>/previous dir before upgrading if (bpPrevDir.exists()) { deleteDir(bpPrevDir); } File bpTmpDir = bpSd.getPreviousTmp(); assert !bpTmpDir.exists() : "previous.tmp directory must not exist."; // 2. Rename <SD>/current/<bpid>/current to // <SD>/current/<bpid>/previous.tmp rename(bpCurDir, bpTmpDir); // 3. Create new <SD>/current with block files hardlinks and VERSION linkAllBlocks(datanode, bpTmpDir, bpCurDir); this.layoutVersion = HdfsConstants.DATANODE_LAYOUT_VERSION; assert this.namespaceID == nsInfo.getNamespaceID() : "Data-node and name-node layout versions must be the same."; this.cTime = nsInfo.getCTime(); writeProperties(bpSd); // 4.rename <SD>/current/<bpid>/previous.tmp to // <SD>/current/<bpid>/previous rename(bpTmpDir, bpPrevDir); LOG.info("Upgrade of block pool " + blockpoolID + " at " + bpSd.getRoot() + " is complete"); }
/** * Load one storage directory. Recover from previous transitions if required. * * @param datanode datanode instance * @param nsInfo namespace information * @param dataDir the root path of the storage directory * @param startOpt startup option * @return the StorageDirectory successfully loaded. * @throws IOException */ private StorageDirectory loadStorageDirectory( DataNode datanode, NamespaceInfo nsInfo, File dataDir, StartupOption startOpt) throws IOException { StorageDirectory sd = new StorageDirectory(dataDir, null, true); try { StorageState curState = sd.analyzeStorage(startOpt, this); // sd is locked but not opened switch (curState) { case NORMAL: break; case NON_EXISTENT: LOG.info("Block pool storage directory " + dataDir + " does not exist"); throw new IOException("Storage directory " + dataDir + " does not exist"); case NOT_FORMATTED: // format LOG.info( "Block pool storage directory " + dataDir + " is not formatted for " + nsInfo.getBlockPoolID()); LOG.info("Formatting ..."); format(sd, nsInfo); break; default: // recovery part is common sd.doRecover(curState); } // 2. Do transitions // Each storage directory is treated individually. // During startup some of them can upgrade or roll back // while others could be up-to-date for the regular startup. doTransition(datanode, sd, nsInfo, startOpt); if (getCTime() != nsInfo.getCTime()) { throw new IOException("Data-node and name-node CTimes must be the same."); } // 3. Update successfully loaded storage. setServiceLayoutVersion(getServiceLayoutVersion()); writeProperties(sd); return sd; } catch (IOException ioe) { sd.unlock(); throw ioe; } }
void doFinalize(File dnCurDir) throws IOException { File bpRoot = getBpRoot(blockpoolID, dnCurDir); StorageDirectory bpSd = new StorageDirectory(bpRoot); File prevDir = bpSd.getPreviousDir(); if (!prevDir.exists()) { return; // already finalized } final String dataDirPath = bpSd.getRoot().getCanonicalPath(); LOG.info( "Finalizing upgrade for storage directory " + dataDirPath + ".\n cur LV = " + this.getLayoutVersion() + "; cur CTime = " + this.getCTime()); assert bpSd.getCurrentDir().exists() : "Current directory must exist."; throw new RuntimeException("未实现"); }
void format(StorageDirectory sd, NamespaceInfo nsInfo) throws IOException { sd.clearDirectory(); // create directory this.layoutVersion = HdfsConstants.LAYOUT_VERSION; this.clusterID = nsInfo.getClusterID(); this.namespaceID = nsInfo.getNamespaceID(); this.cTime = 0; // store storageID as it currently is writeProperties(sd); }
private void doTransition( DataNode datanode, StorageDirectory sd, NamespaceInfo nsInfo, StartupOption startOpt) throws IOException { if (startOpt == StartupOption.ROLLBACK) { throw new RuntimeException("未实现"); } readProperties(sd); checkVersionUpgradable(this.layoutVersion); // 版本号为负数,越小越高,文件里面的layoutVersion必须比hadoop版本大或者等于 assert this.layoutVersion >= HdfsConstants.DATANODE_LAYOUT_VERSION : "不允许将来的版本"; boolean federationSupported = DataNodeLayoutVersion.supports(LayoutVersion.Feature.FEDERATION, layoutVersion); if (!federationSupported && getNamespaceID() != nsInfo.getNamespaceID()) { throw new IOException( "Incompatible namespaceIDs in " + sd.getRoot().getCanonicalPath() + ": namenode namespaceID = " + nsInfo.getNamespaceID() + "; datanode namespaceID = " + getNamespaceID()); } if (federationSupported && !getClusterID().equals(nsInfo.getClusterID())) { throw new IOException( "Incompatible clusterIDs in " + sd.getRoot().getCanonicalPath() + ": namenode clusterID = " + nsInfo.getClusterID() + "; datanode clusterID = " + getClusterID()); } boolean haveValidStorageId = DataNodeLayoutVersion.supports( LayoutVersion.Feature.ADD_DATANODE_AND_STORAGE_UUIDS, layoutVersion) && DatanodeStorage.isValidStorageId(sd.getStorageUuid()); if (this.layoutVersion == HdfsConstants.DATANODE_LAYOUT_VERSION) { createStorageID(sd, !haveValidStorageId); return; } throw new IOException( "BUG: The stored LV = " + this.getLayoutVersion() + " is newer than the supported LV = " + HdfsConstants.DATANODE_LAYOUT_VERSION); }
/** * Finalize procedure deletes an existing snapshot. * * <ol> * <li>Rename previous to finalized.tmp directory * <li>Fully delete the finalized.tmp directory * </ol> * * Do nothing, if previous directory does not exist */ void doFinalize(StorageDirectory sd) throws IOException { File prevDir = sd.getPreviousDir(); if (!prevDir.exists()) return; // already discarded final String dataDirPath = sd.getRoot().getCanonicalPath(); LOG.info( "Finalizing upgrade for storage directory " + dataDirPath + ".\n cur LV = " + this.getLayoutVersion() + "; cur CTime = " + this.getCTime()); assert sd.getCurrentDir().exists() : "Current directory must exist."; final File tmpDir = sd.getFinalizedTmp(); // finalized.tmp directory final File bbwDir = new File(sd.getRoot(), Storage.STORAGE_1_BBW); // 1. rename previous to finalized.tmp rename(prevDir, tmpDir); // 2. delete finalized.tmp dir in a separate thread // Also delete the blocksBeingWritten from HDFS 1.x and earlier, if // it exists. new Daemon( new Runnable() { @Override public void run() { try { deleteDir(tmpDir); if (bbwDir.exists()) { deleteDir(bbwDir); } } catch (IOException ex) { LOG.error("Finalize upgrade for " + dataDirPath + " failed", ex); } LOG.info("Finalize upgrade for " + dataDirPath + " is complete"); } @Override public String toString() { return "Finalize " + dataDirPath; } }) .start(); }
/* * Finalize the block pool storage by deleting <BP>/previous directory * that holds the snapshot. */ void doFinalize(File dnCurDir) throws IOException { File bpRoot = getBpRoot(blockpoolID, dnCurDir); StorageDirectory bpSd = new StorageDirectory(bpRoot); // block pool level previous directory File prevDir = bpSd.getPreviousDir(); if (!prevDir.exists()) { return; // already finalized } final String dataDirPath = bpSd.getRoot().getCanonicalPath(); LOG.info( "Finalizing upgrade for storage directory " + dataDirPath + ".\n cur LV = " + this.getLayoutVersion() + "; cur CTime = " + this.getCTime()); assert bpSd.getCurrentDir().exists() : "Current directory must exist."; // rename previous to finalized.tmp final File tmpDir = bpSd.getFinalizedTmp(); rename(prevDir, tmpDir); // delete finalized.tmp dir in a separate thread new Daemon( new Runnable() { @Override public void run() { try { deleteDir(tmpDir); } catch (IOException ex) { LOG.error("Finalize upgrade for " + dataDirPath + " failed.", ex); } LOG.info("Finalize upgrade for " + dataDirPath + " is complete."); } @Override public String toString() { return "Finalize " + dataDirPath; } }) .start(); }
/** * Upgrade -- Move current storage into a backup directory, and hardlink all its blocks into the * new current directory. * * <p>Upgrade from pre-0.22 to 0.22 or later release e.g. 0.19/0.20/ => 0.22/0.23 * * <ul> * <li>If <SD>/previous exists then delete it * <li>Rename <SD>/current to <SD>/previous.tmp * <li>Create new <SD>/current/<bpid>/current directory * <li> * <ul> * <li>Hard links for block files are created from <SD>/previous.tmp to * <SD>/current/<bpid>/current * <li>Saves new version file in <SD>/current/<bpid>/current directory * </ul> * <li>Rename <SD>/previous.tmp to <SD>/previous * </ul> * * There should be only ONE namenode in the cluster for first time upgrade to 0.22 * * @param sd storage directory * @throws IOException on error */ void doUpgrade(StorageDirectory sd, NamespaceInfo nsInfo) throws IOException { if (LayoutVersion.supports(Feature.FEDERATION, layoutVersion)) { clusterID = nsInfo.getClusterID(); layoutVersion = nsInfo.getLayoutVersion(); writeProperties(sd); return; } LOG.info( "Upgrading storage directory " + sd.getRoot() + ".\n old LV = " + this.getLayoutVersion() + "; old CTime = " + this.getCTime() + ".\n new LV = " + nsInfo.getLayoutVersion() + "; new CTime = " + nsInfo.getCTime()); File curDir = sd.getCurrentDir(); File prevDir = sd.getPreviousDir(); File bbwDir = new File(sd.getRoot(), Storage.STORAGE_1_BBW); assert curDir.exists() : "Data node current directory must exist."; // Cleanup directory "detach" cleanupDetachDir(new File(curDir, STORAGE_DIR_DETACHED)); // 1. delete <SD>/previous dir before upgrading if (prevDir.exists()) deleteDir(prevDir); // get previous.tmp directory, <SD>/previous.tmp File tmpDir = sd.getPreviousTmp(); assert !tmpDir.exists() : "Data node previous.tmp directory must not exist."; // 2. Rename <SD>/current to <SD>/previous.tmp rename(curDir, tmpDir); // 3. Format BP and hard link blocks from previous directory File curBpDir = BlockPoolSliceStorage.getBpRoot(nsInfo.getBlockPoolID(), curDir); BlockPoolSliceStorage bpStorage = new BlockPoolSliceStorage( nsInfo.getNamespaceID(), nsInfo.getBlockPoolID(), nsInfo.getCTime(), nsInfo.getClusterID()); bpStorage.format(curDir, nsInfo); linkAllBlocks(tmpDir, bbwDir, new File(curBpDir, STORAGE_DIR_CURRENT)); // 4. Write version file under <SD>/current layoutVersion = HdfsConstants.LAYOUT_VERSION; clusterID = nsInfo.getClusterID(); writeProperties(sd); // 5. Rename <SD>/previous.tmp to <SD>/previous rename(tmpDir, prevDir); LOG.info("Upgrade of " + sd.getRoot() + " is complete"); addBlockPoolStorage(nsInfo.getBlockPoolID(), bpStorage); }
private void doTransition( DataNode datanode, StorageDirectory sd, NamespaceInfo nsInfo, StartupOption startOpt) throws IOException { if (startOpt == StartupOption.ROLLBACK && sd.getPreviousDir().exists()) { throw new RuntimeException("ROLLBACK 未实现"); } else { int restored = restoreBlockFilesFromTrash(getTrashRootDir(sd)); LOG.info("从垃圾桶恢复" + restored + "块文件."); } readProperties(sd); checkVersionUpgradable(this.layoutVersion); assert this.layoutVersion >= HdfsConstants.DATANODE_LAYOUT_VERSION : "Future version is not allowed"; if (getNamespaceID() != nsInfo.getNamespaceID()) { throw new IOException( "Incompatible namespaceIDs in " + sd.getRoot().getCanonicalPath() + ": namenode namespaceID = " + nsInfo.getNamespaceID() + "; datanode namespaceID = " + getNamespaceID()); } if (!blockpoolID.equals(nsInfo.getBlockPoolID())) { throw new IOException( "Incompatible blockpoolIDs in " + sd.getRoot().getCanonicalPath() + ": namenode blockpoolID = " + nsInfo.getBlockPoolID() + "; datanode blockpoolID = " + blockpoolID); } if (this.layoutVersion == HdfsConstants.DATANODE_LAYOUT_VERSION && this.cTime == nsInfo.getCTime()) { return; // 正常启动 } throw new RuntimeException("upgrade 未实现"); }
private StorageDirectory loadStorageDirectory( DataNode datanode, NamespaceInfo nsInfo, File dataDir, StartupOption startOpt) throws IOException { StorageDirectory sd = new StorageDirectory(dataDir, null, true); try { StorageState curState = sd.analyzeStorage(startOpt, this); switch (curState) { case NORMAL: break; case NON_EXISTENT: LOG.info("Block pool storage directory " + dataDir + " does not exist"); throw new IOException("Storage directory " + dataDir + " does not exist"); case NOT_FORMATTED: // format LOG.info( "Block pool storage directory " + dataDir + " is not formatted for " + nsInfo.getBlockPoolID()); LOG.info("Formatting ..."); format(sd, nsInfo); break; default: throw new RuntimeException("未实现"); } doTransition(datanode, sd, nsInfo, startOpt); if (getCTime() != nsInfo.getCTime()) { throw new IOException("Data-node and name-node CTimes 必须是相同."); } // 3. 更新成功加载存储。 setServiceLayoutVersion(getServiceLayoutVersion()); writeProperties(sd); return sd; } catch (IOException ioe) { sd.unlock(); throw ioe; } }
/** * Check whether underlying file system supports file locking. * * @return <code>true</code> if exclusive locks are supported or <code>false</code> otherwise. * @throws IOException * @see StorageDirectory#lock() */ public boolean isLockSupported(int idx) throws IOException { StorageDirectory sd = storageDirs.get(idx); FileLock firstLock = null; FileLock secondLock = null; try { firstLock = sd.lock; if (firstLock == null) { firstLock = sd.tryLock(); if (firstLock == null) return true; } secondLock = sd.tryLock(); if (secondLock == null) return true; } finally { if (firstLock != null && firstLock != sd.lock) { firstLock.release(); firstLock.channel().close(); } if (secondLock != null) { secondLock.release(); secondLock.channel().close(); } } return false; }
@Override public boolean isPreUpgradableLayout(StorageDirectory sd) throws IOException { File oldF = new File(sd.getRoot(), "storage"); if (!oldF.exists()) return false; // check the layout version inside the storage file // Lock and Read old storage file RandomAccessFile oldFile = new RandomAccessFile(oldF, "rws"); FileLock oldLock = oldFile.getChannel().tryLock(); try { oldFile.seek(0); int oldVersion = oldFile.readInt(); if (oldVersion < LAST_PRE_UPGRADE_LAYOUT_VERSION) return false; } finally { oldLock.release(); oldFile.close(); } return true; }
@Override protected void setPropertiesFromFields(Properties props, StorageDirectory sd) throws IOException { props.setProperty("storageType", storageType.toString()); props.setProperty("clusterID", clusterID); props.setProperty("cTime", String.valueOf(cTime)); props.setProperty("layoutVersion", String.valueOf(layoutVersion)); props.setProperty("storageID", sd.getStorageUuid()); String datanodeUuid = getDatanodeUuid(); if (datanodeUuid != null) { props.setProperty("datanodeUuid", datanodeUuid); } // Set NamespaceID in version before federation if (!DataNodeLayoutVersion.supports(LayoutVersion.Feature.FEDERATION, layoutVersion)) { props.setProperty("namespaceID", String.valueOf(namespaceID)); } }