/// <summary>Ask the DataNode for a new shared memory segment.</summary> /// <remarks> /// Ask the DataNode for a new shared memory segment. This function must be /// called with the manager lock held. We will release the lock while /// communicating with the DataNode. /// </remarks> /// <param name="clientName">The current client name.</param> /// <param name="peer">The peer to use to talk to the DataNode.</param> /// <returns> /// Null if the DataNode does not support shared memory /// segments, or experienced an error creating the /// shm. The shared memory segment itself on success. /// </returns> /// <exception cref="System.IO.IOException"> /// If there was an error communicating over the socket. /// We will not throw an IOException unless the socket /// itself (or the network) is the problem. /// </exception> private DfsClientShm RequestNewShm(string clientName, DomainPeer peer) { DataOutputStream @out = new DataOutputStream(new BufferedOutputStream(peer.GetOutputStream ())); new Sender(@out).RequestShortCircuitShm(clientName); DataTransferProtos.ShortCircuitShmResponseProto resp = DataTransferProtos.ShortCircuitShmResponseProto .ParseFrom(PBHelper.VintPrefixed(peer.GetInputStream())); string error = resp.HasError() ? resp.GetError() : "(unknown)"; switch (resp.GetStatus()) { case DataTransferProtos.Status.Success: { DomainSocket sock = peer.GetDomainSocket(); byte[] buf = new byte[1]; FileInputStream[] fis = new FileInputStream[1]; if (sock.RecvFileInputStreams(fis, buf, 0, buf.Length) < 0) { throw new EOFException("got EOF while trying to transfer the " + "file descriptor for the shared memory segment." ); } if (fis[0] == null) { throw new IOException("the datanode " + this.datanode + " failed to " + "pass a file descriptor for the shared memory segment." ); } try { DfsClientShm shm = new DfsClientShm(PBHelper.Convert(resp.GetId()), fis[0], this, peer); if (DfsClientShmManager.Log.IsTraceEnabled()) { DfsClientShmManager.Log.Trace(this + ": createNewShm: created " + shm); } return(shm); } finally { IOUtils.Cleanup(DfsClientShmManager.Log, fis[0]); } goto case DataTransferProtos.Status.ErrorUnsupported; } case DataTransferProtos.Status.ErrorUnsupported: { // The DataNode just does not support short-circuit shared memory // access, and we should stop asking. DfsClientShmManager.Log.Info(this + ": datanode does not support short-circuit " + "shared memory access: " + error); this.disabled = true; return(null); } default: { // The datanode experienced some kind of unexpected error when trying to // create the short-circuit shared memory segment. DfsClientShmManager.Log.Warn(this + ": error requesting short-circuit shared memory " + "access: " + error); return(null); } } }
/// <summary>Request file descriptors from a DomainPeer.</summary> /// <param name="peer">The peer to use for communication.</param> /// <param name="slot"> /// If non-null, the shared memory slot to associate with the /// new ShortCircuitReplica. /// </param> /// <returns> /// A ShortCircuitReplica object if we could communicate with the /// datanode; null, otherwise. /// </returns> /// <exception cref="System.IO.IOException"> /// If we encountered an I/O exception while communicating /// with the datanode. /// </exception> private ShortCircuitReplicaInfo RequestFileDescriptors(DomainPeer peer, ShortCircuitShm.Slot slot) { ShortCircuitCache cache = clientContext.GetShortCircuitCache(); DataOutputStream @out = new DataOutputStream(new BufferedOutputStream(peer.GetOutputStream ())); ShortCircuitShm.SlotId slotId = slot == null ? null : slot.GetSlotId(); new Sender(@out).RequestShortCircuitFds(block, token, slotId, 1, failureInjector. GetSupportsReceiptVerification()); DataInputStream @in = new DataInputStream(peer.GetInputStream()); DataTransferProtos.BlockOpResponseProto resp = DataTransferProtos.BlockOpResponseProto .ParseFrom(PBHelper.VintPrefixed(@in)); DomainSocket sock = peer.GetDomainSocket(); failureInjector.InjectRequestFileDescriptorsFailure(); switch (resp.GetStatus()) { case DataTransferProtos.Status.Success: { byte[] buf = new byte[1]; FileInputStream[] fis = new FileInputStream[2]; sock.RecvFileInputStreams(fis, buf, 0, buf.Length); ShortCircuitReplica replica = null; try { ExtendedBlockId key = new ExtendedBlockId(block.GetBlockId(), block.GetBlockPoolId ()); if (buf[0] == DataTransferProtos.ShortCircuitFdResponse.UseReceiptVerification.GetNumber ()) { Log.Trace("Sending receipt verification byte for slot " + slot); sock.GetOutputStream().Write(0); } replica = new ShortCircuitReplica(key, fis[0], fis[1], cache, Time.MonotonicNow() , slot); return(new ShortCircuitReplicaInfo(replica)); } catch (IOException e) { // This indicates an error reading from disk, or a format error. Since // it's not a socket communication problem, we return null rather than // throwing an exception. Log.Warn(this + ": error creating ShortCircuitReplica.", e); return(null); } finally { if (replica == null) { IOUtils.Cleanup(DFSClient.Log, fis[0], fis[1]); } } goto case DataTransferProtos.Status.ErrorUnsupported; } case DataTransferProtos.Status.ErrorUnsupported: { if (!resp.HasShortCircuitAccessVersion()) { Log.Warn("short-circuit read access is disabled for " + "DataNode " + datanode + ". reason: " + resp.GetMessage()); clientContext.GetDomainSocketFactory().DisableShortCircuitForPath(pathInfo.GetPath ()); } else { Log.Warn("short-circuit read access for the file " + fileName + " is disabled for DataNode " + datanode + ". reason: " + resp.GetMessage()); } return(null); } case DataTransferProtos.Status.ErrorAccessToken: { string msg = "access control error while " + "attempting to set up short-circuit access to " + fileName + resp.GetMessage(); if (Log.IsDebugEnabled()) { Log.Debug(this + ":" + msg); } return(new ShortCircuitReplicaInfo(new SecretManager.InvalidToken(msg))); } default: { Log.Warn(this + ": unknown response code " + resp.GetStatus() + " while attempting to set up short-circuit access. " + resp.GetMessage()); clientContext.GetDomainSocketFactory().DisableShortCircuitForPath(pathInfo.GetPath ()); return(null); } } }