/* * 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 tachyon.worker; import java.io.IOException; import java.net.URI; import java.util.ArrayList; import org.apache.log4j.Logger; import com.mellanox.jxio.EventName; import com.mellanox.jxio.EventQueueHandler; import com.mellanox.jxio.EventReason; import com.mellanox.jxio.Msg; import com.mellanox.jxio.MsgPool; import com.mellanox.jxio.ServerPortal; import com.mellanox.jxio.ServerSession; import com.mellanox.jxio.ServerSession.SessionKey; import com.mellanox.jxio.WorkerCache.Worker; import com.mellanox.jxio.exceptions.JxioGeneralException; import com.mellanox.jxio.exceptions.JxioSessionClosedException; import tachyon.Constants; import tachyon.Users; public class DataServer implements Runnable { private static final Logger LOG = Logger.getLogger(Constants.LOGGER_TYPE); // The blocks locker manager. private final BlocksLocker mBlocksLocker; private final EventQueueHandler eqh; private final ServerPortal listener; private ArrayList<MsgPool> msgPools = new ArrayList<MsgPool>(); private final int numMsgPoolBuffers = 500; class EqhCallbacks implements EventQueueHandler.Callbacks { private final DataServer outer = DataServer.this; private final int numMsgs; private final int inMsgSize; private final int outMsgSize; public EqhCallbacks(int msgs, int in, int out) { numMsgs = msgs; inMsgSize = in; outMsgSize = out; } public MsgPool getAdditionalMsgPool(int in, int out) { MsgPool mp = new MsgPool(numMsgs, inMsgSize, outMsgSize); outer.msgPools.add(mp); return mp; } } public DataServer(URI uri, WorkerStorage workerStorage) { mBlocksLocker = new BlocksLocker(workerStorage, Users.sDATASERVER_USER_ID); MsgPool pool = new MsgPool(numMsgPoolBuffers, 0, 64 * 1024); msgPools.add(pool); eqh = new EventQueueHandler(new EqhCallbacks(numMsgPoolBuffers, 0, 64 * 1024)); eqh.bindMsgPool(pool); listener = new ServerPortal(eqh, uri, new PortalServerCallbacks(), null); } public class PortalServerCallbacks implements ServerPortal.Callbacks { public void onSessionEvent(EventName session_event, EventReason reason) { if (session_event == EventName.PORTAL_CLOSED) { eqh.breakEventLoop(); } } public void onSessionNew(SessionKey sesKey, String srcIP, Worker workerHint) { SessionServerCallbacks callbacks = new SessionServerCallbacks(sesKey.getUri()); ServerSession session = new ServerSession(sesKey, callbacks); callbacks.setSession(session); listener.accept(session); } } public class SessionServerCallbacks implements ServerSession.Callbacks { private final DataServerMessage responseMessage; private ServerSession session; public SessionServerCallbacks(String uri) { long blockId = Long.parseLong(uri.split("blockId=")[1].split("\\?")[0]); int lockId = mBlocksLocker.lock(blockId); responseMessage = DataServerMessage.createBlockResponseMessage(true, blockId, 0, -1); responseMessage.setLockId(lockId); } public void setSession(ServerSession ses) { session = ses; } public void onRequest(Msg m) { if (session.getIsClosing()) { session.discardRequest(m); } else { responseMessage.copy(m.getOut()); try { session.sendResponse(m); } catch (JxioGeneralException e) { LOG.error(e.toString()); } catch (JxioSessionClosedException e) { LOG.error(e.toString()); } } if (!session.getIsClosing() && responseMessage.finishSending()) { session.close(); } } public void onSessionEvent(EventName session_event, EventReason reason) { if (session_event == EventName.SESSION_CLOSED) { responseMessage.close(); mBlocksLocker.unlock(Math.abs(responseMessage.getBlockId()), responseMessage.getLockId()); } } public boolean onMsgError(Msg msg, EventReason reason) { LOG.error(this.toString() + reason); return true; } } @Override public void run() { eqh.runEventLoop(-1, -1); } public void close() throws IOException { listener.close(); } public boolean isClosed() { return listener.getIsClosing(); } }