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