// TCP large RECEIVE of results. Note that 'this' is NOT the RPC object // that is hoping to get the received object, nor is the current thread the // RPC thread blocking for the object. The current thread is the TCP // reader thread. static void tcp_ack(final AutoBuffer ab) throws IOException { // Get the RPC we're waiting on int task = ab.getTask(); RPC rpc = ab._h2o.taskGet(task); // Race with canceling a large RPC fetch: Task is already dead. Do not // bother reading from the TCP socket, just bail out & close socket. if (rpc == null || rpc._done) { ab.drainClose(); } else { assert rpc._tasknum == task; assert !rpc._done; // Here we have the result, and we're on the correct Node but wrong // Thread. If we just return, the TCP reader thread will close the // remote, the remote will UDP ACK the RPC back, and back on the current // Node but in the correct Thread, we'd wake up and realize we received a // large result. try { rpc.response(ab); } catch (AutoBuffer.AutoBufferException e) { // If TCP fails, we will have done a short-read crushing the original // _dt object, and be unable to resend. This is fatal right now. // Really: an unimplemented feature; fix is to notice that a partial // TCP read means that the server (1) got our remote_exec request, (2) // has computed an answer and was trying to send it to us, (3) failed // sending via TCP hence the server knows it failed and will send again // without any further work from us. We need to disable all the resend // & retry logic, and wait for the server to re-send our result. // Meanwhile the _dt object is crushed with half-read crap, and cannot // be trusted except in the base fields. throw Log.throwErr(e._ioe); } } // ACKACK the remote, telling him "we got the answer" new AutoBuffer(ab._h2o, H2O.ACK_ACK_PRIORITY).putTask(UDP.udp.ackack.ordinal(), task).close(); }
// TCP large RECEIVE of results. Note that 'this' is NOT the RPC object // that is hoping to get the received object, nor is the current thread the // RPC thread blocking for the object. The current thread is the TCP // reader thread. static void tcp_ack(final AutoBuffer ab) { // Get the RPC we're waiting on int task = ab.getTask(); RPC rpc = TASKS.get(task); // Race with canceling a large RPC fetch: Task is already dead. Do not // bother reading from the TCP socket, just bail out & close socket. if (rpc == null) { ab.drainClose(); } else { assert rpc._tasknum == task; assert !rpc._done; // Here we have the result, and we're on the correct Node but wrong // Thread. If we just return, the TCP reader thread will close the // remote, the remote will UDP ACK the RPC back, and back on the current // Node but in the correct Thread, we'd wake up and realize we received a // large result. rpc.response(ab); } // ACKACK the remote, telling him "we got the answer" new AutoBuffer(ab._h2o).putTask(UDP.udp.ackack.ordinal(), task).close(true); }