| /* |
| * |
| * Licensed to the Apache Software Foundation (ASF) 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 org.apache.crail.storage.nvmf; |
| |
| import com.ibm.jnvmf.*; |
| import org.apache.crail.conf.CrailConfiguration; |
| import org.apache.crail.storage.StorageResource; |
| import org.apache.crail.storage.StorageServer; |
| import org.apache.crail.utils.CrailUtils; |
| import org.slf4j.Logger; |
| |
| import java.io.IOException; |
| import java.net.InetSocketAddress; |
| import java.util.List; |
| |
| public class NvmfStorageServer implements StorageServer { |
| private static final Logger LOG = CrailUtils.getLogger(); |
| |
| private boolean isAlive; |
| private long alignedSize; |
| private long address; |
| private boolean initialized = false; |
| private Controller controller; |
| |
| public NvmfStorageServer() {} |
| |
| public void init(CrailConfiguration crailConfiguration, String[] args) throws Exception { |
| if (initialized) { |
| throw new IOException("NvmfStorageTier already initialized"); |
| } |
| initialized = true; |
| NvmfStorageConstants.parseCmdLine(crailConfiguration, args); |
| |
| Nvme nvme; |
| if (NvmfStorageConstants.HOST_NQN == null) { |
| nvme = new Nvme(); |
| } else { |
| nvme = new Nvme(NvmfStorageConstants.HOST_NQN); |
| } |
| |
| NvmfTransportId transportId = new NvmfTransportId( |
| new InetSocketAddress(NvmfStorageConstants.IP_ADDR, NvmfStorageConstants.PORT), |
| NvmfStorageConstants.NQN); |
| controller = nvme.connect(transportId); |
| controller.getControllerConfiguration().setEnable(true); |
| controller.syncConfiguration(); |
| controller.waitUntilReady(); |
| |
| List<Namespace> namespaces = controller.getActiveNamespaces(); |
| Namespace namespace = null; |
| for (Namespace n : namespaces) { |
| if (n.getIdentifier().equals(NvmfStorageConstants.NAMESPACE)) { |
| namespace = n; |
| break; |
| } |
| } |
| if (namespace == null) { |
| throw new IllegalArgumentException("No namespace with id " + NvmfStorageConstants.NAMESPACE + |
| " at controller " + transportId.toString()); |
| } |
| IdentifyNamespaceData namespaceData = namespace.getIdentifyNamespaceData(); |
| LbaFormat lbaFormat = namespaceData.getFormattedLbaSize(); |
| int dataSize = lbaFormat.getLbaDataSize().toInt(); |
| long namespaceSize = dataSize * namespaceData.getNamespaceCapacity(); |
| alignedSize = namespaceSize - (namespaceSize % NvmfStorageConstants.ALLOCATION_SIZE); |
| address = 0; |
| |
| isAlive = true; |
| } |
| |
| @Override |
| public void printConf(Logger log) { |
| NvmfStorageConstants.printConf(log); |
| } |
| |
| public void run() { |
| LOG.info("NnvmfStorageServer started with NVMf target " + getAddress()); |
| while (isAlive) { |
| try { |
| Thread.sleep(NvmfStorageConstants.KEEP_ALIVE_INTERVAL_MS); |
| controller.keepAlive(); |
| } catch (Exception e) { |
| // if StorageServer is still marked as running output stacktrace |
| // otherwise this is expected behaviour |
| if(this.isAlive){ |
| e.printStackTrace(); |
| } |
| } |
| } |
| } |
| |
| @Override |
| public StorageResource allocateResource() throws Exception { |
| StorageResource resource = null; |
| |
| if (alignedSize > 0){ |
| LOG.info("new block, length " + NvmfStorageConstants.ALLOCATION_SIZE); |
| LOG.debug("block stag 0, address " + address + ", length " + NvmfStorageConstants.ALLOCATION_SIZE); |
| alignedSize -= NvmfStorageConstants.ALLOCATION_SIZE; |
| resource = StorageResource.createResource(address, NvmfStorageConstants.ALLOCATION_SIZE, 0); |
| address += NvmfStorageConstants.ALLOCATION_SIZE; |
| } |
| |
| return resource; |
| } |
| |
| @Override |
| public InetSocketAddress getAddress() { |
| return new InetSocketAddress(NvmfStorageConstants.IP_ADDR, NvmfStorageConstants.PORT); |
| } |
| |
| @Override |
| public boolean isAlive() { |
| return isAlive; |
| } |
| |
| public void prepareToShutDown(){ |
| |
| LOG.info("Preparing Nvmf-Storage server for shutdown"); |
| |
| this.isAlive = false; |
| |
| // stop jnvmf controller |
| try { |
| this.controller.free(); |
| } catch(Exception e) { |
| e.printStackTrace(); |
| } |
| } |
| } |