/** Test of createTimer method, of class FleaseStage. */ @Test public void testGetState() throws Exception { FleaseStage fs = new FleaseStage( cfg, "/tmp/xtreemfs-test/", new FleaseMessageSenderInterface() { @Override public void sendMessage(FleaseMessage message, InetSocketAddress recipient) { // ignore me } }, true, new FleaseViewChangeListenerInterface() { @Override public void viewIdChangeEvent(ASCIIString cellId, int viewId) {} }, new FleaseStatusListener() { @Override public void statusChanged(ASCIIString cellId, Flease lease) {} @Override public void leaseFailed(ASCIIString cellId, FleaseException error) { fail(error.toString()); } }, null); FleaseMessage msg = new FleaseMessage(FleaseMessage.MsgType.EVENT_RESTART); msg.setCellId(new ASCIIString("testcell")); fs.start(); fs.waitForStartup(); FleaseFuture f = fs.openCell(new ASCIIString("testcell"), new ArrayList(), false); final AtomicBoolean done = new AtomicBoolean(false); f.get(); Thread.sleep(100); Map<ASCIIString, FleaseMessage> m = fs.getLocalState(); // for (ASCIIString cellId : m.keySet()) { // System.out.println("cell "+cellId+" "+m.get(cellId)); // } fs.shutdown(); fs.waitForShutdown(); }
/** Test of createTimer method, of class FleaseStage. */ @Test public void testCreateTimer() throws Exception { FleaseStage fs = new FleaseStage( cfg, "/tmp/xtreemfs-test/", new FleaseMessageSenderInterface() { @Override public void sendMessage(FleaseMessage messages, InetSocketAddress recipient) { // ignore me } }, true, new FleaseViewChangeListenerInterface() { @Override public void viewIdChangeEvent(ASCIIString cellId, int viewId) {} }, new FleaseStatusListener() { @Override public void statusChanged(ASCIIString cellId, Flease lease) { throw new UnsupportedOperationException("Not supported yet."); } @Override public void leaseFailed(ASCIIString cellId, FleaseException error) { throw new UnsupportedOperationException("Not supported yet."); } }, null); FleaseMessage msg = new FleaseMessage(FleaseMessage.MsgType.EVENT_RESTART); msg.setCellId(new ASCIIString("testcell")); fs.start(); fs.waitForStartup(); fs.createTimer(msg, TimeSync.getLocalSystemTime() + 20); Thread.sleep(100); fs.shutdown(); fs.waitForShutdown(); }
/** * Handles paxos learn messages. Removes oudated instances and updates maxLearnedInstId * accordingly * * @param msg incomming message */ public void handleLEARN(FleaseMessage msg) { final FleaseAcceptorCell cc = getCell(msg); cc.touch(); if ((cc.getPrepared() != null) && (cc.getPrepared().after(msg)) || (cc.getAccepted() != null) && (cc.getAccepted().after(msg))) { if (Logging.isDebug() && config.isDebugPrintMessages()) Logging.logMessage( Logging.LEVEL_DEBUG, Category.replication, this, "A ignore outdated LEARN message " + msg.getProposalNo()); } else { if (Logging.isDebug() && config.isDebugPrintMessages()) { final String preped = (cc.getPrepared() == null) ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString() : cc.getPrepared().getProposalNo().toString(); final String acced = (cc.getAccepted() == null) ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString() : cc.getAccepted().getProposalNo() + "=" + cc.getAccepted().getLeaseHolder() + "/" + cc.getAccepted().getLeaseTimeout(); Logging.logMessage( Logging.LEVEL_DEBUG, Category.replication, this, "A learn p:" + preped + " a: " + acced + " -> " + msg.getProposalNo() + "=" + msg.getLeaseHolder() + "/" + msg.getLeaseTimeout()); } cc.setAccepted(msg); cc.setPrepared(msg); cc.setLatestLearn(msg); evtListener.learnedEvent( msg.getCellId(), msg.getLeaseHolder(), msg.getLeaseTimeout(), msg.getMasterEpochNumber()); } }
/** Test of createTimer method, of class FleaseStage. */ @Test public void testOpenAndGetLease() throws Exception { final ASCIIString CELL_ID = new ASCIIString("testcell"); final AtomicReference<Flease> result = new AtomicReference(); FleaseStage fs = new FleaseStage( cfg, "/tmp/xtreemfs-test/", new FleaseMessageSenderInterface() { @Override public void sendMessage(FleaseMessage message, InetSocketAddress recipient) { // ignore me } }, true, new FleaseViewChangeListenerInterface() { @Override public void viewIdChangeEvent(ASCIIString cellId, int viewId) {} }, new FleaseStatusListener() { @Override public void statusChanged(ASCIIString cellId, Flease lease) { // System.out.println("state change: "+cellId+" owner="+lease.getLeaseHolder()); synchronized (result) { result.set( new Flease( cellId, lease.getLeaseHolder(), lease.getLeaseTimeout_ms(), lease.getMasterEpochNumber())); result.notify(); } } @Override public void leaseFailed(ASCIIString cellId, FleaseException error) { fail(error.toString()); } }, null); FleaseMessage msg = new FleaseMessage(FleaseMessage.MsgType.EVENT_RESTART); msg.setCellId(CELL_ID); fs.start(); fs.waitForStartup(); fs.openCell(CELL_ID, new ArrayList(), false); synchronized (result) { if (result.get() == null) result.wait(1000); if (result.get() == null) fail("timeout!"); } assertEquals(result.get().getLeaseHolder(), cfg.getIdentity()); FleaseFuture f = fs.closeCell(CELL_ID, false); f.get(); Thread.sleep(12000); result.set(null); fs.openCell(CELL_ID, new ArrayList(), false); synchronized (result) { if (result.get() == null) result.wait(1000); if (result.get() == null) fail("timeout!"); } assertEquals(result.get().getLeaseHolder(), cfg.getIdentity()); fs.shutdown(); fs.waitForShutdown(); }
/** main loop */ public FleaseMessage processMessage(FleaseMessage msg) { assert (!quit); /*if (Logging.isDebug()) Logging.logMessage(Logging.LEVEL_DEBUG,this,"received %s",msg.toString());*/ final long now = TimeSync.getLocalSystemTime(); if (msg.getSendTimestamp() + config.getMessageTimeout() < TimeSync.getGlobalTime()) { // old message, ignore if (Logging.isDebug() && config.isDebugPrintMessages()) Logging.logMessage( Logging.LEVEL_DEBUG, Category.replication, this, "A outdated message discarded: %s", msg.toString()); return null; } if (this.waitUntilTimestamp_ms >= now) { if (Logging.isDebug() && config.isDebugPrintMessages()) Logging.logMessage( Logging.LEVEL_DEBUG, Category.replication, this, "A message discarded, acceptor is still in recovery period"); return null; } assert (msg.getCellId() != null); final FleaseAcceptorCell cc = getCell(msg.getCellId()); if (cc.getViewId() < msg.getViewId()) { // If the local view is lower than the delivered one, the view listener has to be informed to // update // the local view. But the request can still be answered. viewListener.viewIdChangeEvent(msg.getCellId(), msg.getViewId()); } else if (cc.getViewId() > msg.getViewId() || (cc.getViewId() == msg.getViewId() && cc.isViewInvalidated())) { // If the request is from an older view, or the a view that has been invalidated on this // AcceptorCell, the request has to be aborted. FleaseMessage response = new FleaseMessage(FleaseMessage.MsgType.MSG_WRONG_VIEW, msg); response.setViewId(cc.getViewId()); return response; } FleaseMessage response = null; if (msg.getMsgType() == FleaseMessage.MsgType.MSG_PREPARE) response = handlePREPARE(msg); else if (msg.getMsgType() == FleaseMessage.MsgType.MSG_ACCEPT) response = handleACCEPT(msg); else if (msg.getMsgType() == FleaseMessage.MsgType.MSG_LEARN) handleLEARN(msg); /*else if (msg.getMsgType() == FleaseMessage.MsgType.MSG_GET_LEASE) response = handleGETLEASE(msg); else if (msg.getMsgType() == FleaseMessage.MsgType.MSG_RENEW_LEASE) response = handleRENEWINSTANCE(msg);*/ else Logging.logMessage( Logging.LEVEL_ERROR, Category.replication, this, "A invalid message type received: %s", msg.toString()); /*if (Logging.isDebug()) Logging.logMessage(Logging.LEVEL_DEBUG,this,"response %s",(response != null) ? response.toString() : "<empty>");*/ return response; }
/** * Handles paxos accept (vote) messages. * * @param msg incomming message * @return a response message or null */ public FleaseMessage handleACCEPT(FleaseMessage msg) { final FleaseAcceptorCell cc = getCell(msg); cc.touch(); if ((cc.getPrepared() != null) && (cc.getPrepared().after(msg))) { // reject the request if (Logging.isDebug() && config.isDebugPrintMessages()) { final String preped = (cc.getPrepared() == null) ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString() : cc.getPrepared().getProposalNo().toString(); Logging.logMessage( Logging.LEVEL_DEBUG, Category.replication, this, "A accept NACK p:" + preped + " is after " + msg.getProposalNo() + ""); } FleaseMessage tmp = new FleaseMessage(FleaseMessage.MsgType.MSG_ACCEPT_NACK, msg); tmp.setSendTimestamp(TimeSync.getGlobalTime()); tmp.setLeaseHolder(null); tmp.setLeaseTimeout(0); tmp.setPrevProposalNo(cc.getPrepared().getProposalNo()); return tmp; } else { // okay accept it if (Logging.isDebug() && config.isDebugPrintMessages()) { final String preped = (cc.getPrepared() == null) ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString() : cc.getPrepared().getProposalNo().toString(); final String acced = (cc.getAccepted() == null) ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString() : cc.getAccepted().getProposalNo() + "=" + cc.getAccepted().getLeaseHolder() + "/" + cc.getAccepted().getLeaseTimeout(); Logging.logMessage( Logging.LEVEL_DEBUG, Category.replication, this, "A accept ACK p:" + preped + " a: " + acced + " -> " + msg.getProposalNo() + "=" + msg.getLeaseHolder() + "/" + msg.getLeaseTimeout()); } assert (msg.getLeaseHolder() != null); cc.setAccepted(msg); cc.setPrepared(msg); FleaseMessage tmp = new FleaseMessage(FleaseMessage.MsgType.MSG_ACCEPT_ACK, msg); tmp.setSendTimestamp(TimeSync.getGlobalTime()); return tmp; } }
/** * Handles paxos prepare messages * * @param msg the incomming message * @return a response message */ public FleaseMessage handlePREPARE(FleaseMessage msg) { final FleaseAcceptorCell cc = getCell(msg); cc.touch(); if ((cc.getPrepared() != null) && (cc.getPrepared().after(msg))) { if (Logging.isDebug() && config.isDebugPrintMessages()) { final String preped = (cc.getPrepared() == null) ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString() : cc.getPrepared().getProposalNo().toString(); Logging.logMessage( Logging.LEVEL_DEBUG, Category.replication, this, "A prepare NACK p:" + preped + " is after " + msg.getProposalNo() + ""); } FleaseMessage reject = new FleaseMessage(FleaseMessage.MsgType.MSG_PREPARE_NACK, msg); reject.setPrevProposalNo(cc.getPrepared().getProposalNo()); reject.setLeaseHolder(null); reject.setLeaseTimeout(0); reject.setSendTimestamp(TimeSync.getGlobalTime()); return reject; } else { if (Logging.isDebug() && config.isDebugPrintMessages()) { final String preped = (cc.getPrepared() == null) ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString() : cc.getPrepared().getProposalNo().toString(); final String acced = (cc.getAccepted() == null) ? ProposalNumber.EMPTY_PROPOSAL_NUMBER.toString() : cc.getAccepted().getProposalNo() + "=" + cc.getAccepted().getLeaseHolder() + "/" + cc.getAccepted().getLeaseTimeout(); Logging.logMessage( Logging.LEVEL_DEBUG, Category.replication, this, "A prepare ACK p:" + preped + " -> " + msg.getProposalNo() + " a:" + acced); } // lastPrepared = msg; cc.setPrepared(msg); // FIXME:Persistently write to disk FleaseMessage response = new FleaseMessage(FleaseMessage.MsgType.MSG_PREPARE_ACK, msg); if (cc.getAccepted() != null) { response.setPrevProposalNo(cc.getAccepted().getProposalNo()); response.setLeaseHolder(cc.getAccepted().getLeaseHolder()); assert (response.getLeaseHolder() != null); response.setLeaseTimeout(cc.getAccepted().getLeaseTimeout()); } response.setSendTimestamp(TimeSync.getGlobalTime()); return response; } }
private FleaseAcceptorCell getCell(FleaseMessage msg) { assert (msg != null); return getCell(msg.getCellId()); }