/// <exception cref="System.IO.IOException"/> internal DfsClientShm(ShortCircuitShm.ShmId shmId, FileInputStream stream, DfsClientShmManager.EndpointShmManager manager, DomainPeer peer) : base(shmId, stream) { this.manager = manager; this.peer = peer; }
/// <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); }
/// <summary>Create the ShortCircuitShm.</summary> /// <param name="shmId">The ID to use.</param> /// <param name="stream"> /// The stream that we're going to use to create this /// shared memory segment. /// Although this is a FileInputStream, we are going to /// assume that the underlying file descriptor is writable /// as well as readable. It would be more appropriate to use /// a RandomAccessFile here, but that class does not have /// any public accessor which returns a FileDescriptor, /// unlike FileInputStream. /// </param> /// <exception cref="System.IO.IOException"/> public ShortCircuitShm(ShortCircuitShm.ShmId shmId, FileInputStream stream) { if (!NativeIO.IsAvailable()) { throw new NotSupportedException("NativeIO is not available."); } if (Shell.Windows) { throw new NotSupportedException("DfsClientShm is not yet implemented for Windows." ); } if (@unsafe == null) { throw new NotSupportedException("can't use DfsClientShm because we failed to " + "load misc.Unsafe."); } this.shmId = shmId; this.mmappedLength = GetUsableLength(stream); this.baseAddress = NativeIO.POSIX.Mmap(stream.GetFD(), NativeIO.POSIX.MmapProtRead | NativeIO.POSIX.MmapProtWrite, true, mmappedLength); this.slots = new ShortCircuitShm.Slot[mmappedLength / BytesPerSlot]; this.allocatedSlots = new BitSet(slots.Length); if (Log.IsTraceEnabled()) { Log.Trace("creating " + this.GetType().Name + "(shmId=" + shmId + ", mmappedLength=" + mmappedLength + ", baseAddress=" + string.Format("%x", baseAddress) + ", slots.length=" + slots.Length + ")"); } }
/// <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>Unregister a shared memory segment.</summary> /// <remarks> /// Unregister a shared memory segment. /// Once a segment is unregistered, we will not allocate any more slots /// inside that segment. /// The DomainSocketWatcher calls this while holding the DomainSocketWatcher /// lock. /// </remarks> /// <param name="shmId">The ID of the shared memory segment to unregister.</param> internal virtual void UnregisterShm(ShortCircuitShm.ShmId shmId) { this._enclosing.Lock.Lock(); try { Sharpen.Collections.Remove(this.full, shmId); Sharpen.Collections.Remove(this.notFull, shmId); } finally { this._enclosing.Lock.Unlock(); } }
public SlotId(ShortCircuitShm.ShmId shmId, int slotIdx) { this.shmId = shmId; this.slotIdx = slotIdx; }