/// <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;
                    }
                }
            }
            /// <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);
            }