private final RPC<T> remote_compute( ArrayList<Key> keys ) { if( keys.size() == 0 ) return null; DRemoteTask rpc = clone(); rpc.setCompleter(null); rpc._keys = keys.toArray(new Key[keys.size()]); addToPendingCount(1); // Block until the RPC returns // Set self up as needing completion by this RPC: when the ACK comes back // we'll get a wakeup. return new RPC(keys.get(0).home_node(), rpc).addCompleter(this).call(); }
public void run() { Thread.currentThread().setPriority(Thread.NORM_PRIORITY); while( true ) { try { RPC t = PENDING.take(); // One-shot timeout effect. Retries need to re-insert back in the queue if( H2O.CLOUD.contains(t._target) ) { if( !t.isDone() ) t.call(); } else t.cancel(true); } catch( InterruptedException e ) { // Interrupted while waiting for a packet? // Blow it off and go wait again... } } } public static final RPC[] pendingRPCs(){
public static Value get( H2ONode target, Key key, int priority ) { RPC<TaskGetKey> rpc, old; while( true ) { // Repeat until we get a unique TGK installed per key // Do we have an old TaskGetKey in-progress? rpc = TGKS.get(key); if( rpc != null && rpc._dt._priority >= priority ) break; old = rpc; // Make a new TGK. rpc = new RPC(target,new TaskGetKey(key,priority),1.0f); if( TGKS.putIfMatchUnlocked(key,rpc,old) == old ) { rpc.setTaskNum().call(); // Start the op break; // Successful install of a fresh RPC } } Value val = rpc.get()._val; // Block for, then fetch out the result TGKS.putIfMatchUnlocked(key,null,rpc); // Clear from cache return val; }
@Override public void lcompute() { _infos = new NodeTaskInfo[H2O.CLOUD.size()]; TaskInfo [][] ts = new TaskInfo[H2O.CLOUD.size()][]; int i = 0; for (H2ONode n : H2O.CLOUD._memary) ts[i++] = n.currentTasksInfo(); RPC [] pendingRPCs = UDPTimeOutThread.pendingRPCs(); TaskInfo [] pending = new TaskInfo[pendingRPCs.length]; for(int j = 0; j < pendingRPCs.length; ++j) pending[j] = new TaskInfo(pendingRPCs[j].task(),pendingRPCs[j].taskNum(),pendingRPCs[j].target().index(), pendingRPCs[j].isDone()? task_status.DONE:task_status.CMP,pendingRPCs[j]._callCnt); _infos[H2O.SELF.index()] = new NodeTaskInfo(pending,ts); tryComplete(); } }
private void reduce3( RPC<T> rpc ) { if( rpc == null ) return; T mrt = rpc.get(); // This is a blocking remote call // Note: because _fs is transient it is not set or cleared by the RPC. // Because the MRT object is a clone of 'self' it's likely to contain a ptr // to the self _fs which will be not-null and still have local pending // blocks. Not much can be asserted there. _profile.gather(mrt._profile, rpc.size_rez()); // Unlike reduce2, results are in mrt directly not mrt._res. if( mrt._nhi != -1L ) { // Any results at all? if( _res == null ) _res = mrt; else _res.reduce4(mrt); } }
static void invalidate( H2ONode h2o, Key key, Futures fs ) { Future f = RPC.call(h2o,new TaskInvalidateKey(key)); if( fs != null ) fs.add(f); }
private final void donCompletion( CountedCompleter caller ) { // Distributed completion assert _lo == null || _lo.isDone(); assert _hi == null || _hi.isDone(); // Fold up results from left & right subtrees if( _lo != null ) reduce2(_lo.get()); if( _hi != null ) reduce2(_hi.get()); if( _local != null ) reduce2(_local ); // Note: in theory (valid semantics) we could push these "over the wire" // and block for them as we're blocking for the top-level initial split. // However, that would require sending "isDone" flags over the wire also. // MUCH simpler to just block for them all now, and send over the empty set // of not-yet-blocked things. if(_local != null && _local._fs != null ) _local._fs.blockForPending(); // Block on all other pending tasks, also _keys = null; // Do not return _keys over wire if( _top_level ) postGlobal(); }; // Override to do work after all the forks have returned
for( H2OCountedCompleter hcc : _fjtasks ) if( hcc == cc) alreadyIn = true; if( !alreadyIn ) addCompleter((H2OCountedCompleter)cc); _dt.setCompleter(null); try { if( isDone() ) { if( _target != null ) _target.taskRemove(_tasknum); return this; ab.putTask(UDP.udp.exec,_tasknum).put1(CLIENT_UDP_SEND).put(_dt); boolean t = ab.hasTCP(); assert sz_check(ab) : "Resend of "+_dt.getClass()+" changes size from "+_size+" to "+ab.size()+" for task#"+_tasknum;
/** Block until it completes, even if run remotely */ public final T invoke( Key key ) { RPC<Atomic<T>> rpc = fork(key); return (T)(rpc == null ? this : rpc.get()); // Block for it }
@Override public V get() { // check priorities - FJ task can only block on a task with higher priority! Thread cThr = Thread.currentThread(); int priority = (cThr instanceof FJWThr) ? ((FJWThr)cThr)._priority : -1; // was hitting this (priority=1 but _dt.priority()=0 for DRemoteTask) - not clear who increased priority of FJWThr to 1... // assert _dt.priority() > priority || (_dt.priority() == priority && (_dt instanceof DRemoteTask || _dt instanceof MRTask2)) assert _dt.priority() > priority || ((_dt instanceof DRemoteTask || _dt instanceof MRTask2)) : "*** Attempting to block on task (" + _dt.getClass() + ") with equal or lower priority. Can lead to deadlock! " + _dt.priority() + " <= " + priority; if( _done ) return result(); // Fast-path shortcut // Use FJP ManagedBlock for this blocking-wait - so the FJP can spawn // another thread if needed. try { try { ForkJoinPool.managedBlock(this); } catch (InterruptedException e) { } } catch(Throwable t){ // catch and rethrow to preserve the stack trace! throw new RuntimeException(t); } if( _done ) return result(); // Fast-path shortcut assert isCancelled(); return null; } // Return true if blocking is unnecessary, which is true if the Task isDone.
if( ctrl < 0 || ctrl >= UDP.udp.UDPS.length ) x = 0; switch( UDP.udp.UDPS[x] ) { case exec: RPC.remote_exec (_ab); break; case ack: RPC.tcp_ack (_ab); break; case timeline: TimeLine.tcp_call(_ab); break; default: throw new RuntimeException("Unknown TCP Type: " + ctrl+" "+_ab._h2o);
AutoBuffer call(AutoBuffer ab) { int tnum = ab.getTask(); RPC<?> t = ab._h2o.taskGet(tnum); assert t== null || t._tasknum == tnum; if( t != null ) t.response(ab); // Do the 2nd half of this task, includes ACKACK else ab.close(); // Else forgotten task, but still must ACKACK return new AutoBuffer(ab._h2o).putTask(UDP.udp.ackack.ordinal(),tnum); }
@Override public boolean isReleasable() { return isDone(); } // Possibly blocks the current thread. Returns true if isReleasable would
@Override public final boolean cancel( boolean mayInterruptIfRunning ) { boolean did = false; synchronized(this) { // Install the answer under lock if( !isCancelled() ) { did = true; // Did cancel (was not cancelled already) _target.taskRemove(_tasknum); _target = null; // Flag as canceled UDPTimeOutThread.PENDING.remove(this); } notifyAll(); // notify in any case } return did; }
@Override public void compute2() { _ab.getPort(); // skip past the port if( _ctrl <= UDP.udp.ack.ordinal() ) UDP.udp.UDPS[_ctrl]._udp.call(_ab).close(); else RPC.remote_exec(_ab); tryComplete(); } /** Exceptional completion path; mostly does printing if the exception was
protected int response( AutoBuffer ab ) { assert _tasknum==ab.getTask(); if( _done ) return ab.close(); // Ignore duplicate response packet int flag = ab.getFlag(); // Must read flag also, to advance ab if( flag == SERVER_TCP_SEND ) return ab.close(); // Ignore UDP packet for a TCP reply assert flag == SERVER_UDP_SEND; synchronized(this) { // Install the answer under lock if( _done ) return ab.close(); // Ignore duplicate response packet UDPTimeOutThread.PENDING.remove(this); _dt.read(ab); // Read the answer (under lock?) _size_rez = ab.size(); // Record received size ab.close(); // Also finish the read (under lock?) _dt.onAck(); // One time only execute (before sending ACKACK) _done = true; // Only read one (of many) response packets ab._h2o.taskRemove(_tasknum); // Flag as task-completed, even if the result is null notifyAll(); // And notify in any case } doAllCompletions(); // Send all tasks needing completion to the work queues return 0; }
private final void doTest(){ _droppedPackets = new int[_N]; Arrays.fill(_droppedPackets,-1); _pings = new RPC[_msgSzs.length][_N]; // addToPendingCount(_msgSzs.length*_N - 1); for(int i = 0; i < _msgSzs.length; ++i) for(int j = 0; j < _N; ++j) // instead of synchronization, just wait for predetermined amount of time _pings[i][j] = new RPC(H2O.CLOUD._memary[_tgtId],new UDPPing(_msgSzs[i]))/*.addCompleter(this)*/.call(); try { Thread.sleep(5000); } catch (InterruptedException e) {} // if not done yet, finish no matter what (racy but we don't care here - only a debug tool, does not have to be precise) // setPendingCount(0); }