Skip to content

Commit

Permalink
Basic mount / unmount implementation + journaling.
Browse files Browse the repository at this point in the history
  • Loading branch information
jsimsa committed Sep 16, 2015
1 parent 7e46b09 commit 5bec4ce
Show file tree
Hide file tree
Showing 9 changed files with 280 additions and 403 deletions.
431 changes: 48 additions & 383 deletions common/src/main/java/tachyon/thrift/FileSystemMasterService.java

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions common/src/thrift/tachyon.thrift
Expand Up @@ -231,20 +231,20 @@ service FileSystemMasterService {
/**
* Loads the subtree identifies by the given path from UFS into Tachyon.
*/
bool load(1: string ufsPath) throws (1: TachyonException te)
void load(1: string ufsPath) throws (1: TachyonException te)

/**
* Creates a new "mount point", mounts the given UFS path in the Tachyon namespace at the given
* path. The path should not exist and should not be nested under any existing mount point.
*/
bool mount(1: string tachyonPath, 2: string ufsPath) throws (1: TachyonException te)
void mount(1: string tachyonPath, 2: string ufsPath) throws (1: TachyonException te)

/**
* Deletes an existing "mount point", voiding the Tachyon namespace at the given path. The path
* should correspond to an existing mount point. Any files in its subtree that are backed by UFS
* will be persisted before they are removed from the Tachyon namespace.
*/
bool unmount(1: string tachyonPath) throws (1: TachyonException te)
void unmount(1: string tachyonPath) throws (1: TachyonException te)

// Lineage Features
i32 createDependency(1: list<string> parents, 2: list<string> children,
Expand Down
4 changes: 2 additions & 2 deletions servers/src/main/java/tachyon/master/TachyonMaster.java
Expand Up @@ -77,15 +77,15 @@ public static void main(String[] args) {
/** The address for the rpc server */
private final InetSocketAddress mMasterAddress;

// The masters
// the masters
/** The master managing all block metadata */
protected BlockMaster mBlockMaster;
/** The master managing all file system related metadata */
protected FileSystemMaster mFileSystemMaster;
/** The master managing all raw table related metadata */
protected RawTableMaster mRawTableMaster;

// The journals for the masters
// the journals for the masters
/** The journal for the block master */
protected final Journal mBlockMasterJournal;
/** The journal for the file system master */
Expand Down
41 changes: 32 additions & 9 deletions servers/src/main/java/tachyon/master/file/FileSystemMaster.java
Expand Up @@ -35,12 +35,16 @@
import tachyon.StorageLevelAlias;
import tachyon.TachyonURI;
import tachyon.conf.TachyonConf;
import tachyon.exception.AlreadyExistsException;
import tachyon.exception.NotFoundException;
import tachyon.master.MasterBase;
import tachyon.master.block.BlockId;
import tachyon.master.block.BlockMaster;
import tachyon.master.file.journal.AddCheckpointEntry;
import tachyon.master.file.journal.AddMountPointEntry;
import tachyon.master.file.journal.CompleteFileEntry;
import tachyon.master.file.journal.DeleteFileEntry;
import tachyon.master.file.journal.DeleteMountPointEntry;
import tachyon.master.file.journal.DependencyEntry;
import tachyon.master.file.journal.InodeDirectoryIdGeneratorEntry;
import tachyon.master.file.journal.InodeEntry;
Expand All @@ -51,9 +55,10 @@
import tachyon.master.file.meta.DependencyMap;
import tachyon.master.file.meta.Inode;
import tachyon.master.file.meta.InodeDirectory;
import tachyon.master.file.meta.InodeDirectoryIdGenerator;
import tachyon.master.file.meta.InodeFile;
import tachyon.master.file.meta.InodeDirectoryIdGenerator;
import tachyon.master.file.meta.InodeTree;
import tachyon.master.file.meta.MountTable;
import tachyon.master.journal.Journal;
import tachyon.master.journal.JournalEntry;
import tachyon.master.journal.JournalOutputStream;
Expand Down Expand Up @@ -83,14 +88,14 @@ public final class FileSystemMaster extends MasterBase {
private static final Logger LOG = LoggerFactory.getLogger(Constants.LOGGER_TYPE);

private final BlockMaster mBlockMaster;

/** This manages the file system inode structure. This must be journaled. */
private final InodeTree mInodeTree;
/** This manages metadata for lineage. This must be journaled. */
private final DependencyMap mDependencyMap = new DependencyMap();
/** This generates unique directory ids. This must be journaled. */
private final InodeDirectoryIdGenerator mDirectoryIdGenerator;

/** This manages the file system mount points. */
private final MountTable mMountTable = new MountTable();
private final PrefixList mWhitelist;

/**
Expand Down Expand Up @@ -165,6 +170,20 @@ public void processJournalEntry(JournalEntry entry) throws IOException {
renameFromEntry((RenameEntry) entry);
} else if (entry instanceof InodeDirectoryIdGeneratorEntry) {
mDirectoryIdGenerator.fromJournalEntry((InodeDirectoryIdGeneratorEntry) entry);
} else if (entry instanceof AddMountPointEntry) {
AddMountPointEntry typedEntry = (AddMountPointEntry) entry;
try {
mMountTable.add(typedEntry.getTachyonPath(), typedEntry.getUfsPath());
} catch (AlreadyExistsException aee) {
throw new IOException(aee.getMessage());
}
} else if (entry instanceof DeleteMountPointEntry) {
DeleteMountPointEntry typedEntry = (DeleteMountPointEntry) entry;
try {
mMountTable.delete(typedEntry.getTachyonPath());
} catch (NotFoundException nfe) {
throw new IOException(nfe.getMessage());
}
} else {
throw new IOException("unexpected entry in journal: " + entry);
}
Expand Down Expand Up @@ -1071,15 +1090,19 @@ public List<Integer> getPriorityDependencyList() {
}
}

public boolean load(String ufsPath) throws TachyonException {
return true;
public void load(String ufsPath) throws TachyonException {
}

public boolean mount(String tachyonPath, String ufsPath) throws TachyonException {
return true;
public void mount(String tachyonPath, String ufsPath) throws AlreadyExistsException {
mMountTable.add(tachyonPath, ufsPath);
writeJournalEntry(new AddMountPointEntry(tachyonPath, ufsPath));
flushJournal();
}

public boolean unmount(String tachyonPath) throws TachyonException {
return true;
public void unmount(String tachyonPath) throws NotFoundException {
// TODO(jiri): Persist files nested under tachyonPath and then void its namespace.
mMountTable.delete(tachyonPath);
writeJournalEntry(new DeleteMountPointEntry(tachyonPath));
flushJournal();
}
}
Expand Up @@ -21,6 +21,8 @@
import java.util.Set;

import tachyon.TachyonURI;
import tachyon.exception.AlreadyExistsException;
import tachyon.exception.NotFoundException;
import tachyon.thrift.BlockInfoException;
import tachyon.thrift.DependencyDoesNotExistException;
import tachyon.thrift.DependencyInfo;
Expand Down Expand Up @@ -190,17 +192,25 @@ public void requestFilesInDependency(int depId) throws DependencyDoesNotExistExc
}

@Override
public boolean load(String ufsPath) throws TachyonException {
return mFileSystemMaster.load(ufsPath);
public void load(String ufsPath) throws TachyonException {
mFileSystemMaster.load(ufsPath);
}

@Override
public boolean mount(String tachyonPath, String ufsPath) throws TachyonException {
return mFileSystemMaster.mount(tachyonPath, ufsPath);
public void mount(String tachyonPath, String ufsPath) throws TachyonException {
try {
mFileSystemMaster.mount(tachyonPath, ufsPath);
} catch (AlreadyExistsException aee) {
throw new TachyonException(aee.getMessage());
}
}

@Override
public boolean unmount(String tachyonPath) throws TachyonException {
return mFileSystemMaster.unmount(tachyonPath);
public void unmount(String tachyonPath) throws TachyonException {
try {
mFileSystemMaster.unmount(tachyonPath);
} catch (NotFoundException nfe) {
throw new TachyonException(nfe.getMessage());
}
}
}
@@ -0,0 +1,54 @@
/*
* Licensed to the University of California, Berkeley under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/

package tachyon.master.file.journal;

import java.util.Map;

import com.google.common.collect.Maps;

import tachyon.master.journal.JournalEntry;
import tachyon.master.journal.JournalEntryType;

public class AddMountPointEntry implements JournalEntry {
private final String mTachyonPath;
private final String mUfsPath;

public AddMountPointEntry(String tachyonPath, String ufsPath) {
mTachyonPath = tachyonPath;
mUfsPath = ufsPath;
}

public String getTachyonPath() {
return mTachyonPath;
}

public String getUfsPath() {
return mUfsPath;
}

@Override
public JournalEntryType getType() {
return JournalEntryType.ADD_MOUNTPOINT;
}

@Override
public Map<String, Object> getParameters() {
Map<String, Object> parameters = Maps.newHashMapWithExpectedSize(2);
parameters.put("tachyonPath", mTachyonPath);
parameters.put("ufsPath", mUfsPath);
return parameters;
}
}
@@ -0,0 +1,47 @@
/*
* Licensed to the University of California, Berkeley under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/

package tachyon.master.file.journal;

import java.util.Map;

import com.google.common.collect.Maps;

import tachyon.master.journal.JournalEntry;
import tachyon.master.journal.JournalEntryType;

public class DeleteMountPointEntry implements JournalEntry {
private final String mTachyonPath;

public DeleteMountPointEntry(String tachyonPath) {
mTachyonPath = tachyonPath;
}

public String getTachyonPath() {
return mTachyonPath;
}

@Override
public JournalEntryType getType() {
return JournalEntryType.ADD_MOUNTPOINT;
}

@Override
public Map<String, Object> getParameters() {
Map<String, Object> parameters = Maps.newHashMapWithExpectedSize(1);
parameters.put("tachyonPath", mTachyonPath);
return parameters;
}
}
76 changes: 76 additions & 0 deletions servers/src/main/java/tachyon/master/file/meta/MountTable.java
@@ -0,0 +1,76 @@
/*
* Licensed to the University of California, Berkeley under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/

package tachyon.master.file.meta;

import java.util.HashMap;
import java.util.Map;

import tachyon.exception.AlreadyExistsException;
import tachyon.exception.NotFoundException;

/** This class is used for keeping track of Tachyon mount points. It is thread safe. */
public class MountTable {
private Map<String, String> mMountTable;

public MountTable() {
final int INITIAL_CAPACITY = 10;
mMountTable = new HashMap<String, String>(INITIAL_CAPACITY);
}

public synchronized void add(String tachyonPath, String ufsPath) throws AlreadyExistsException {
for (Map.Entry<String, String> entry : mMountTable.entrySet()) {
if (hasPrefix(tachyonPath, entry.getKey())) {
// Cannot mount a path under an existing mount point.
throw new AlreadyExistsException("Tachyon path " + tachyonPath
+ " cannot be mounted under an existing mount point " + entry.getValue());
}
}
mMountTable.put(tachyonPath, ufsPath);
}

public synchronized void delete(String tachyonPath) throws NotFoundException {
if (mMountTable.containsKey(tachyonPath)) {
mMountTable.remove(tachyonPath);
}
// Cannot mount a path under an existing mount point.
throw new NotFoundException("Tachyon path " + tachyonPath + " is not a valid mount point.");
}

public synchronized String lookup(String tachyonPath) {
for (Map.Entry<String, String> entry : mMountTable.entrySet()) {
if (hasPrefix(tachyonPath, entry.getKey())) {
return entry.getValue() + tachyonPath.substring(entry.getKey().length());
}
}
// If the given path is not found in the mount table, the lookup is an identity.
return tachyonPath;
}

public synchronized String reverseLookup(String ufsPath) throws NotFoundException {
for (Map.Entry<String, String> entry : mMountTable.entrySet()) {
if (hasPrefix(ufsPath, entry.getValue())) {
return entry.getKey() + ufsPath.substring(entry.getValue().length());
}
}
// If the given path is not found in the mount table, the reverse lookup fails.
throw new NotFoundException("UFS path " + ufsPath + " is not mounted in Tachyon namespace.");
}

private boolean hasPrefix(String path, String prefix) {
// TODO(jiri): Use canonical representation for UFS scheme and authority.
return path.startsWith(prefix);
}
}
Expand Up @@ -28,6 +28,8 @@ public enum JournalEntryType {
INODE_FILE,
INODE_DIRECTORY,
INODE_MTIME,
ADD_MOUNTPOINT,
DELETE_MOUNTPOINT,
ADD_CHECKPOINT,
DEPENDENCY,
COMPLETE_FILE,
Expand Down

0 comments on commit 5bec4ce

Please sign in to comment.