You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@crail.apache.org by ps...@apache.org on 2018/01/22 14:20:58 UTC
[14/29] incubator-crail git commit: Apache package renaming
http://git-wip-us.apache.org/repos/asf/incubator-crail/blob/32f8ead2/client/src/main/java/org/apache/crail/conf/CrailConstants.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/crail/conf/CrailConstants.java b/client/src/main/java/org/apache/crail/conf/CrailConstants.java
new file mode 100644
index 0000000..667c454
--- /dev/null
+++ b/client/src/main/java/org/apache/crail/conf/CrailConstants.java
@@ -0,0 +1,262 @@
+/*
+ * Crail: A Multi-tiered Distributed Direct Access File System
+ *
+ * Author: Patrick Stuedi <st...@zurich.ibm.com>
+ *
+ * Copyright (C) 2016, IBM Corporation
+ *
+ * Licensed 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 org.apache.crail.conf;
+
+import java.io.IOException;
+
+import org.apache.crail.utils.CrailUtils;
+import org.slf4j.Logger;
+
+public class CrailConstants {
+ private static final Logger LOG = CrailUtils.getLogger();
+
+ public static final String VERSION_KEY = "crail.version";
+ public static int VERSION = 3003;
+
+ public static final String DIRECTORY_DEPTH_KEY = "crail.directorydepth";
+ public static int DIRECTORY_DEPTH = 16;
+
+ public static final String TOKEN_EXPIRATION_KEY = "crail.tokenexpiration";
+ public static long TOKEN_EXPIRATION = 10;
+
+ public static final String BLOCK_SIZE_KEY = "crail.blocksize";
+ public static long BLOCK_SIZE = 67108864;
+
+ public static final String CACHE_LIMIT_KEY = "crail.cachelimit";
+ public static long CACHE_LIMIT = 1073741824;
+
+ public static final String CACHE_PATH_KEY = "crail.cachepath";
+ public static String CACHE_PATH = "/home/stu/craildata/cache";
+
+ public static final String USER_KEY = "crail.user";
+ public static String USER = "stu";
+
+ public static final String SHADOW_REPLICATION_KEY = "crail.shadowreplication";
+ public static int SHADOW_REPLICATION = 1;
+
+ public static final String DEBUG_KEY = "crail.debug";
+ public static boolean DEBUG = false;
+
+ public static final String STATISTICS_KEY = "crail.statistics";
+ public static boolean STATISTICS = true;
+
+ public static final String RPC_TIMEOUT_KEY = "crail.rpctimeout";
+ public static int RPC_TIMEOUT = 1000;
+
+ public static final String DATA_TIMEOUT_KEY = "crail.datatimeout";
+ public static int DATA_TIMEOUT = 1000;
+
+ public static final String BUFFER_SIZE_KEY = "crail.buffersize";
+ public static int BUFFER_SIZE = 1048576;
+
+ public static final String SLICE_SIZE_KEY = "crail.slicesize";
+ public static int SLICE_SIZE = 524288;
+
+ public static final String SINGLETON_KEY = "crail.singleton";
+ public static boolean SINGLETON = false;
+
+ public static final String REGION_SIZE_KEY = "crail.regionsize";
+ public static long REGION_SIZE = 1073741824;
+
+ public static final String DIRECTORY_RECORD_KEY = "crail.directoryrecord";
+ public static int DIRECTORY_RECORD = 512;
+
+ public static final String DIRECTORY_RANDOMIZE_KEY = "crail.directoryrandomize";
+ public static boolean DIRECTORY_RANDOMIZE = true;
+
+ public static final String CACHE_IMPL_KEY = "crail.cacheimpl";
+ public static String CACHE_IMPL = "com.ibm.crail.memory.MappedBufferCache";
+
+ public static final String LOCATION_MAP_KEY = "crail.locationmap";
+ public static String LOCATION_MAP = "";
+
+ //namenode interface
+ public static final String NAMENODE_ADDRESS_KEY = "crail.namenode.address";
+ public static String NAMENODE_ADDRESS = "";
+
+ public static final String NAMENODE_FILEBLOCKS_KEY = "crail.namenode.fileblocks";
+ public static int NAMENODE_FILEBLOCKS = 16;
+
+ public static final String NAMENODE_BLOCKSELECTION_KEY = "crail.namenode.blockselection";
+ public static String NAMENODE_BLOCKSELECTION = "roundrobin";
+
+ public static final String NAMENODE_RPC_TYPE_KEY = "crail.namenode.rpctype";
+ public static String NAMENODE_RPC_TYPE = "com.ibm.crail.namenode.rpc.darpc.DaRPCNameNode";
+
+ public static final String NAMENODE_RPC_SERVICE_KEY = "crail.namenode.rpcservice";
+ public static String NAMENODE_RPC_SERVICE = "com.ibm.crail.namenode.NameNodeService";
+
+ public static final String NAMENODE_LOG_KEY = "crail.namenode.log";
+ public static String NAMENODE_LOG = "";
+
+ //storage interface
+ public static final String STORAGE_TYPES_KEY = "crail.storage.types";
+ public static String STORAGE_TYPES = "com.ibm.crail.storage.rdma.RdmaStorageTier";
+
+ public static final String STORAGE_CLASSES_KEY = "crail.storage.classes";
+ public static int STORAGE_CLASSES = 1;
+
+ public static final String STORAGE_ROOTCLASS_KEY = "crail.storage.rootclass";
+ public static int STORAGE_ROOTCLASS = 0;
+
+ public static final String STORAGE_KEEPALIVE_KEY = "crail.storage.keepalive";
+ public static int STORAGE_KEEPALIVE = 2;
+
+ public static void updateConstants(CrailConfiguration conf){
+ //general
+ if (conf.get(DIRECTORY_DEPTH_KEY) != null) {
+ DIRECTORY_DEPTH = Integer.parseInt(conf.get(DIRECTORY_DEPTH_KEY));
+ }
+ if (conf.get(TOKEN_EXPIRATION_KEY) != null) {
+ TOKEN_EXPIRATION = Long.parseLong(conf.get(TOKEN_EXPIRATION_KEY));
+ }
+ if (conf.get(BLOCK_SIZE_KEY) != null) {
+ BLOCK_SIZE = Long.parseLong(conf.get(BLOCK_SIZE_KEY));
+ }
+ if (conf.get(CACHE_LIMIT_KEY) != null) {
+ CACHE_LIMIT = Long.parseLong(conf.get(CACHE_LIMIT_KEY));
+ }
+ if (conf.get(CACHE_PATH_KEY) != null) {
+ CACHE_PATH = conf.get(CACHE_PATH_KEY);
+ }
+ if (conf.get(USER_KEY) != null) {
+ USER = conf.get(CrailConstants.USER_KEY);
+ }
+ if (conf.get(SHADOW_REPLICATION_KEY) != null) {
+ SHADOW_REPLICATION = Integer.parseInt(conf.get(SHADOW_REPLICATION_KEY));
+ }
+ if (conf.get(DEBUG_KEY) != null) {
+ DEBUG = Boolean.parseBoolean(conf.get(DEBUG_KEY));
+ }
+ if (conf.get(STATISTICS_KEY) != null) {
+ STATISTICS = Boolean.parseBoolean(conf.get(STATISTICS_KEY));
+ }
+ if (conf.get(RPC_TIMEOUT_KEY) != null) {
+ RPC_TIMEOUT = Integer.parseInt(conf.get(RPC_TIMEOUT_KEY));
+ }
+ if (conf.get(DATA_TIMEOUT_KEY) != null) {
+ DATA_TIMEOUT = Integer.parseInt(conf.get(DATA_TIMEOUT_KEY));
+ }
+ if (conf.get(BUFFER_SIZE_KEY) != null) {
+ BUFFER_SIZE = Integer.parseInt(conf.get(BUFFER_SIZE_KEY));
+ }
+ if (conf.get(SLICE_SIZE_KEY) != null) {
+ SLICE_SIZE = Integer.parseInt(conf.get(SLICE_SIZE_KEY));
+ }
+ if (conf.get(CrailConstants.SINGLETON_KEY) != null) {
+ SINGLETON = conf.getBoolean(CrailConstants.SINGLETON_KEY, false);
+ }
+ if (conf.get(REGION_SIZE_KEY) != null) {
+ REGION_SIZE = Integer.parseInt(conf.get(REGION_SIZE_KEY));
+ }
+ if (conf.get(DIRECTORY_RECORD_KEY) != null) {
+ DIRECTORY_RECORD = Integer.parseInt(conf.get(DIRECTORY_RECORD_KEY));
+ }
+ if (conf.get(CrailConstants.DIRECTORY_RANDOMIZE_KEY) != null) {
+ DIRECTORY_RANDOMIZE = conf.getBoolean(CrailConstants.DIRECTORY_RANDOMIZE_KEY, false);
+ }
+ if (conf.get(CACHE_IMPL_KEY) != null) {
+ CACHE_IMPL = conf.get(CACHE_IMPL_KEY);
+ }
+ if (conf.get(LOCATION_MAP_KEY) != null) {
+ LOCATION_MAP = conf.get(LOCATION_MAP_KEY);
+ }
+
+ //namenode interface
+ if (conf.get(NAMENODE_ADDRESS_KEY) != null) {
+ NAMENODE_ADDRESS = conf.get(NAMENODE_ADDRESS_KEY);
+ }
+ if (conf.get(NAMENODE_BLOCKSELECTION_KEY) != null) {
+ NAMENODE_BLOCKSELECTION = conf.get(NAMENODE_BLOCKSELECTION_KEY);
+ }
+ if (conf.get(NAMENODE_FILEBLOCKS_KEY) != null) {
+ NAMENODE_FILEBLOCKS = Integer.parseInt(conf.get(NAMENODE_FILEBLOCKS_KEY));
+ }
+ if (conf.get(NAMENODE_RPC_TYPE_KEY) != null) {
+ NAMENODE_RPC_TYPE = conf.get(NAMENODE_RPC_TYPE_KEY);
+ }
+ if (conf.get(NAMENODE_LOG_KEY) != null) {
+ NAMENODE_LOG = conf.get(NAMENODE_LOG_KEY);
+ }
+
+ //storage interface
+ if (conf.get(STORAGE_TYPES_KEY) != null) {
+ STORAGE_TYPES = conf.get(STORAGE_TYPES_KEY);
+ }
+ if (conf.get(STORAGE_CLASSES_KEY) != null) {
+ STORAGE_CLASSES = Math.max(Integer.parseInt(conf.get(STORAGE_CLASSES_KEY)), CrailUtils.getStorageClasses(STORAGE_TYPES));
+ } else {
+ STORAGE_CLASSES = CrailUtils.getStorageClasses(STORAGE_TYPES);
+ }
+ if (conf.get(STORAGE_ROOTCLASS_KEY) != null) {
+ STORAGE_ROOTCLASS = Integer.parseInt(conf.get(STORAGE_ROOTCLASS_KEY));
+ }
+ if (conf.get(STORAGE_KEEPALIVE_KEY) != null) {
+ STORAGE_KEEPALIVE = Integer.parseInt(conf.get(STORAGE_KEEPALIVE_KEY));
+ }
+ }
+
+ public static void printConf(){
+ LOG.info(VERSION_KEY + " " + VERSION);
+ LOG.info(DIRECTORY_DEPTH_KEY + " " + DIRECTORY_DEPTH);
+ LOG.info(TOKEN_EXPIRATION_KEY + " " + TOKEN_EXPIRATION);
+ LOG.info(BLOCK_SIZE_KEY + " " + BLOCK_SIZE);
+ LOG.info(CACHE_LIMIT_KEY + " " + CACHE_LIMIT);
+ LOG.info(CACHE_PATH_KEY + " " + CACHE_PATH);
+ LOG.info(USER_KEY + " " + USER);
+ LOG.info(SHADOW_REPLICATION_KEY + " " + SHADOW_REPLICATION);
+ LOG.info(DEBUG_KEY + " " + DEBUG);
+ LOG.info(STATISTICS_KEY + " " + STATISTICS);
+ LOG.info(RPC_TIMEOUT_KEY + " " + RPC_TIMEOUT);
+ LOG.info(DATA_TIMEOUT_KEY + " " + DATA_TIMEOUT);
+ LOG.info(BUFFER_SIZE_KEY + " " + BUFFER_SIZE);
+ LOG.info(SLICE_SIZE_KEY + " " + SLICE_SIZE);
+ LOG.info(SINGLETON_KEY + " " + SINGLETON);
+ LOG.info(REGION_SIZE_KEY + " " + REGION_SIZE);
+ LOG.info(DIRECTORY_RECORD_KEY + " " + DIRECTORY_RECORD);
+ LOG.info(DIRECTORY_RANDOMIZE_KEY + " " + DIRECTORY_RANDOMIZE);
+ LOG.info(CACHE_IMPL_KEY + " " + CACHE_IMPL);
+ LOG.info(LOCATION_MAP_KEY + " " + LOCATION_MAP);
+ LOG.info(NAMENODE_ADDRESS_KEY + " " + NAMENODE_ADDRESS);
+ LOG.info(NAMENODE_BLOCKSELECTION_KEY + " " + NAMENODE_BLOCKSELECTION);
+ LOG.info(NAMENODE_FILEBLOCKS_KEY + " " + NAMENODE_FILEBLOCKS);
+ LOG.info(NAMENODE_RPC_TYPE_KEY + " " + NAMENODE_RPC_TYPE);
+ LOG.info(NAMENODE_LOG_KEY + " " + NAMENODE_LOG);
+ LOG.info(STORAGE_TYPES_KEY + " " + STORAGE_TYPES);
+ LOG.info(STORAGE_CLASSES_KEY + " " + STORAGE_CLASSES);
+ LOG.info(STORAGE_ROOTCLASS_KEY + " " + STORAGE_ROOTCLASS);
+ LOG.info(STORAGE_KEEPALIVE_KEY + " " + STORAGE_KEEPALIVE);
+ }
+
+ public static void verify() throws IOException {
+ if (CrailConstants.BUFFER_SIZE % CrailConstants.DIRECTORY_RECORD != 0){
+ throw new IOException("crail.buffersize must be multiple of " + CrailConstants.DIRECTORY_RECORD);
+ }
+ if (Math.max(CrailConstants.BUFFER_SIZE, CrailConstants.SLICE_SIZE) % Math.min(CrailConstants.BUFFER_SIZE, CrailConstants.SLICE_SIZE) != 0){
+ throw new IOException("crail.slicesize must be multiple of buffersize " + CrailConstants.BUFFER_SIZE);
+ }
+ if (CrailConstants.STORAGE_CLASSES < CrailUtils.getStorageClasses(STORAGE_TYPES)){
+ throw new IOException("crail.storage.classes cannot be smaller than the number of storage types " + CrailUtils.getStorageClasses(STORAGE_TYPES));
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-crail/blob/32f8ead2/client/src/main/java/org/apache/crail/core/CoreBlockLocation.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/crail/core/CoreBlockLocation.java b/client/src/main/java/org/apache/crail/core/CoreBlockLocation.java
new file mode 100644
index 0000000..d2a5850
--- /dev/null
+++ b/client/src/main/java/org/apache/crail/core/CoreBlockLocation.java
@@ -0,0 +1,127 @@
+/*
+ * Crail: A Multi-tiered Distributed Direct Access File System
+ *
+ * Author: Patrick Stuedi <st...@zurich.ibm.com>
+ *
+ * Copyright (C) 2016, IBM Corporation
+ *
+ * Licensed 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 org.apache.crail.core;
+
+import org.apache.crail.CrailBlockLocation;
+
+class CoreBlockLocation implements CrailBlockLocation {
+ private String[] names;
+ private String[] hosts;
+ private String[] topology;
+ private int[] storageTypes;
+ private int[] storageClasses;
+ private int[] locationAffinities;
+ private long offset;
+ private long length;
+
+ public CoreBlockLocation() {
+ }
+
+ public long getOffset() {
+ return offset;
+ }
+
+ public void setOffset(long offset) {
+ this.offset = offset;
+ }
+
+ public void setLength(long length) {
+ this.length = length;
+ }
+
+ public long getLength(){
+ return length;
+ }
+
+ public String[] getNames() {
+ return names;
+ }
+
+ public void setNames(String[] names) {
+ this.names = names;
+ }
+
+ public String[] getHosts() {
+ return hosts;
+ }
+
+ public void setHosts(String[] hosts) {
+ this.hosts = hosts;
+ }
+
+ public String[] getTopology() {
+ return topology;
+ }
+
+ public void setTopologyPaths(String[] topology) {
+ this.topology = topology;
+ }
+
+ public int[] getStorageTypes() {
+ return storageTypes;
+ }
+
+ public void setStorageTypes(int[] storageTypes) {
+ this.storageTypes = storageTypes;
+ }
+
+ public int[] getStorageClasses() {
+ return storageClasses;
+ }
+
+ public void setStorageClasses(int[] storageClasses) {
+ this.storageClasses = storageClasses;
+ }
+
+ public int[] getLocationAffinities() {
+ return locationAffinities;
+ }
+
+ public void setLocationAffinities(int[] locationTiers) {
+ this.locationAffinities = locationTiers;
+ }
+
+ public String toString() {
+ StringBuilder result = new StringBuilder();
+ result.append(offset);
+ result.append(',');
+ result.append(length);
+ for(String h: hosts) {
+ result.append(',');
+ result.append(h);
+ }
+ for (int i = 0; i < storageTypes.length; i++){
+ result.append(',');
+ result.append(storageTypes[i]);
+ }
+ for (int i = 0; i < storageClasses.length; i++){
+ result.append(',');
+ result.append(storageClasses[i]);
+ }
+ for (int i = 0; i < locationAffinities.length; i++){
+ result.append(',');
+ result.append(locationAffinities[i]);
+ }
+ return result.toString();
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-crail/blob/32f8ead2/client/src/main/java/org/apache/crail/core/CoreDataOperation.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/crail/core/CoreDataOperation.java b/client/src/main/java/org/apache/crail/core/CoreDataOperation.java
new file mode 100644
index 0000000..9fd3ca3
--- /dev/null
+++ b/client/src/main/java/org/apache/crail/core/CoreDataOperation.java
@@ -0,0 +1,137 @@
+/*
+ * Crail: A Multi-tiered Distributed Direct Access File System
+ *
+ * Author: Patrick Stuedi <st...@zurich.ibm.com>
+ *
+ * Copyright (C) 2016, IBM Corporation
+ *
+ * Licensed 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 org.apache.crail.core;
+
+import org.apache.crail.CrailBuffer;
+import org.apache.crail.CrailResult;
+import org.apache.crail.conf.CrailConstants;
+import org.apache.crail.storage.StorageFuture;
+import org.apache.crail.storage.StorageResult;
+import org.apache.crail.utils.BufferCheckpoint;
+import org.apache.crail.utils.MultiFuture;
+
+class CoreDataOperation extends MultiFuture<StorageResult, CrailResult> implements CrailResult {
+ private CoreStream stream;
+ private CrailBuffer buffer;
+ private long fileOffset;
+ private int bufferPosition;
+ private int bufferLimit;
+ private int operationLength;
+
+ //current state
+ private BufferCheckpoint bufferCheckpoint;
+ private int inProcessLen;
+ private long completedLen;
+ private boolean isSynchronous;
+
+ public CoreDataOperation(CoreStream stream, CrailBuffer buffer) throws Exception{
+ this.stream = stream;
+ this.buffer = buffer;
+ this.fileOffset = stream.position();
+ this.bufferPosition = buffer.position();
+ this.bufferLimit = buffer.limit();
+ this.operationLength = buffer.remaining();
+ this.inProcessLen = 0;
+ this.completedLen = 0;
+ this.isSynchronous = false;
+
+ if (operationLength > 0){
+ this.bufferCheckpoint = stream.getBufferCheckpoint();
+ if (CrailConstants.DEBUG){
+ this.bufferCheckpoint.checkIn(buffer);
+ }
+ }
+ }
+
+ public long getLen() {
+ return completedLen;
+ }
+
+ void incProcessedLen(int opLen){
+ this.inProcessLen += opLen;
+ }
+
+ long getInProcessLen(){
+ return this.inProcessLen;
+ }
+
+ int getBufferLimit(){
+ return bufferLimit;
+ }
+
+ int remaining() {
+ return operationLength - inProcessLen;
+ }
+
+ int getCurrentBufferPosition(){
+ return bufferPosition + inProcessLen;
+ }
+
+ long getCurrentStreamPosition(){
+ return fileOffset + inProcessLen;
+ }
+
+ boolean isProcessed() {
+ return inProcessLen == operationLength;
+ }
+
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ return false;
+ }
+
+ public boolean isCancelled() {
+ return false;
+ }
+
+ public synchronized void add(StorageFuture dataFuture) {
+ super.add(dataFuture);
+ if (dataFuture.isSynchronous()){
+ this.isSynchronous = true;
+ }
+ }
+
+ //-----------
+
+ public void completeOperation(){
+ super.completeOperation();
+ if (this.isDone()){
+ stream.update(fileOffset + completedLen);
+ if (CrailConstants.DEBUG){
+ bufferCheckpoint.checkOut(buffer);
+ }
+ }
+ }
+
+ boolean isSynchronous() {
+ return isSynchronous;
+ }
+
+ @Override
+ public void aggregate(StorageResult result) {
+ completedLen += result.getLen();
+ }
+
+ @Override
+ public CrailResult getAggregate() {
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-crail/blob/32f8ead2/client/src/main/java/org/apache/crail/core/CoreDirectory.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/crail/core/CoreDirectory.java b/client/src/main/java/org/apache/crail/core/CoreDirectory.java
new file mode 100644
index 0000000..add90fd
--- /dev/null
+++ b/client/src/main/java/org/apache/crail/core/CoreDirectory.java
@@ -0,0 +1,94 @@
+/*
+ * Crail: A Multi-tiered Distributed Direct Access File System
+ *
+ * Author: Patrick Stuedi <st...@zurich.ibm.com>
+ *
+ * Copyright (C) 2016, IBM Corporation
+ *
+ * Licensed 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 org.apache.crail.core;
+
+import java.util.Iterator;
+
+import org.apache.crail.CrailContainer;
+import org.apache.crail.CrailDirectory;
+import org.apache.crail.CrailMultiFile;
+import org.apache.crail.CrailTable;
+import org.apache.crail.conf.CrailConstants;
+import org.apache.crail.metadata.FileInfo;
+
+class CoreDirectory extends CoreNode implements CrailContainer, CrailDirectory, CrailMultiFile, CrailTable {
+
+ public CoreDirectory(CoreFileSystem fs, FileInfo fileInfo, String path){
+ super(fs, fileInfo, path);
+ this.fs = fs;
+ this.fileInfo = fileInfo;
+ this.path = path;
+ }
+
+ @Override
+ public int files() {
+ return (int) fileInfo.getCapacity()/CrailConstants.DIRECTORY_RECORD;
+ }
+
+ @Override
+ public Iterator<String> listEntries() throws Exception {
+ return fs.listEntries(path);
+ }
+
+ @Override
+ public CoreDirectory asDirectory() throws Exception {
+ if (!getType().isDirectory()){
+ throw new Exception("file type mismatch, type " + getType());
+ }
+ return this;
+ }
+
+ @Override
+ public CoreDirectory asContainer() throws Exception {
+ if (!getType().isContainer()){
+ throw new Exception("file type mismatch, type " + getType());
+ }
+ return this;
+ }
+
+ @Override
+ public CrailMultiFile asMultiFile() throws Exception {
+ if (!getType().isMultiFile()){
+ throw new Exception("file type mismatch, type " + getType());
+ }
+ return this;
+ }
+
+ @Override
+ public CrailTable asTable() throws Exception {
+ if (!getType().isTable()){
+ throw new Exception("file type mismatch, type " + getType());
+ }
+ return this;
+ }
+
+ DirectoryOutputStream getDirectoryOutputStream() throws Exception {
+ CoreOutputStream outputStream = super.getOutputStream(0);
+ return new DirectoryOutputStream(outputStream);
+ }
+
+ DirectoryInputStream getDirectoryInputStream(boolean randomize) throws Exception {
+ CoreInputStream inputStream = super.getInputStream(0);
+ return new DirectoryInputStream(inputStream, randomize);
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-crail/blob/32f8ead2/client/src/main/java/org/apache/crail/core/CoreFile.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/crail/core/CoreFile.java b/client/src/main/java/org/apache/crail/core/CoreFile.java
new file mode 100644
index 0000000..083d075
--- /dev/null
+++ b/client/src/main/java/org/apache/crail/core/CoreFile.java
@@ -0,0 +1,202 @@
+/*
+ * Crail: A Multi-tiered Distributed Direct Access File System
+ *
+ * Author: Patrick Stuedi <st...@zurich.ibm.com>
+ *
+ * Copyright (C) 2016, IBM Corporation
+ *
+ * Licensed 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 org.apache.crail.core;
+
+import java.util.concurrent.Semaphore;
+
+import org.apache.crail.CrailBlockLocation;
+import org.apache.crail.CrailContainer;
+import org.apache.crail.CrailDirectory;
+import org.apache.crail.CrailFS;
+import org.apache.crail.CrailFile;
+import org.apache.crail.CrailInputStream;
+import org.apache.crail.CrailKeyValue;
+import org.apache.crail.CrailMultiFile;
+import org.apache.crail.CrailNode;
+import org.apache.crail.CrailNodeType;
+import org.apache.crail.CrailOutputStream;
+import org.apache.crail.CrailTable;
+import org.apache.crail.metadata.FileInfo;
+
+public class CoreFile extends CoreNode implements CrailFile, CrailKeyValue {
+ private Semaphore outputStreams;
+
+ public CoreFile(CoreFileSystem fs, FileInfo fileInfo, String path){
+ super(fs, fileInfo, path);
+ this.outputStreams = new Semaphore(1);
+ }
+
+ public CrailInputStream getDirectInputStream(long readHint) throws Exception{
+ if (fileInfo.getType().isDirectory()){
+ throw new Exception("Cannot open stream for directory");
+ }
+
+ return super.getInputStream(readHint);
+ }
+
+ public synchronized CrailOutputStream getDirectOutputStream(long writeHint) throws Exception {
+ if (fileInfo.getType().isDirectory()){
+ throw new Exception("Cannot open stream for directory");
+ }
+ if (fileInfo.getToken() == 0){
+ throw new Exception("File is in read mode, cannot create outputstream, fd " + fileInfo.getFd());
+ }
+ if (!outputStreams.tryAcquire()){
+ throw new Exception("Only one concurrent output stream per file allowed");
+ }
+ return super.getOutputStream(writeHint);
+ }
+
+ public long getToken() {
+ return fileInfo.getToken();
+ }
+
+ public boolean tokenFree(){
+ return fileInfo.tokenFree();
+ }
+
+ public CoreFile asFile() throws Exception {
+ if (!getType().isDataFile()){
+ throw new Exception("file type mismatch, type " + getType());
+ }
+ return this;
+ }
+
+ public CoreFile asKeyValue() throws Exception {
+ if (!getType().isKeyValue()){
+ throw new Exception("file type mismatch, type " + getType());
+ }
+ return this;
+ }
+
+ void closeOutputStream(CoreOutputStream stream) throws Exception {
+ super.closeOutputStream(stream);
+ outputStreams.release();
+ }
+}
+
+class CoreEarlyFile implements CrailFile, CrailKeyValue {
+ private CoreFileSystem fs;
+ private String path;
+ private CrailNodeType type;
+ private CreateNodeFuture future;
+ private CrailFile file;
+
+ public CoreEarlyFile(CoreFileSystem fs, String path, CrailNodeType type, CreateNodeFuture future) {
+ this.fs = fs;
+ this.path = path;
+ this.type = type;
+ this.future = future;
+ this.file = null;
+ }
+
+ public CrailInputStream getDirectInputStream(long readHint) throws Exception{
+ return file().getDirectInputStream(readHint);
+ }
+
+ public synchronized CrailOutputStream getDirectOutputStream(long writeHint) throws Exception {
+ return file().getDirectOutputStream(writeHint);
+ }
+
+ public CrailBlockLocation[] getBlockLocations(long start, long len) throws Exception{
+ return fs.getBlockLocations(path, start, len);
+ }
+
+ public long getToken() {
+ return file().getToken();
+ }
+
+ public CrailFile asFile() throws Exception {
+ return this;
+ }
+
+ public CrailKeyValue asKeyValue() throws Exception {
+ return this;
+ }
+
+ @Override
+ public CrailFS getFileSystem() {
+ return fs;
+ }
+
+ @Override
+ public String getPath() {
+ return path;
+ }
+
+ @Override
+ public CrailNode syncDir() throws Exception {
+ return file().syncDir();
+ }
+
+ @Override
+ public long getModificationTime() {
+ return file().getModificationTime();
+ }
+
+ @Override
+ public long getCapacity() {
+ return file().getCapacity();
+ }
+
+ @Override
+ public CrailNodeType getType() {
+ return type;
+ }
+
+ @Override
+ public CrailContainer asContainer() throws Exception {
+ throw new Exception("this is not a container");
+ }
+
+ @Override
+ public CrailDirectory asDirectory() throws Exception {
+ throw new Exception("this is not a directory");
+ }
+
+ @Override
+ public CrailMultiFile asMultiFile() throws Exception {
+ throw new Exception("this is not a multifile");
+ }
+
+ @Override
+ public CrailTable asTable() throws Exception {
+ throw new Exception("this is not a table");
+ }
+
+ @Override
+ public long getFd() {
+ return file().getFd();
+ }
+
+ private synchronized CrailFile file() {
+ try {
+ if (file == null){
+ file = this.future.get().asFile();
+ }
+ return file;
+ } catch(Exception e){
+ throw new RuntimeException(e);
+ }
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-crail/blob/32f8ead2/client/src/main/java/org/apache/crail/core/CoreFileSystem.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/crail/core/CoreFileSystem.java b/client/src/main/java/org/apache/crail/core/CoreFileSystem.java
new file mode 100644
index 0000000..da6f06c
--- /dev/null
+++ b/client/src/main/java/org/apache/crail/core/CoreFileSystem.java
@@ -0,0 +1,653 @@
+/*
+ * Crail: A Multi-tiered Distributed Direct Access File System
+ *
+ * Author: Patrick Stuedi <st...@zurich.ibm.com>
+ *
+ * Copyright (C) 2016, IBM Corporation
+ *
+ * Licensed 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 org.apache.crail.core;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.StringTokenizer;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.crail.CrailBlockLocation;
+import org.apache.crail.CrailBuffer;
+import org.apache.crail.CrailFS;
+import org.apache.crail.CrailLocationClass;
+import org.apache.crail.CrailNode;
+import org.apache.crail.CrailNodeType;
+import org.apache.crail.CrailResult;
+import org.apache.crail.CrailStatistics;
+import org.apache.crail.CrailStorageClass;
+import org.apache.crail.Upcoming;
+import org.apache.crail.conf.CrailConfiguration;
+import org.apache.crail.conf.CrailConstants;
+import org.apache.crail.memory.BufferCache;
+import org.apache.crail.metadata.BlockInfo;
+import org.apache.crail.metadata.DataNodeInfo;
+import org.apache.crail.metadata.FileInfo;
+import org.apache.crail.metadata.FileName;
+import org.apache.crail.rpc.RpcClient;
+import org.apache.crail.rpc.RpcConnection;
+import org.apache.crail.rpc.RpcCreateFile;
+import org.apache.crail.rpc.RpcDeleteFile;
+import org.apache.crail.rpc.RpcDispatcher;
+import org.apache.crail.rpc.RpcErrors;
+import org.apache.crail.rpc.RpcFuture;
+import org.apache.crail.rpc.RpcGetFile;
+import org.apache.crail.rpc.RpcGetLocation;
+import org.apache.crail.rpc.RpcPing;
+import org.apache.crail.rpc.RpcRenameFile;
+import org.apache.crail.storage.StorageClient;
+import org.apache.crail.utils.BlockCache;
+import org.apache.crail.utils.BufferCheckpoint;
+import org.apache.crail.utils.CrailUtils;
+import org.apache.crail.utils.EndpointCache;
+import org.apache.crail.utils.NextBlockCache;
+import org.apache.crail.utils.BlockCache.FileBlockCache;
+import org.apache.crail.utils.NextBlockCache.FileNextBlockCache;
+import org.slf4j.Logger;
+
+public class CoreFileSystem extends CrailFS {
+ private static final Logger LOG = CrailUtils.getLogger();
+ private static AtomicInteger fsCount = new AtomicInteger(0);
+
+ //namenode operations
+ private RpcClient rpcClient;
+ private RpcConnection rpcConnection;
+
+ //datanode operations
+ private EndpointCache datanodeEndpointCache;
+
+ private AtomicLong streamCounter;
+ private ConcurrentHashMap<Long, CoreInputStream> openInputStreams;
+ private ConcurrentHashMap<Long, CoreOutputStream> openOutputStreams;
+
+ private BlockCache blockCache;
+ private NextBlockCache nextBlockCache;
+ private BufferCache bufferCache;
+ private BufferCheckpoint bufferCheckpoint;
+ private ConcurrentHashMap<String, String> locationMap;
+
+ private boolean isOpen;
+ private int fsId;
+ private CrailLocationClass localClass;
+
+ private CoreIOStatistics ioStatsIn;
+ private CoreIOStatistics ioStatsOut;
+ private CoreStreamStatistics streamStats;
+ private CrailStatistics statistics;
+
+ public CoreFileSystem(CrailConfiguration conf) throws Exception {
+ CrailConstants.updateConstants(conf);
+ CrailConstants.printConf();
+ CrailConstants.verify();
+
+ //Datanodes
+ StringTokenizer tokenizer = new StringTokenizer(CrailConstants.STORAGE_TYPES, ",");
+ LinkedList<StorageClient> dataNodeClients = new LinkedList<StorageClient>();
+ while (tokenizer.hasMoreTokens()){
+ String name = tokenizer.nextToken();
+ StorageClient dataNode = StorageClient.createInstance(name);
+ dataNode.init(conf, null);
+ dataNode.printConf(LOG);
+ dataNodeClients.add(dataNode);
+ }
+ this.datanodeEndpointCache = new EndpointCache(fsId, dataNodeClients);
+
+ //Namenode
+ InetSocketAddress nnAddr = CrailUtils.getNameNodeAddress();
+ this.rpcClient = RpcClient.createInstance(CrailConstants.NAMENODE_RPC_TYPE);
+ rpcClient.init(conf, null);
+ rpcClient.printConf(LOG);
+ ConcurrentLinkedQueue<InetSocketAddress> namenodeList = CrailUtils.getNameNodeList();
+ ConcurrentLinkedQueue<RpcConnection> connectionList = new ConcurrentLinkedQueue<RpcConnection>();
+ while(!namenodeList.isEmpty()){
+ InetSocketAddress address = namenodeList.poll();
+ RpcConnection connection = rpcClient.connect(address);
+ connectionList.add(connection);
+ }
+ if (connectionList.size() == 1){
+ this.rpcConnection = connectionList.poll();
+ } else {
+ this.rpcConnection = new RpcDispatcher(connectionList);
+ }
+ LOG.info("connected to namenode(s) " + rpcConnection);
+
+ //Client
+ this.fsId = fsCount.getAndIncrement();
+ this.localClass = CrailUtils.getLocationClass();
+ this.bufferCache = BufferCache.createInstance(CrailConstants.CACHE_IMPL);
+ this.blockCache = new BlockCache();
+ this.nextBlockCache = new NextBlockCache();
+ this.openInputStreams = new ConcurrentHashMap<Long, CoreInputStream>();
+ this.openOutputStreams = new ConcurrentHashMap<Long, CoreOutputStream>();
+ this.streamCounter = new AtomicLong(0);
+ this.isOpen = true;
+ this.bufferCheckpoint = new BufferCheckpoint();
+ this.locationMap = new ConcurrentHashMap<String, String>();
+ CrailUtils.parseMap(CrailConstants.LOCATION_MAP, locationMap);
+
+ this.statistics = new CrailStatistics();
+ this.ioStatsIn = new CoreIOStatistics("core/input");
+ statistics.addProvider(ioStatsIn);
+ this.ioStatsOut = new CoreIOStatistics("core/output");
+ statistics.addProvider(ioStatsOut);
+ this.streamStats = new CoreStreamStatistics();
+ statistics.addProvider(streamStats);
+ statistics.addProvider(bufferCache);
+ statistics.addProvider(datanodeEndpointCache);
+ }
+
+ public Upcoming<CrailNode> create(String path, CrailNodeType type, CrailStorageClass storageClass, CrailLocationClass locationClass) throws Exception {
+ FileName name = new FileName(path);
+
+ if (CrailConstants.DEBUG){
+ LOG.info("createNode: name " + path + ", type " + type + ", storageAffinity " + storageClass + ", locationAffinity " + locationClass);
+ }
+
+ RpcFuture<RpcCreateFile> fileRes = rpcConnection.createFile(name, type, storageClass.value(), locationClass.value());
+ return new CreateNodeFuture(this, path, type, fileRes);
+ }
+
+ CoreNode _createNode(String path, CrailNodeType type, RpcCreateFile fileRes) throws Exception {
+ if (fileRes.getError() == RpcErrors.ERR_PARENT_MISSING){
+ throw new IOException("createNode: " + RpcErrors.messages[fileRes.getError()] + ", name " + path);
+ } else if (fileRes.getError() == RpcErrors.ERR_FILE_EXISTS){
+ throw new IOException("createNode: " + RpcErrors.messages[fileRes.getError()] + ", name " + path);
+ } else if (fileRes.getError() != RpcErrors.ERR_OK){
+ LOG.info("createNode: " + RpcErrors.messages[fileRes.getError()] + ", name " + path);
+ throw new IOException("createNode: " + RpcErrors.messages[fileRes.getError()] + ", error " + fileRes.getError());
+ }
+
+ FileInfo fileInfo = fileRes.getFile();
+ FileInfo dirInfo = fileRes.getParent();
+ if (fileInfo == null || dirInfo == null){
+ throw new IOException("createFile: " + RpcErrors.messages[RpcErrors.ERR_UNKNOWN]);
+ }
+ if (fileInfo.getType() != type){
+ throw new IOException("createFile: " + "file type mismatch");
+ }
+
+ blockCache.remove(fileInfo.getFd());
+ nextBlockCache.remove(fileInfo.getFd());
+ CoreNode node = CoreNode.create(this, fileInfo, path);
+
+ BlockInfo fileBlock = fileRes.getFileBlock();
+ getBlockCache(fileInfo.getFd()).put(CoreSubOperation.createKey(fileInfo.getFd(), 0), fileBlock);
+
+ //write directory record is a directory slot has been assigned to the file
+ if (fileInfo.getDirOffset() >= 0){
+ BlockInfo dirBlock = fileRes.getDirBlock();
+ getBlockCache(dirInfo.getFd()).put(CoreSubOperation.createKey(dirInfo.getFd(), fileInfo.getDirOffset()), dirBlock);
+ CoreSyncOperation syncOperation = getSyncOperation(dirInfo, fileInfo, path, true);
+ node.addSyncOperation(syncOperation);
+ }
+
+ if (CrailConstants.DEBUG){
+ LOG.info("createFile: name " + path + ", success, fd " + fileInfo.getFd() + ", token " + fileInfo.getToken());
+ }
+
+ return node;
+ }
+
+ public Upcoming<CrailNode> lookup(String path) throws Exception {
+ FileName name = new FileName(path);
+
+ if (CrailConstants.DEBUG){
+ LOG.info("lookupDirectory: path " + path);
+ }
+
+ RpcFuture<RpcGetFile> fileRes = rpcConnection.getFile(name, false);
+ return new LookupNodeFuture(this, path, fileRes);
+ }
+
+ CoreNode _lookupNode(RpcGetFile fileRes, String path) throws Exception {
+ if (fileRes.getError() == RpcErrors.ERR_GET_FILE_FAILED){
+ return null;
+ }
+ else if (fileRes.getError() != RpcErrors.ERR_OK){
+ LOG.info("lookupDirectory: " + RpcErrors.messages[fileRes.getError()]);
+ return null;
+ }
+
+ FileInfo fileInfo = fileRes.getFile();
+
+ CoreNode node = null;
+ if (fileInfo != null){
+ if (CrailConstants.DEBUG){
+ LOG.info("lookup: name " + path + ", success, fd " + fileInfo.getFd());
+ }
+ BlockInfo fileBlock = fileRes.getFileBlock();
+ getBlockCache(fileInfo.getFd()).put(CoreSubOperation.createKey(fileInfo.getFd(), 0), fileBlock);
+
+ node = CoreNode.create(this, fileInfo, path);
+ }
+ return node;
+ }
+
+
+ public Upcoming<CrailNode> rename(String src, String dst) throws Exception {
+ FileName srcPath = new FileName(src);
+ FileName dstPath = new FileName(dst);
+
+ if (CrailConstants.DEBUG){
+ LOG.info("rename: srcname " + src + ", dstname " + dst);
+ }
+
+ RpcFuture<RpcRenameFile> renameRes = rpcConnection.renameFile(srcPath, dstPath);
+ return new RenameNodeFuture(this, src, dst, renameRes);
+ }
+
+ CrailNode _rename(RpcRenameFile renameRes, String src, String dst) throws Exception {
+ if (renameRes.getError() == RpcErrors.ERR_SRC_FILE_NOT_FOUND){
+ LOG.info("rename: " + RpcErrors.messages[renameRes.getError()]);
+ return null;
+ }
+ if (renameRes.getError() == RpcErrors.ERR_DST_PARENT_NOT_FOUND){
+ LOG.info("rename: " + RpcErrors.messages[renameRes.getError()]);
+ return null;
+ }
+ if (renameRes.getError() == RpcErrors.ERR_FILE_EXISTS){
+ LOG.info("rename: " + RpcErrors.messages[renameRes.getError()]);
+ return null;
+ }
+ if (renameRes.getError() != RpcErrors.ERR_OK){
+ LOG.info("rename: " + RpcErrors.messages[renameRes.getError()]);
+ throw new IOException(RpcErrors.messages[renameRes.getError()]);
+ }
+ if (renameRes.getDstParent().getCapacity() < renameRes.getDstFile().getDirOffset() + CrailConstants.DIRECTORY_RECORD){
+ LOG.info("rename: parent capacity does not match dst file offset, capacity " + renameRes.getDstParent().getCapacity() + ", offset " + renameRes.getDstFile().getDirOffset());
+ }
+
+ FileInfo srcParent = renameRes.getSrcParent();
+ FileInfo srcFile = renameRes.getSrcFile();
+ FileInfo dstDir = renameRes.getDstParent();
+ FileInfo dstFile = renameRes.getDstFile();
+
+ BlockInfo srcBlock = renameRes.getSrcBlock();
+ getBlockCache(srcParent.getFd()).put(CoreSubOperation.createKey(srcParent.getFd(), srcFile.getDirOffset()), srcBlock);
+ BlockInfo dirBlock = renameRes.getDstBlock();
+ getBlockCache(dstDir.getFd()).put(CoreSubOperation.createKey(dstDir.getFd(), dstFile.getDirOffset()), dirBlock);
+
+ CoreSyncOperation syncOperationSrc = getSyncOperation(srcParent, srcFile, src, false);
+ CoreSyncOperation syncOperationDst = getSyncOperation(dstDir, dstFile, dst, true);
+
+ blockCache.remove(srcFile.getFd());
+
+ if (CrailConstants.DEBUG){
+ LOG.info("rename: srcname " + src + ", dstname " + dst + ", success");
+ }
+
+ CoreNode node = CoreNode.create(this, dstFile, dst);
+ node.addSyncOperation(syncOperationSrc);
+ node.addSyncOperation(syncOperationDst);
+ return node;
+ }
+
+ public Upcoming<CrailNode> delete(String path, boolean recursive) throws Exception {
+ FileName name = new FileName(path);
+
+ if (CrailConstants.DEBUG){
+ LOG.info("delete: name " + path + ", recursive " + recursive);
+ }
+
+ RpcFuture<RpcDeleteFile> fileRes = rpcConnection.removeFile(name, recursive);
+ return new DeleteNodeFuture(this, path, recursive, fileRes);
+ }
+
+ CrailNode _delete(RpcDeleteFile fileRes, String path, boolean recursive) throws Exception {
+ if (fileRes.getError() == RpcErrors.ERR_HAS_CHILDREN) {
+ LOG.info("delete: " + RpcErrors.messages[fileRes.getError()]);
+ throw new IOException(RpcErrors.messages[fileRes.getError()]);
+ }
+ if (fileRes.getError() != RpcErrors.ERR_OK) {
+ LOG.info("delete: " + RpcErrors.messages[fileRes.getError()]);
+ return null;
+ }
+
+ FileInfo fileInfo = fileRes.getFile();
+ FileInfo dirInfo = fileRes.getParent();
+
+ CoreSyncOperation syncOperation = getSyncOperation(dirInfo, fileInfo, path, false);
+
+ blockCache.remove(fileInfo.getFd());
+
+ if (CrailConstants.DEBUG){
+ LOG.info("delete: name " + path + ", recursive " + recursive + ", success");
+ }
+
+ CoreNode node = CoreNode.create(this, fileInfo, path);
+ node.addSyncOperation(syncOperation);
+ return node;
+ }
+
+ public DirectoryInputStream listEntries(String name) throws Exception {
+ return _listEntries(name, CrailConstants.DIRECTORY_RANDOMIZE);
+ }
+
+ public DirectoryInputStream _listEntries(String name, boolean randomize) throws Exception {
+ FileName directory = new FileName(name);
+
+ if (CrailConstants.DEBUG){
+ LOG.info("getDirectoryList: " + name);
+ }
+
+ RpcGetFile fileRes = rpcConnection.getFile(directory, false).get(CrailConstants.RPC_TIMEOUT, TimeUnit.MILLISECONDS);
+ if (fileRes.getError() != RpcErrors.ERR_OK) {
+ LOG.info("getDirectoryList: " + RpcErrors.messages[fileRes.getError()]);
+ throw new FileNotFoundException(RpcErrors.messages[fileRes.getError()]);
+ }
+
+ FileInfo dirInfo = fileRes.getFile();
+ if (!dirInfo.getType().isContainer()){
+ LOG.info("getDirectoryList: " + RpcErrors.messages[RpcErrors.ERR_FILE_IS_NOT_DIR]);
+ throw new FileNotFoundException(RpcErrors.messages[RpcErrors.ERR_FILE_IS_NOT_DIR]);
+ }
+
+ CoreDirectory dirFile = new CoreDirectory(this, dirInfo, name);
+ DirectoryInputStream inputStream = dirFile.getDirectoryInputStream(randomize);
+ return inputStream;
+ }
+
+ public CrailBlockLocation[] getBlockLocations(String path, long start, long len) throws Exception {
+ if (CrailConstants.DEBUG){
+ LOG.info("location: path " + path + ", start " + start + ", len " + len);
+ }
+
+ if (path == null) {
+ LOG.info("Path null");
+ return null;
+ }
+ if (start < 0 || len < 0) {
+ LOG.info("Start or len invalid");
+ throw new IOException("Invalid start or len parameter");
+ }
+
+
+ FileName name = new FileName(path);
+ long rangeStart = CrailUtils.blockStartAddress(start);
+ long range = start + len - CrailUtils.blockStartAddress(start);
+ long blockCount = range / CrailConstants.BLOCK_SIZE;
+ if (range % CrailConstants.BLOCK_SIZE > 0){
+ blockCount++;
+ }
+ CoreBlockLocation[] blockLocations = new CoreBlockLocation[(int) blockCount];
+ HashMap<Long, DataNodeInfo> dataNodeSet = new HashMap<Long, DataNodeInfo>();
+ HashMap<Long, DataNodeInfo> offset2DataNode = new HashMap<Long, DataNodeInfo>();
+
+ for (long current = CrailUtils.blockStartAddress(start); current < start + len; current += CrailConstants.BLOCK_SIZE){
+ RpcGetLocation getLocationRes = rpcConnection.getLocation(name, current).get(CrailConstants.RPC_TIMEOUT, TimeUnit.MILLISECONDS);
+ if (getLocationRes.getError() != RpcErrors.ERR_OK) {
+ LOG.info("location: " + RpcErrors.messages[getLocationRes.getError()]);
+ throw new IOException(RpcErrors.messages[getLocationRes.getError()]);
+ }
+
+ DataNodeInfo dataNodeInfo = getLocationRes.getBlockInfo().getDnInfo();
+ dataNodeSet.put(dataNodeInfo.key(), dataNodeInfo);
+ CoreBlockLocation location = new CoreBlockLocation();
+ location.setOffset(current);
+ location.setLength(Math.min(start + len - current, CrailConstants.BLOCK_SIZE));
+ long index = (current - rangeStart) / CrailConstants.BLOCK_SIZE;
+ blockLocations[(int) index] = location;
+ offset2DataNode.put(current, dataNodeInfo);
+ }
+
+ //asign an identifier to each data node
+ ArrayList<DataNodeInfo> dataNodeArray = new ArrayList<DataNodeInfo>(dataNodeSet.size());
+ int index = 0;
+ for (DataNodeInfo dn : dataNodeSet.values()){
+ dataNodeArray.add(index, dn);
+ index++;
+ }
+
+ int locationSize = Math.min(CrailConstants.SHADOW_REPLICATION, dataNodeSet.size());
+ int blockIndex = 0;
+ for (int i = 0; i < blockLocations.length; i++){
+ CoreBlockLocation location = blockLocations[i];
+ String[] hosts = new String[locationSize];
+ String[] names = new String[locationSize];
+ String[] topology = new String[locationSize];
+ int[] storageType = new int[locationSize];
+ int[] storageClass = new int[locationSize];
+ int[] locationTiers = new int[locationSize];
+
+ DataNodeInfo dnInfo = offset2DataNode.get(location.getOffset());
+ DataNodeInfo mainDataNode = dataNodeSet.get(dnInfo.key());
+ InetSocketAddress address = CrailUtils.datanodeInfo2SocketAddr(mainDataNode);
+ names[0] = getMappedLocation(address.getAddress().getCanonicalHostName()) + ":" + address.getPort();
+ hosts[0] = getMappedLocation(address.getAddress().getCanonicalHostName());
+ topology[0] = "/default-rack/" + names[0];
+ storageType[0] = mainDataNode.getStorageType();
+ storageClass[0] = mainDataNode.getStorageClass();
+ locationTiers[0] = mainDataNode.getLocationClass();
+ for (int j = 1; j < locationSize; j++){
+ DataNodeInfo replicaDataNode = dataNodeArray.get(blockIndex);
+ address = CrailUtils.datanodeInfo2SocketAddr(replicaDataNode);
+ names[j] = getMappedLocation(address.getAddress().getCanonicalHostName()) + ":" + address.getPort();
+ hosts[j] = getMappedLocation(address.getAddress().getCanonicalHostName());
+ topology[j] = "/default-rack/" + names[j];
+ storageType[j] = replicaDataNode.getStorageType();
+ storageClass[j] = replicaDataNode.getStorageClass();
+ locationTiers[j] = replicaDataNode.getLocationClass();
+ blockIndex = (blockIndex + 1) % dataNodeArray.size();
+ }
+ location.setNames(names);
+ location.setHosts(hosts);
+ location.setTopologyPaths(topology);
+ location.setStorageTypes(storageType);
+ location.setStorageClasses(storageClass);
+ location.setLocationAffinities(locationTiers);
+ }
+
+ return blockLocations;
+ }
+
+ public void dumpNameNode() throws Exception {
+ rpcConnection.dumpNameNode().get(CrailConstants.RPC_TIMEOUT, TimeUnit.MILLISECONDS);
+ }
+
+ public void ping() throws Exception {
+ RpcPing pingRes = rpcConnection.pingNameNode().get(CrailConstants.RPC_TIMEOUT, TimeUnit.MILLISECONDS);
+ if (pingRes.getError() != RpcErrors.ERR_OK) {
+ LOG.info("Ping: " + RpcErrors.messages[pingRes.getError()]);
+ throw new IOException(RpcErrors.messages[pingRes.getError()]);
+ }
+ }
+
+ public CrailBuffer allocateBuffer() throws IOException {
+ return this.bufferCache.getBuffer();
+ }
+
+ public void freeBuffer(CrailBuffer buffer) throws IOException {
+ this.bufferCache.putBuffer(buffer);
+ }
+
+ public int getFsId() {
+ return fsId;
+ }
+
+ public CrailLocationClass getLocationClass() {
+ return localClass;
+ }
+
+ public BufferCheckpoint getBufferCheckpoint() {
+ return bufferCheckpoint;
+ }
+
+ public CrailStatistics getStatistics(){
+ return statistics;
+ }
+
+ public void closeFileSystem() throws Exception {
+ if (!isOpen) {
+ return;
+ }
+
+ LinkedList<CoreInputStream> tmpIn = new LinkedList<CoreInputStream>();
+ for (CoreInputStream stream : openInputStreams.values()) {
+ tmpIn.add(stream);
+ }
+ for (CoreInputStream stream : tmpIn) {
+ stream.close();
+ }
+
+ LinkedList<CoreOutputStream> tmpOut = new LinkedList<CoreOutputStream>();
+ LinkedList<CoreOutputStream> tmpOutDir = new LinkedList<CoreOutputStream>();
+ for (CoreOutputStream stream : openOutputStreams.values()) {
+ if (stream.getFile().getType().isContainer()){
+ tmpOutDir.add(stream);
+ } else {
+ tmpOut.add(stream);
+ }
+ }
+ for (CoreOutputStream stream : tmpOut) {
+ stream.close();
+ }
+ for (CoreOutputStream stream : tmpOutDir) {
+ stream.close();
+ }
+
+ bufferCache.close();
+ datanodeEndpointCache.close();
+ rpcConnection.close();
+ rpcClient.close();
+ this.isOpen = false;
+ }
+
+ public void closeFile(FileInfo fileInfo) throws Exception {
+ if (fileInfo.getToken() > 0){
+ rpcConnection.setFile(fileInfo, true).get(CrailConstants.RPC_TIMEOUT, TimeUnit.MILLISECONDS);
+ }
+ }
+
+ public BufferCache getBufferCache() {
+ return bufferCache;
+ }
+
+ public void purgeCache() {
+ blockCache.purge();
+ nextBlockCache.purge();
+ }
+
+ //-------------------------------------------------------------
+
+ CoreOutputStream getOutputStream(CoreNode file, long writeHint) throws Exception {
+ CoreOutputStream outputStream = new CoreOutputStream(file, streamCounter.incrementAndGet(), writeHint);
+ openOutputStreams.put(outputStream.getStreamId(), outputStream);
+
+ if (CrailConstants.STATISTICS){
+ streamStats.incOpen();
+ streamStats.incOpenOutput();
+ streamStats.incCurrentOutput();
+ streamStats.incMaxOutput();
+ if (file.getType().isDirectory()){
+ streamStats.incOpenOutputDir();
+ }
+ }
+ return outputStream;
+ }
+
+ CoreInputStream getInputStream(CoreNode file, long readHint) throws Exception {
+ CoreInputStream inputStream = new CoreInputStream(file, streamCounter.incrementAndGet(), readHint);
+ openInputStreams.put(inputStream.getStreamId(), inputStream);
+
+ if (CrailConstants.STATISTICS){
+ streamStats.incOpen();
+ streamStats.incOpenInput();
+ streamStats.incCurrentInput();
+ streamStats.incMaxInput();
+ if (file.getType().isDirectory()){
+ streamStats.incOpenInputDir();
+ }
+ }
+ return inputStream;
+ }
+
+ CoreStream unregisterInputStream(CoreInputStream coreStream) {
+ CoreStream stream = this.openInputStreams.remove(coreStream.getStreamId());
+ if (stream != null && CrailConstants.STATISTICS){
+ streamStats.incClose();
+ streamStats.incCloseInput();
+ this.ioStatsIn.mergeStatistics(stream.getCoreStatistics());
+ streamStats.decCurrentInput();
+ if (stream.getFile().getType().isDirectory()){
+ streamStats.incCloseInputDir();
+ }
+ }
+
+ return stream;
+ }
+
+ CoreStream unregisterOutputStream(CoreOutputStream coreStream) {
+ CoreStream stream = this.openOutputStreams.remove(coreStream.getStreamId());
+ if (stream != null && CrailConstants.STATISTICS){
+ streamStats.incClose();
+ streamStats.incCloseOutput();
+ this.ioStatsOut.mergeStatistics(stream.getCoreStatistics());
+ streamStats.decCurrentOutput();
+ if (stream.getFile().getType().isDirectory()){
+ streamStats.incCloseOutputDir();
+ }
+ }
+
+ return stream;
+ }
+
+ FileBlockCache getBlockCache(long fd){
+ return blockCache.getFileBlockCache(fd);
+ }
+
+ FileNextBlockCache getNextBlockCache(long fd){
+ return nextBlockCache.getFileBlockCache(fd);
+ }
+
+ RpcConnection getNamenodeClientRpc() {
+ return rpcConnection;
+ }
+
+ EndpointCache getDatanodeEndpointCache() {
+ return datanodeEndpointCache;
+ }
+
+ String getMappedLocation(String hostname){
+ String mappedValue = locationMap.get(hostname);
+ return mappedValue != null ? mappedValue : hostname;
+ }
+
+ CoreSyncOperation getSyncOperation(FileInfo dirInfo, FileInfo fileInfo, String path, boolean valid) throws Exception{
+ long adjustedCapacity = fileInfo.getDirOffset()*CrailConstants.DIRECTORY_RECORD + CrailConstants.DIRECTORY_RECORD;
+ dirInfo.setCapacity(Math.max(dirInfo.getCapacity(), adjustedCapacity));
+ CoreDirectory dirFile = new CoreDirectory(this, dirInfo, CrailUtils.getParent(path));
+ DirectoryOutputStream stream = dirFile.getDirectoryOutputStream();
+ DirectoryRecord record = new DirectoryRecord(valid, path);
+ Future<CrailResult> future = stream.writeRecord(record, fileInfo.getDirOffset());
+ CoreSyncOperation syncOperation = new CoreSyncOperation(stream, future);
+ return syncOperation;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-crail/blob/32f8ead2/client/src/main/java/org/apache/crail/core/CoreIOStatistics.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/crail/core/CoreIOStatistics.java b/client/src/main/java/org/apache/crail/core/CoreIOStatistics.java
new file mode 100644
index 0000000..03d22e3
--- /dev/null
+++ b/client/src/main/java/org/apache/crail/core/CoreIOStatistics.java
@@ -0,0 +1,252 @@
+/*
+ * Crail: A Multi-tiered Distributed Direct Access File System
+ *
+ * Author: Patrick Stuedi <st...@zurich.ibm.com>
+ *
+ * Copyright (C) 2016, IBM Corporation
+ *
+ * Licensed 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 org.apache.crail.core;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.crail.CrailStatistics;
+import org.apache.crail.CrailStatistics.StatisticsProvider;
+
+public class CoreIOStatistics implements CrailStatistics.StatisticsProvider {
+ private String mode;
+ private AtomicLong totalOps;
+ private AtomicLong localOps;
+ private AtomicLong remoteOps;
+ private AtomicLong localDirOps;
+ private AtomicLong remoteDirOps;
+ private AtomicLong cachedOps;
+ private AtomicLong nonblockingOps;
+ private AtomicLong blockingOps;
+ private AtomicLong prefetchedOps;
+ private AtomicLong prefetchedBlockingOps;
+ private AtomicLong prefetchedNonblockingOps;
+ private AtomicLong opLen;
+ private AtomicLong capacity;
+ private AtomicLong totalStreams;
+ private AtomicLong totalSeeks;
+
+ public CoreIOStatistics(String mode){
+ this.mode = mode;
+ this.totalOps = new AtomicLong(0);
+ this.localOps = new AtomicLong(0);
+ this.remoteOps = new AtomicLong(0);
+ this.localDirOps = new AtomicLong(0);
+ this.remoteDirOps = new AtomicLong(0);
+ this.cachedOps = new AtomicLong(0);
+ this.nonblockingOps = new AtomicLong(0);
+ this.blockingOps = new AtomicLong(0);
+ this.prefetchedOps = new AtomicLong(0);
+ this.prefetchedBlockingOps = new AtomicLong(0);
+ this.prefetchedNonblockingOps = new AtomicLong(0);
+ this.opLen = new AtomicLong(0);
+ this.capacity = new AtomicLong(0);
+ this.totalStreams = new AtomicLong(0);
+ this.totalSeeks = new AtomicLong(0);
+ resetStatistics();
+ }
+
+ @Override
+ public String providerName() {
+ return mode;
+ }
+
+ @Override
+ public String printStatistics() {
+ return "total " + getTotalOps() + ", localOps " + getLocalOps() + ", remoteOps " + getRemoteOps() + ", localDirOps " + getLocalDirOps() + ", remoteDirOps " + getRemoteDirOps() +
+ ", cached " + getCachedOps() + ", nonBlocking " + getNonblockingOps() + ", blocking " + getBlockingOps() +
+ ", prefetched " + getPrefetchedOps() + ", prefetchedNonBlocking " + getPrefetchedNonblockingOps() + ", prefetchedBlocking " + getPrefetchedBlockingOps() +
+ ", capacity " + getCapacity() + ", totalStreams " + getTotalStreams() + ", avgCapacity " + getAvgCapacity() +
+ ", avgOpLen " + getAvgOpLen();
+ }
+
+ public void resetStatistics(){
+ this.totalOps.set(0);
+ this.localOps.set(0);
+ this.remoteOps.set(0);
+ this.localDirOps.set(0);
+ this.remoteDirOps.set(0);
+ this.cachedOps.set(0);
+ this.nonblockingOps.set(0);
+ this.blockingOps.set(0);
+ this.prefetchedOps.set(0);
+ this.prefetchedBlockingOps.set(0);
+ this.prefetchedNonblockingOps.set(0);
+ this.opLen.set(0);
+ this.capacity.set(0);
+ this.totalStreams.set(0);
+ this.totalSeeks.set(0);
+ }
+
+ public void mergeStatistics(StatisticsProvider provider){
+ if (provider instanceof CoreIOStatistics){
+ CoreIOStatistics newProvider = (CoreIOStatistics) provider;
+ totalOps.addAndGet(newProvider.getTotalOps());
+ localOps.addAndGet(newProvider.getLocalOps());
+ remoteOps.addAndGet(newProvider.getRemoteOps());
+ localDirOps.addAndGet(newProvider.getLocalDirOps());
+ remoteDirOps.addAndGet(newProvider.getRemoteDirOps());
+ cachedOps.addAndGet(newProvider.getCachedOps());
+ nonblockingOps.addAndGet(newProvider.getNonblockingOps());
+ blockingOps.addAndGet(newProvider.getBlockingOps());
+ prefetchedOps.addAndGet(newProvider.getPrefetchedOps());
+ prefetchedNonblockingOps.addAndGet(newProvider.getPrefetchedNonblockingOps());
+ prefetchedBlockingOps.addAndGet(newProvider.getPrefetchedBlockingOps());
+ opLen.addAndGet(newProvider.getOpLen());
+ capacity.addAndGet(newProvider.getCapacity());
+ totalSeeks.addAndGet(newProvider.getTotalSeeks());
+ totalStreams.incrementAndGet();
+ }
+ }
+
+ public long getTotalOps() {
+ return totalOps.get();
+ }
+
+ void incTotalOps(long opLen) {
+ this.totalOps.incrementAndGet();
+ this.opLen.addAndGet(opLen);
+ }
+
+ public long getLocalOps(){
+ return localOps.get();
+ }
+
+ public void incLocalOps() {
+ localOps.incrementAndGet();
+ }
+
+ public long getRemoteOps(){
+ return remoteOps.get();
+ }
+
+ public void incRemoteOps() {
+ remoteOps.incrementAndGet();
+ }
+
+ public long getLocalDirOps(){
+ return localDirOps.get();
+ }
+
+ public void incLocalDirOps() {
+ localDirOps.incrementAndGet();
+ }
+
+ public long getRemoteDirOps(){
+ return remoteDirOps.get();
+ }
+
+ public void incRemoteDirOps() {
+ remoteDirOps.incrementAndGet();
+ }
+
+ public long getCachedOps() {
+ return cachedOps.get();
+ }
+
+ void incCachedOps() {
+ this.cachedOps.incrementAndGet();
+ }
+
+ public long getNonblockingOps() {
+ return nonblockingOps.get();
+ }
+
+ void incNonblockingOps() {
+ this.nonblockingOps.incrementAndGet();
+ }
+
+ public long getBlockingOps() {
+ return blockingOps.get();
+ }
+
+ void incBlockingOps() {
+ this.blockingOps.incrementAndGet();
+ }
+
+ public long getPrefetchedOps() {
+ return prefetchedOps.get();
+ }
+
+ void incPrefetchedOps() {
+ this.prefetchedOps.incrementAndGet();
+ }
+
+ public long getPrefetchedBlockingOps() {
+ return prefetchedBlockingOps.get();
+ }
+
+ void incPrefetchedBlockingOps() {
+ this.prefetchedBlockingOps.incrementAndGet();
+ }
+
+ public long getPrefetchedNonblockingOps() {
+ return prefetchedNonblockingOps.get();
+ }
+
+ void incPrefetchedNonblockingOps() {
+ this.prefetchedNonblockingOps.incrementAndGet();
+ }
+
+ public long getOpLen() {
+ return opLen.get();
+ }
+
+ public long getAvgOpLen(){
+ long _avg = 0;
+ long _totalOps = totalOps.get();
+ long _opLen = opLen.get();
+ if (_totalOps > 0){
+ _avg = _opLen / _totalOps;
+ }
+ return _avg;
+ }
+
+ public void setCapacity(long capacity){
+ this.capacity.set(capacity);
+ }
+
+ public long getCapacity(){
+ return capacity.get();
+ }
+
+ public long getAvgCapacity(){
+ long _avg = 0;
+ long _capacity = capacity.get();
+ long _totalStreams = totalStreams.get();
+ if (_totalStreams > 0){
+ _avg = _capacity / _totalStreams;
+ }
+ return _avg;
+ }
+
+ public long getTotalStreams(){
+ return totalStreams.get();
+ }
+
+ public long getTotalSeeks() {
+ return totalSeeks.get();
+ }
+
+ void incTotalSeekds() {
+ this.totalSeeks.incrementAndGet();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-crail/blob/32f8ead2/client/src/main/java/org/apache/crail/core/CoreInputStream.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/crail/core/CoreInputStream.java b/client/src/main/java/org/apache/crail/core/CoreInputStream.java
new file mode 100644
index 0000000..f80b7d8
--- /dev/null
+++ b/client/src/main/java/org/apache/crail/core/CoreInputStream.java
@@ -0,0 +1,132 @@
+/*
+ * Crail: A Multi-tiered Distributed Direct Access File System
+ *
+ * Author: Patrick Stuedi <st...@zurich.ibm.com>
+ *
+ * Copyright (C) 2016, IBM Corporation
+ *
+ * Licensed 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 org.apache.crail.core;
+
+import java.io.IOException;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.crail.CrailBuffer;
+import org.apache.crail.CrailInputStream;
+import org.apache.crail.CrailResult;
+import org.apache.crail.conf.CrailConstants;
+import org.apache.crail.metadata.BlockInfo;
+import org.apache.crail.storage.StorageEndpoint;
+import org.apache.crail.storage.StorageFuture;
+import org.apache.crail.utils.CrailImmediateOperation;
+import org.apache.crail.utils.CrailUtils;
+import org.slf4j.Logger;
+
+public class CoreInputStream extends CoreStream implements CrailInputStream {
+ private static final Logger LOG = CrailUtils.getLogger();
+ private AtomicLong inFlight;
+ private long readHint;
+ private CrailImmediateOperation noOp;
+ private boolean open;
+
+ public CoreInputStream(CoreNode file, long streamId, long readHint) throws Exception {
+ super(file, streamId, 0);
+ this.inFlight = new AtomicLong(0);
+ this.readHint = Math.max(0, Math.min(file.getCapacity(), readHint));
+ this.noOp = new CrailImmediateOperation(0);
+ this.open = true;
+ if (CrailConstants.DEBUG){
+ LOG.info("CoreInputStream: open, path " + file.getPath() + ", fd " + file.getFd() + ", streamId " + streamId + ", isDir " + file.getType().isDirectory() + ", readHint " + this.readHint);
+ }
+ }
+
+ final public Future<CrailResult> read(CrailBuffer dataBuf) throws Exception {
+ if (!open) {
+ throw new IOException("stream already closed");
+ }
+ if (dataBuf.remaining() <= 0) {
+ return noOp;
+ }
+ if (position() >= getFile().getCapacity()) {
+ return null;
+ }
+
+ long fileAvailable = available();
+ long bufAvailable = (long) dataBuf.remaining();
+ if (fileAvailable < bufAvailable){
+ int _fileAvailable = (int) fileAvailable;
+ dataBuf.limit(dataBuf.position() + _fileAvailable);
+ }
+
+ inFlight.incrementAndGet();
+ CoreDataOperation future = dataOperation(dataBuf);
+ if (position() < readHint){
+ prefetchMetadata();
+ }
+ if (future.isSynchronous()){
+ future.get();
+ }
+ return future;
+ }
+
+ final public int available() {
+ long available = Math.max(0, getFile().getCapacity() - position());
+ long maxint = (long) Integer.MAX_VALUE;
+ if (available < maxint){
+ return (int) available;
+ } else {
+ return Integer.MAX_VALUE;
+ }
+ }
+
+ final public void seek(long pos) throws IOException {
+ long oldPos = position();
+ super.seek(pos);
+ long newPos = position();
+ if (oldPos != newPos){
+ this.readHint = 0;
+ }
+ }
+
+ public void close() throws Exception {
+ if (!open){
+ return;
+ }
+ if (inFlight.get() != 0){
+ LOG.info("Cannot close, pending operations, opcount " + inFlight.get() + ", path " + getFile().getPath());
+ throw new IOException("Cannot close, pending operations, opcount " + inFlight.get());
+ }
+
+ updateIOStats();
+ node.closeInputStream(this);
+ open = false;
+ if (CrailConstants.DEBUG){
+ LOG.info("CoreInputStream, close, path " + this.getFile().getPath() + ", fd " + getFile().getFd() + ", streamId " + getStreamId());
+ }
+ }
+
+ // --------------------------
+
+ StorageFuture trigger(StorageEndpoint endpoint, CoreSubOperation opDesc, CrailBuffer buffer, BlockInfo block) throws Exception {
+ StorageFuture future = endpoint.read(buffer, block, opDesc.getBlockOffset());
+ return future;
+ }
+
+ void update(long newCapacity) {
+ inFlight.decrementAndGet();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-crail/blob/32f8ead2/client/src/main/java/org/apache/crail/core/CoreMetaDataOperation.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/crail/core/CoreMetaDataOperation.java b/client/src/main/java/org/apache/crail/core/CoreMetaDataOperation.java
new file mode 100644
index 0000000..0a4babd
--- /dev/null
+++ b/client/src/main/java/org/apache/crail/core/CoreMetaDataOperation.java
@@ -0,0 +1,279 @@
+/*
+ * Crail: A Multi-tiered Distributed Direct Access File System
+ *
+ * Author: Patrick Stuedi <st...@zurich.ibm.com>
+ *
+ * Copyright (C) 2016, IBM Corporation
+ *
+ * Licensed 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 org.apache.crail.core;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.crail.CrailNode;
+import org.apache.crail.CrailNodeType;
+import org.apache.crail.Upcoming;
+import org.apache.crail.conf.CrailConstants;
+import org.apache.crail.rpc.RpcCreateFile;
+import org.apache.crail.rpc.RpcDeleteFile;
+import org.apache.crail.rpc.RpcErrors;
+import org.apache.crail.rpc.RpcGetFile;
+import org.apache.crail.rpc.RpcRenameFile;
+import org.apache.crail.rpc.RpcVoid;
+
+public abstract class CoreMetaDataOperation<R,T> implements Upcoming<T> {
+ protected static int RPC_PENDING = 0;
+ protected static int RPC_DONE = 1;
+ protected static int RPC_ERROR = 2;
+
+ private AtomicInteger status;
+ protected Future<R> rpcResult;
+ private T finalResult;
+ private Exception exception;
+
+ abstract T process(R tmp) throws Exception;
+
+ public CoreMetaDataOperation(Future<R> result){
+ this.rpcResult = result;
+ this.finalResult = null;
+ this.status = new AtomicInteger(RPC_PENDING);
+ this.exception = null;
+ }
+
+ @Override
+ public boolean isDone() {
+ if (status.get() == RPC_PENDING){
+ try {
+ if (rpcResult.isDone()){
+ R tmp = rpcResult.get();
+ finalResult = process(tmp);
+ status.set(RPC_DONE);
+ }
+ } catch (Exception e) {
+ status.set(RPC_ERROR);
+ this.exception = e;
+ }
+ }
+
+ return status.get() > 0;
+ }
+
+ @Override
+ public T get() throws InterruptedException, ExecutionException {
+ if (this.exception != null){
+ throw new ExecutionException(exception);
+ }
+
+ if (status.get() == RPC_PENDING){
+ try {
+ R tmp = rpcResult.get();
+ finalResult = process(tmp);
+ status.set(RPC_DONE);
+ } catch (Exception e) {
+ status.set(RPC_ERROR);
+ this.exception = e;
+ }
+ }
+
+ if (status.get() == RPC_DONE){
+ return finalResult;
+ } else if (status.get() == RPC_PENDING){
+ throw new InterruptedException("RPC timeout");
+ } else if (exception != null) {
+ throw new ExecutionException(exception);
+ } else {
+ throw new InterruptedException("RPC error");
+ }
+ }
+
+ @Override
+ public T get(long timeout, TimeUnit unit) throws InterruptedException,
+ ExecutionException, TimeoutException {
+ if (this.exception != null){
+ throw new ExecutionException(exception);
+ }
+
+ if (status.get() == RPC_PENDING){
+ try {
+ R tmp = rpcResult.get(CrailConstants.DATA_TIMEOUT, TimeUnit.MILLISECONDS);
+ finalResult = process(tmp);
+ status.set(RPC_DONE);
+ } catch (Exception e) {
+ status.set(RPC_ERROR);
+ this.exception = e;
+ }
+ }
+
+ if (status.get() == RPC_DONE){
+ return finalResult;
+ } else if (status.get() == RPC_PENDING){
+ throw new InterruptedException("RPC timeout");
+ } else if (exception != null) {
+ throw new ExecutionException(exception);
+ } else {
+ throw new InterruptedException("RPC error");
+ }
+ }
+
+ public T early() throws Exception {
+ return this.get();
+ }
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ return false;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return false;
+ }
+}
+
+class CreateNodeFuture extends CoreMetaDataOperation<RpcCreateFile, CrailNode> {
+ private CoreFileSystem fs;
+ private String path;
+ private CrailNodeType type;
+
+ public CreateNodeFuture(CoreFileSystem fs, String path, CrailNodeType type, Future<RpcCreateFile> fileRes) {
+ super(fileRes);
+ this.fs = fs;
+ this.path = path;
+ this.type = type;
+ }
+
+ @Override
+ CrailNode process(RpcCreateFile response) throws Exception {
+ return fs._createNode(path, type, response);
+ }
+
+ @Override
+ public CrailNode early() throws Exception {
+ switch(type){
+ case DATAFILE:
+ return new CoreEarlyFile(fs, path, type, this);
+ case DIRECTORY:
+ case MULTIFILE:
+ return null;
+ default:
+ return super.early();
+ }
+ }
+
+}
+
+class LookupNodeFuture extends CoreMetaDataOperation<RpcGetFile, CrailNode> {
+ private String path;
+ private CoreFileSystem fs;
+
+ public LookupNodeFuture(CoreFileSystem fs, String path, Future<RpcGetFile> fileRes) {
+ super(fileRes);
+ this.fs = fs;
+ this.path = path;
+ }
+
+ @Override
+ CrailNode process(RpcGetFile tmp) throws Exception {
+ return fs._lookupNode(tmp, path);
+ }
+
+}
+
+class DeleteNodeFuture extends CoreMetaDataOperation<RpcDeleteFile, CrailNode> {
+ private String path;
+ private boolean recursive;
+ private CoreFileSystem fs;
+
+ public DeleteNodeFuture(CoreFileSystem fs, String path, boolean recursive, Future<RpcDeleteFile> fileRes) {
+ super(fileRes);
+ this.fs = fs;
+ this.path = path;
+ this.recursive = recursive;
+ }
+
+ @Override
+ CrailNode process(RpcDeleteFile tmp) throws Exception {
+ return fs._delete(tmp, path, recursive);
+ }
+}
+
+class RenameNodeFuture extends CoreMetaDataOperation<RpcRenameFile, CrailNode> {
+ private String src;
+ private String dst;
+ private CoreFileSystem fs;
+
+ public RenameNodeFuture(CoreFileSystem fs, String src, String dst, Future<RpcRenameFile> fileRes) {
+ super(fileRes);
+ this.fs = fs;
+ this.src = src;
+ this.dst = dst;
+ }
+
+ @Override
+ CrailNode process(RpcRenameFile tmp) throws Exception {
+ return fs._rename(tmp, src, dst);
+ }
+}
+
+class SyncNodeFuture extends CoreMetaDataOperation<RpcVoid, Void> {
+
+ public SyncNodeFuture(Future<RpcVoid> fileRes) {
+ super(fileRes);
+ }
+
+ @Override
+ Void process(RpcVoid tmp) throws Exception {
+ if (tmp.getError() != RpcErrors.ERR_OK){
+ throw new Exception("sync: " + RpcErrors.messages[tmp.getError()]);
+ }
+ return null;
+ }
+}
+
+class NoOperation implements Future<Void> {
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ return false;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return false;
+ }
+
+ @Override
+ public boolean isDone() {
+ return true;
+ }
+
+ @Override
+ public Void get() throws InterruptedException, ExecutionException {
+ return null;
+ }
+
+ @Override
+ public Void get(long timeout, TimeUnit unit) throws InterruptedException,
+ ExecutionException, TimeoutException {
+ return null;
+ }
+}
+
+
http://git-wip-us.apache.org/repos/asf/incubator-crail/blob/32f8ead2/client/src/main/java/org/apache/crail/core/CoreNode.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/crail/core/CoreNode.java b/client/src/main/java/org/apache/crail/core/CoreNode.java
new file mode 100644
index 0000000..57cc086
--- /dev/null
+++ b/client/src/main/java/org/apache/crail/core/CoreNode.java
@@ -0,0 +1,143 @@
+/*
+ * Crail: A Multi-tiered Distributed Direct Access File System
+ *
+ * Author: Patrick Stuedi <st...@zurich.ibm.com>
+ *
+ * Copyright (C) 2016, IBM Corporation
+ *
+ * Licensed 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 org.apache.crail.core;
+
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.apache.crail.CrailBlockLocation;
+import org.apache.crail.CrailKeyValue;
+import org.apache.crail.CrailMultiFile;
+import org.apache.crail.CrailNode;
+import org.apache.crail.CrailNodeType;
+import org.apache.crail.CrailTable;
+import org.apache.crail.metadata.FileInfo;
+
+public class CoreNode implements CrailNode {
+ protected CoreFileSystem fs;
+ protected FileInfo fileInfo;
+ protected String path;
+ private LinkedBlockingQueue<CoreSyncOperation> syncOperations;
+
+ public static CoreNode create(CoreFileSystem fs, FileInfo fileInfo, String path) {
+ if (fileInfo.getType().isContainer()){
+ return new CoreDirectory(fs, fileInfo, path);
+ } else {
+ return new CoreFile(fs, fileInfo, path);
+ }
+ }
+
+ protected CoreNode(CoreFileSystem fs, FileInfo fileInfo, String path){
+ this.fs = fs;
+ this.fileInfo = fileInfo;
+ this.path = path;
+ this.syncOperations = new LinkedBlockingQueue<CoreSyncOperation>();
+ }
+
+ @Override
+ public CoreFileSystem getFileSystem() {
+ return fs;
+ }
+
+ @Override
+ public String getPath() {
+ return path;
+ }
+
+ public long getModificationTime() {
+ return fileInfo.getModificationTime();
+ }
+
+ public long getCapacity() {
+ return fileInfo.getCapacity();
+ }
+
+ public CrailNodeType getType() {
+ return fileInfo.getType();
+ }
+
+ public long getFd() {
+ return fileInfo.getFd();
+ }
+
+ @Override
+ public CoreNode syncDir() throws Exception {
+ while(!syncOperations.isEmpty()){
+ CoreSyncOperation syncOp = syncOperations.poll();
+ syncOp.close();
+ }
+ return this;
+ }
+
+ public CoreFile asFile() throws Exception {
+ throw new Exception("Type of file unclear");
+ }
+
+ public CoreDirectory asContainer() throws Exception {
+ throw new Exception("Type of file unclear");
+ }
+
+ public CoreDirectory asDirectory() throws Exception {
+ throw new Exception("Type of file unclear");
+ }
+
+ public CrailMultiFile asMultiFile() throws Exception {
+ throw new Exception("Type of file unclear");
+ }
+
+ public CrailTable asTable() throws Exception {
+ throw new Exception("Type of file unclear");
+ }
+
+ public CrailKeyValue asKeyValue() throws Exception {
+ throw new Exception("Type of file unclear");
+ }
+
+ public CrailBlockLocation[] getBlockLocations(long start, long len) throws Exception {
+ return fs.getBlockLocations(path, start, len);
+ }
+
+ protected CoreInputStream getInputStream(long readHint) throws Exception{
+ return fs.getInputStream(this, readHint);
+ }
+
+ CoreOutputStream getOutputStream(long writeHint) throws Exception {
+ return fs.getOutputStream(this, writeHint);
+ }
+
+ void closeInputStream(CoreInputStream coreStream) throws Exception {
+ fs.unregisterInputStream(coreStream);
+ }
+
+ void closeOutputStream(CoreOutputStream coreStream) throws Exception {
+ syncDir();
+ fs.unregisterOutputStream(coreStream);
+ }
+
+ FileInfo getFileInfo(){
+ return fileInfo;
+ }
+
+ void addSyncOperation(CoreSyncOperation operation){
+ this.syncOperations.add(operation);
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-crail/blob/32f8ead2/client/src/main/java/org/apache/crail/core/CoreOutputStream.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/crail/core/CoreOutputStream.java b/client/src/main/java/org/apache/crail/core/CoreOutputStream.java
new file mode 100644
index 0000000..6772780
--- /dev/null
+++ b/client/src/main/java/org/apache/crail/core/CoreOutputStream.java
@@ -0,0 +1,117 @@
+/*
+ * Crail: A Multi-tiered Distributed Direct Access File System
+ *
+ * Author: Patrick Stuedi <st...@zurich.ibm.com>
+ *
+ * Copyright (C) 2016, IBM Corporation
+ *
+ * Licensed 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 org.apache.crail.core;
+
+import java.io.IOException;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.crail.CrailBuffer;
+import org.apache.crail.CrailOutputStream;
+import org.apache.crail.CrailResult;
+import org.apache.crail.conf.CrailConstants;
+import org.apache.crail.metadata.BlockInfo;
+import org.apache.crail.storage.StorageEndpoint;
+import org.apache.crail.storage.StorageFuture;
+import org.apache.crail.utils.CrailImmediateOperation;
+import org.apache.crail.utils.CrailUtils;
+import org.slf4j.Logger;
+
+public class CoreOutputStream extends CoreStream implements CrailOutputStream {
+ private static final Logger LOG = CrailUtils.getLogger();
+ private AtomicLong inFlight;
+ private long writeHint;
+ private CrailImmediateOperation noOp;
+ private boolean open;
+
+ public CoreOutputStream(CoreNode file, long streamId, long writeHint) throws Exception {
+ super(file, streamId, file.getCapacity());
+ this.writeHint = Math.max(0, writeHint);
+ this.inFlight = new AtomicLong(0);
+ this.noOp = new CrailImmediateOperation(0);
+ this.open = true;
+ if (CrailConstants.DEBUG){
+ LOG.info("CoreOutputStream, open, path " + file.getPath() + ", fd " + file.getFd() + ", streamId " + streamId + ", isDir " + file.getType().isDirectory() + ", writeHint " + this.writeHint);
+ }
+ }
+
+ final public Future<CrailResult> write(CrailBuffer dataBuf) throws Exception {
+ if (!open) {
+ throw new IOException("Stream closed, cannot write");
+ }
+ if (dataBuf.remaining() <= 0) {
+ return noOp;
+ }
+
+ inFlight.incrementAndGet();
+ CoreDataOperation future = dataOperation(dataBuf);
+ if (position() < writeHint){
+ prefetchMetadata();
+ }
+ if (future.isSynchronous()){
+ future.get();
+ }
+ return future;
+ }
+
+ final public long getWriteHint() {
+ return this.writeHint;
+ }
+
+ public Future<Void> sync() throws IOException {
+ if (inFlight.get() != 0){
+ LOG.info("Cannot sync, pending operations, opcount " + inFlight.get());
+ throw new IOException("Cannot close, pending operations, opcount " + inFlight.get());
+ }
+ return super.sync();
+ }
+
+ public void close() throws Exception {
+ if (!open){
+ return;
+ }
+ if (inFlight.get() != 0){
+ LOG.info("Cannot close, pending operations, opcount " + inFlight.get() + ", path " + getFile().getPath());
+ throw new IOException("Cannot close, pending operations, opcount " + inFlight.get() + ", fd " + getFile().getFd() + ", streamId " + getStreamId() + ", capacity " + getFile().getCapacity());
+ }
+
+ sync().get();
+ updateIOStats();
+ node.closeOutputStream(this);
+ open = false;
+ if (CrailConstants.DEBUG){
+ LOG.info("CoreOutputStream, close, path " + this.getFile().getPath() + ", fd " + getFile().getFd() + ", streamId " + getStreamId() + ", capacity " + getFile().getCapacity());
+ }
+ }
+
+ // ----------------------
+
+ StorageFuture trigger(StorageEndpoint endpoint, CoreSubOperation opDesc, CrailBuffer buffer, BlockInfo block) throws Exception {
+ StorageFuture dataFuture = endpoint.write(buffer, block, opDesc.getBlockOffset());
+ return dataFuture;
+ }
+
+ synchronized void update(long newCapacity) {
+ inFlight.decrementAndGet();
+ setCapacity(newCapacity);
+ }
+}