private final static int next_idx( long [] tl ) { // Spin until we can CAS-acquire a fresh index while( true ) { int oldidx = (int)tl[0]; int newidx = (oldidx+1)&(MAX_EVENTS-1); if( CAS( tl, 0, oldidx, newidx ) ) return oldidx; } }
public final int dropped () { return TimeLine.dropped (_val, _eventIdx); } public final boolean isSend() { return send_recv() == 0; }
public static long ns( long[] tl, int idx ) { return tl[idx(tl,idx)+1]; } // Returns zero for send, 1 for recv
/** * Only for debugging. * Prints local timeline to stdout. * * To be used in case of an error when global timeline can not be relied upon as we might not be able to talk to other nodes. */ public static void printMyTimeLine(){ long [] s = TimeLine.snapshot(); System.err.println("===================================<TIMELINE>=============================================="); for(int i = 0; i < TimeLine.length(); ++i) { long lo = TimeLine.l0(s, i),hi = TimeLine.l8(s, i); int port = (int)((lo >> 8) & 0xFFFF); String op = TimeLine.send_recv(s,i) == 0?"SEND":"RECV"; if(!TimeLine.isEmpty(s, i) && (lo & 0xFF) == UDP.udp.exec.ordinal()) System.err.println(TimeLine.ms(s, i) + ": " + op + " " + (((TimeLine.ns(s, i) & 4) != 0)?"TCP":"UDP") + TimeLine.inet(s, i) + ":" + port + " | " + UDP.printx16(lo, hi)); } System.err.println("==========================================================================================="); } }
Event nextEvent() { return nextEvent(TimeLine.length()); }
public final long dataHi() { return TimeLine.l8(_val, _eventIdx); } public final long ns() { return TimeLine.ns(_val, _eventIdx); }
public final InetAddress addrPack() { return TimeLine.inet(_val, _eventIdx); } public final long dataLo() { return TimeLine.l0(_val, _eventIdx); }
public final long dataLo() { return TimeLine.l0(_val, _eventIdx); } public final long dataHi() { return TimeLine.l8(_val, _eventIdx); }
public final long ms() { return TimeLine.ms(_val, _eventIdx) + recoH2O()._heartbeat._jvm_boot_msec; } public H2ONode packH2O() { return _packh2o; } // H2O in packet
private static void record2( H2ONode h2o, long ns, boolean tcp, int sr, int drop, long b0, long b8 ) { final long ms = System.currentTimeMillis(); // Read first, in case we're slow storing values long deltams = ms-JVM_BOOT_MSEC; assert deltams < 0x0FFFFFFFFL; // No daily overflow final long[] tl = TIMELINE; // Read once, in case the whole array shifts out from under us final int idx = next_idx(tl); // Next free index tl[idx*WORDS_PER_EVENT+0+1] = (deltams)<<32 | (h2o.ip4()&0x0FFFFFFFFL); tl[idx*WORDS_PER_EVENT+1+1] = (ns&~7)| (tcp?4:0)|sr|drop; // More complexities: record the *receiver* port in the timeline - but not // in the outgoing UDP packet! The outgoing packet always has the sender's // port (that's us!) - which means the recorded timeline packet normally // never carries the *receiver* port - meaning the sender's timeline does // not record who he sent to! With this hack the Timeline record always // contains the info about "the other guy": inet+port for the receiver in // the sender's Timeline, and vice-versa for the receiver's Timeline. if( sr==0 ) b0 = (b0 & ~0xFFFF00) | (h2o._key.udp_port()<<8); tl[idx*WORDS_PER_EVENT+2+1] = b0; tl[idx*WORDS_PER_EVENT+3+1] = b8; }
boolean next() { return next(TimeLine.length()); }
public static long l8( long[] tl, int idx ) { return tl[idx(tl,idx)+3]; }
boolean next(int maxIdx) { int max = Math.min(maxIdx, TimeLine.length()); if (_eventIdx >= max) return false; while (++_eventIdx < max) if (!isEmpty()) return computeH2O(true); return computeH2O(false); }
public static boolean isEmpty( long[] tl, int idx ) { return tl[idx(tl,idx)+0]==0; }
private static long x0( long[] tl, int idx ) { return tl[idx(tl,idx)+0]; } // ms since boot of JVM
public static long l0( long[] tl, int idx ) { return tl[idx(tl,idx)+2]; } public static long l8( long[] tl, int idx ) { return tl[idx(tl,idx)+3]; }