/* * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0 * (the "License"). You may not use this work except in compliance with the License, which is * available at www.apache.org/licenses/LICENSE-2.0 * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied, as more fully set forth in the License. * * See the NOTICE file distributed with this work for information regarding copyright ownership. */ package alluxio.worker.block.meta; import alluxio.Configuration; import alluxio.PropertyKey; import alluxio.WorkerStorageTierAssoc; import alluxio.exception.BlockAlreadyExistsException; import alluxio.exception.PreconditionMessage; import alluxio.exception.WorkerOutOfSpaceException; import alluxio.util.FormatUtils; import alluxio.util.io.FileUtils; import alluxio.util.io.PathUtils; import com.google.common.base.Preconditions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.annotation.concurrent.NotThreadSafe; /** * Represents a tier of storage, for example memory or SSD. It serves as a container of * {@link StorageDir} which actually contains metadata information about blocks stored and space * used/available. */ @NotThreadSafe public final class StorageTier { private static final Logger LOG = LoggerFactory.getLogger(StorageTier.class); /** Alias value of this tier in tiered storage. */ private final String mTierAlias; /** Ordinal value of this tier in tiered storage, highest level is 0. */ private final int mTierOrdinal; /** Total capacity of all StorageDirs in bytes. */ private long mCapacityBytes; private List<StorageDir> mDirs; private StorageTier(String tierAlias) { mTierAlias = tierAlias; mTierOrdinal = new WorkerStorageTierAssoc().getOrdinal(tierAlias); } private void initStorageTier() throws BlockAlreadyExistsException, IOException, WorkerOutOfSpaceException { String workerDataFolder = Configuration.get(PropertyKey.WORKER_DATA_FOLDER); String tmpDir = Configuration.get(PropertyKey.WORKER_DATA_TMP_FOLDER); PropertyKey tierDirPathConf = PropertyKey.Template.WORKER_TIERED_STORE_LEVEL_DIRS_PATH.format(mTierOrdinal); String[] dirPaths = Configuration.get(tierDirPathConf).split(","); // Add the worker data folder path after each storage directory, the final path will be like // /mnt/ramdisk/alluxioworker for (int i = 0; i < dirPaths.length; i++) { dirPaths[i] = PathUtils.concatPath(dirPaths[i].trim(), workerDataFolder); } PropertyKey tierDirCapacityConf = PropertyKey.Template.WORKER_TIERED_STORE_LEVEL_DIRS_QUOTA.format(mTierOrdinal); String rawDirQuota = Configuration.get(tierDirCapacityConf); Preconditions.checkState(rawDirQuota.length() > 0, PreconditionMessage.ERR_TIER_QUOTA_BLANK); String[] dirQuotas = rawDirQuota.split(","); mDirs = new ArrayList<>(dirPaths.length); long totalCapacity = 0; for (int i = 0; i < dirPaths.length; i++) { int index = i >= dirQuotas.length ? dirQuotas.length - 1 : i; long capacity = FormatUtils.parseSpaceSize(dirQuotas[index]); totalCapacity += capacity; mDirs.add(StorageDir.newStorageDir(this, i, capacity, dirPaths[i])); // Delete tmp directory. String tmpDirPath = PathUtils.concatPath(dirPaths[i], tmpDir); try { FileUtils.deletePathRecursively(tmpDirPath); } catch (IOException e) { if (FileUtils.exists(tmpDirPath)) { LOG.error("Failed to clean up temporary directory: {}.", tmpDirPath); } } } mCapacityBytes = totalCapacity; } /** * Factory method to create {@link StorageTier}. * * @param tierAlias the tier alias * @return a new storage tier * @throws BlockAlreadyExistsException if the tier already exists * @throws WorkerOutOfSpaceException if there is not enough space available */ public static StorageTier newStorageTier(String tierAlias) throws BlockAlreadyExistsException, IOException, WorkerOutOfSpaceException { StorageTier ret = new StorageTier(tierAlias); ret.initStorageTier(); return ret; } /** * @return the tier ordinal */ public int getTierOrdinal() { return mTierOrdinal; } /** * @return the tier alias */ public String getTierAlias() { return mTierAlias; } /** * @return the capacity (in bytes) */ public long getCapacityBytes() { return mCapacityBytes; } /** * @return the remaining capacity (in bytes) */ public long getAvailableBytes() { long availableBytes = 0; for (StorageDir dir : mDirs) { availableBytes += dir.getAvailableBytes(); } return availableBytes; } /** * Returns a directory for the given index. * * @param dirIndex the directory index * @return a directory */ public StorageDir getDir(int dirIndex) { return mDirs.get(dirIndex); } /** * @return a list of directories in this tier */ public List<StorageDir> getStorageDirs() { return Collections.unmodifiableList(mDirs); } }