예제 #1
0
            /// <summary>Pull a slot out of a preexisting shared memory segment.</summary>
            /// <remarks>
            /// Pull a slot out of a preexisting shared memory segment.
            /// Must be called with the manager lock held.
            /// </remarks>
            /// <param name="blockId">The blockId to put inside the Slot object.</param>
            /// <returns>
            /// null if none of our shared memory segments contain a
            /// free slot; the slot object otherwise.
            /// </returns>
            private ShortCircuitShm.Slot AllocSlotFromExistingShm(ExtendedBlockId blockId)
            {
                if (this.notFull.IsEmpty())
                {
                    return(null);
                }
                KeyValuePair <ShortCircuitShm.ShmId, DfsClientShm> entry = this.notFull.FirstEntry
                                                                               ();
                DfsClientShm shm = entry.Value;

                ShortCircuitShm.ShmId shmId = shm.GetShmId();
                ShortCircuitShm.Slot  slot  = shm.AllocAndRegisterSlot(blockId);
                if (shm.IsFull())
                {
                    if (DfsClientShmManager.Log.IsTraceEnabled())
                    {
                        DfsClientShmManager.Log.Trace(this + ": pulled the last slot " + slot.GetSlotIdx(
                                                          ) + " out of " + shm);
                    }
                    DfsClientShm removedShm = Sharpen.Collections.Remove(this.notFull, shmId);
                    Preconditions.CheckState(removedShm == shm);
                    this.full[shmId] = shm;
                }
                else
                {
                    if (DfsClientShmManager.Log.IsTraceEnabled())
                    {
                        DfsClientShmManager.Log.Trace(this + ": pulled slot " + slot.GetSlotIdx() + " out of "
                                                      + shm);
                    }
                }
                return(slot);
            }
예제 #2
0
            /// <summary>Stop tracking a slot.</summary>
            /// <remarks>
            /// Stop tracking a slot.
            /// Must be called with the EndpointShmManager lock held.
            /// </remarks>
            /// <param name="slot">The slot to release.</param>
            internal virtual void FreeSlot(ShortCircuitShm.Slot slot)
            {
                DfsClientShm shm = (DfsClientShm)slot.GetShm();

                shm.UnregisterSlot(slot.GetSlotIdx());
                if (shm.IsDisconnected())
                {
                    // Stale shared memory segments should not be tracked here.
                    Preconditions.CheckState(!this.full.Contains(shm.GetShmId()));
                    Preconditions.CheckState(!this.notFull.Contains(shm.GetShmId()));
                    if (shm.IsEmpty())
                    {
                        if (DfsClientShmManager.Log.IsTraceEnabled())
                        {
                            DfsClientShmManager.Log.Trace(this + ": freeing empty stale " + shm);
                        }
                        shm.Free();
                    }
                }
                else
                {
                    ShortCircuitShm.ShmId shmId = shm.GetShmId();
                    Sharpen.Collections.Remove(this.full, shmId);
                    // The shm can't be full if we just freed a slot.
                    if (shm.IsEmpty())
                    {
                        Sharpen.Collections.Remove(this.notFull, shmId);
                        // If the shared memory segment is now empty, we call shutdown(2) on
                        // the UNIX domain socket associated with it.  The DomainSocketWatcher,
                        // which is watching this socket, will call DfsClientShm#handle,
                        // cleaning up this shared memory segment.
                        //
                        // See #{DfsClientShmManager#domainSocketWatcher} for details about why
                        // we don't want to call DomainSocketWatcher#remove directly here.
                        //
                        // Note that we could experience 'fragmentation' here, where the
                        // DFSClient allocates a bunch of slots in different shared memory
                        // segments, and then frees most of them, but never fully empties out
                        // any segment.  We make some attempt to avoid this fragmentation by
                        // always allocating new slots out of the shared memory segment with the
                        // lowest ID, but it could still occur.  In most workloads,
                        // fragmentation should not be a major concern, since it doesn't impact
                        // peak file descriptor usage or the speed of allocation.
                        if (DfsClientShmManager.Log.IsTraceEnabled())
                        {
                            DfsClientShmManager.Log.Trace(this + ": shutting down UNIX domain socket for " +
                                                          "empty " + shm);
                        }
                        this.Shutdown(shm);
                    }
                    else
                    {
                        this.notFull[shmId] = shm;
                    }
                }
            }
예제 #3
0
            /// <exception cref="System.IO.IOException"/>
            public void Visit(Dictionary <DatanodeInfo, DfsClientShmManager.PerDatanodeVisitorInfo
                                          > info)
            {
                NUnit.Framework.Assert.IsTrue(info[datanode].full.IsEmpty());
                NUnit.Framework.Assert.IsFalse(info[datanode].disabled);
                NUnit.Framework.Assert.AreEqual(1, info[datanode].notFull.Values.Count);
                DfsClientShm shm = info[datanode].notFull.Values.GetEnumerator().Next();

                NUnit.Framework.Assert.IsFalse(shm.IsDisconnected());
            }
예제 #4
0
 internal void Shutdown(DfsClientShm shm)
 {
     try
     {
         shm.GetPeer().GetDomainSocket().Shutdown();
     }
     catch (IOException e)
     {
         DfsClientShmManager.Log.Warn(this + ": error shutting down shm: got IOException calling "
                                      + "shutdown(SHUT_RDWR)", e);
     }
 }
예제 #5
0
 public virtual void FreeSlot(ShortCircuitShm.Slot slot)
 {
     Lock.Lock();
     try
     {
         DfsClientShm shm = (DfsClientShm)slot.GetShm();
         shm.GetEndpointShmManager().FreeSlot(slot);
     }
     finally
     {
         Lock.Unlock();
     }
 }
예제 #6
0
                /// <exception cref="System.IO.IOException"/>
                public void Visit(Dictionary <DatanodeInfo, DfsClientShmManager.PerDatanodeVisitorInfo
                                              > info)
                {
                    NUnit.Framework.Assert.IsTrue(info[datanode].full.IsEmpty());
                    NUnit.Framework.Assert.IsFalse(info[datanode].disabled);
                    NUnit.Framework.Assert.AreEqual(1, info[datanode].notFull.Values.Count);
                    DfsClientShm shm = info[datanode].notFull.Values.GetEnumerator().Next();

                    for (IEnumerator <ShortCircuitShm.Slot> iter = shm.SlotIterator(); iter.HasNext();)
                    {
                        ShortCircuitShm.Slot slot = iter.Next();
                        if (slot.IsValid())
                        {
                            this._enclosing.done.SetValue(false);
                        }
                    }
                }
예제 #7
0
            /// <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);
                }
                }
            }