All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.piax.gtrans.ov.sg.RQMessage Maven / Gradle / Ivy

The newest version!
/*
 * RQMessage.java - RQMessage implementation of SkipGraph.
 *
 * Copyright (c) 2015 Kota Abe / PIAX development team
 *
 * You can redistribute it and/or modify it under either the terms of
 * the AGPLv3 or PIAX binary code license. See the file COPYING
 * included in the PIAX package for more in detail.
 *
 * $Id: MSkipGraph.java 1160 2015-03-15 02:43:20Z teranisi $
 */

package org.piax.gtrans.ov.sg;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.NavigableMap;

import org.piax.common.DdllKey;
import org.piax.common.Endpoint;
import org.piax.common.PeerId;
import org.piax.common.subspace.Range;
import org.piax.gtrans.RemoteValue;
import org.piax.gtrans.TransOptions;
import org.piax.gtrans.TransOptions.ResponseType;
import org.piax.gtrans.ov.Link;
import org.piax.gtrans.ov.sg.SGMessagingFramework.SGReplyMessage;
import org.piax.gtrans.ov.sg.SGMessagingFramework.SGRequestMessage;
import org.piax.gtrans.ov.sg.SkipGraph.QueryId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * a class representing a message used for propagating range queries.
 * 

* this class contains various data that are required to be transmitted to the * target nodes. this class also contains failedLinks field, which * represents a set of failed nodes that are found while processing the range * query. *

* this class also manages (partial) results returned from child nodes ( * rqRet). * * @author k-abe */ public class RQMessage extends SGRequestMessage { /*--- logger ---*/ private static final Logger logger = LoggerFactory .getLogger(RQMessage.class); private static final long serialVersionUID = 1L; /** true if you want to record all the intermediate nodes */ public final static boolean TRACE = true; /** subranges, split by the range query algorithm */ final Collection> subRanges; /** query id */ final QueryId qid; /* query contents */ final Object query; /** hop counter for gathering statistics */ final int hops; transient RQReturn rqRet; /** * failed links. this field is used for avoiding and repairing dead links. */ final List failedLinks; /** cached allLinks for retransmission */ transient NavigableMap cachedAllLinks; /** intermediate nodes along with query path */ List trace; public static RQMessage newRQMessage4Root( SGMessagingFramework sgmf, Collection> subRanges, QueryId qid, Object query, int expire, TransOptions opts) { RQMessage msg; // XXX opts should be on the message if (TransOptions.responseType(opts) != ResponseType.DIRECT) { msg = new RQMessage(sgmf, true, false, null, SGMessagingFramework.DUMMY_MSGID, subRanges, qid, query, expire, 0); } else { msg = new RQMessage(sgmf, true, true, sgmf.myLocator, SGMessagingFramework.DUMMY_MSGID, subRanges, qid, query, expire, 0); } return msg; } /** * create an instance of RQMessage. * * @param sgmf the SGMessagingFramework managing this message * @param isRoot true if this instance is used at the root node * @param isDirectReturn true if reply messages should be directly sent to * the root node * @param replyTo the node that the reply message for this message should be * sent to * @param replyId the ID to distinguish queries at the replyTo node * @param subRanges set of query ranges * @param qid QueryId to uniquely distinguish this message * @param query an object sent to all the nodes within the query ranges * @param expire expiration time. * @param hops a hop count from the root node */ private RQMessage(SGMessagingFramework sgmf, boolean isRoot, boolean isDirectReturn, E replyTo, int replyId, Collection> subRanges, QueryId qid, Object query, int expire, int hops) { /* * ignored if replyTo == null */ super(sgmf, isRoot, isDirectReturn, replyTo, replyId, expire); this.subRanges = subRanges; this.qid = qid; this.query = query; this.hops = hops; this.failedLinks = new ArrayList(); if (TRACE) { trace = new ArrayList(); } } /** * create an instance of RQMessage whose subRange is replaced. * * @param newSubRanges new subranges to be replaced to * @return an instance of RQMessage */ public RQMessage newInstanceSubrangesChanged( Collection> newSubRanges) { RQMessage newMsg = new RQMessage(this, newSubRanges); newMsg.rqRet = rqRet; return newMsg; } private RQMessage(RQMessage msgSrc, Collection> newSubRanges) { super(msgSrc); this.subRanges = newSubRanges; this.qid = msgSrc.qid; this.query = msgSrc.query; this.hops = msgSrc.hops; this.failedLinks = new ArrayList(msgSrc.failedLinks); if (TRACE) { trace = new ArrayList(msgSrc.trace); } } /** * create a child RQMessage from this instance. *

* this method is used at intermediate nodes. * * @param newSubRange new subrange for the child RQMessage * @param reason commentary string for debugging * @return a instance of child RQMessage */ public RQMessage newChildInstance(Collection> newSubRange, String reason) { RQMessage newMsg; if (isDirectReturn) { newMsg = new RQMessage(sgmf, false, true, replyTo, replyId, newSubRange, qid, query, expire, hops + 1); } else { newMsg = new RQMessage(sgmf, false, false, null, SGMessagingFramework.DUMMY_MSGID, newSubRange, qid, query, expire, hops + 1); } newMsg.rqRet = rqRet; assert rqRet != null; newMsg.addFailedLinks(failedLinks); newMsg.addTrace(trace); newMsg.addTrace(reason); return newMsg; } @Override public String toString() { return "RQMsg[sender=" + sender + ", receiver=" + receiver + ", msgId=" + msgId + ", replyTo=" + replyTo + ", replyId=" + replyId + ", subRanges=" + subRanges + ", rqRet=" + rqRet + ", failedLinks=" + failedLinks + "]"; } void addFailedLinks(Collection links) { failedLinks.addAll(links); } void addTrace(Collection locs) { if (TRACE) { trace.addAll(locs); } } void addTrace(String loc) { if (TRACE) { trace.add(loc); } } @Override public void execute(SkipGraph sg) { sg.rqDisseminate(this); } @Override public boolean onReceivingReply(SkipGraph sg, SGReplyMessage reply0) { RQReplyMessage reply = (RQReplyMessage) reply0; logger.debug("onReceivingReply: reply={}, this={}", reply, this); sg.rqSetReturnValue(rqRet, reply.senderId, reply.vals, reply.hops); if (isDirectReturn) { assert isRoot; return rqRet.isCompleted(); } else { return reply.isFinal; } } @Override public synchronized void onTimeOut(SkipGraph sg) { logger.debug("onTimeout: {}, {}", sg.toStringShort(), this); synchronized (rqRet) { // このメッセージのACKタイムアウトの契機で,同時に送ったメッセージで // タイムアウトしているものがないか調べる. Collection failedNodes = new HashSet(); Collection> ranges = new HashSet>(); for (RQMessage msg : rqRet.childMsgs.values()) { if (msg.isAckTimedOut()) { msg.ackReceived = true; // XXX: fake fake fake failedNodes.add(msg.receiver); ranges.addAll(msg.subRanges); } } logger.debug("onTimeout: failedNodes = {}", failedNodes); if (!failedNodes.isEmpty()) { sg.fixRoutingTables(failedNodes, rqRet.parentMsg, ranges); } /* * org.piax.gtrans.sg.fixRoutingTable(failedNodes, null, * rqRet.parentMsg, ranges); */ } } /** * a class representing a reply message against {@link RQMessage}, * containing range query results. */ public static class RQReplyMessage extends SGReplyMessage { private static final long serialVersionUID = 1L; final PeerId senderId; final Collection>> vals; /** is final reply? */ final boolean isFinal; final int hops; /** * constructor. * * @param sg skip graph * @param replyTo the RQMessage for which the reply message is created * @param vals return values * @param isFinal true if this reply message is the final message and no * more reply message will be sent * @param hops max hop count observed by this node (maybe) */ public RQReplyMessage(SkipGraph sg, RQMessage replyTo, Collection>> vals, boolean isFinal, int hops) { super(sg, replyTo); this.senderId = sg.peerId; this.vals = vals; this.isFinal = isFinal; this.hops = hops; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy