/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.hdfs.client; import java.io.FileInputStream; import java.io.IOException; import java.util.Iterator; import org.apache.hadoop.hdfs.ShortCircuitShm; import org.apache.hadoop.hdfs.client.DfsClientShmManager.EndpointShmManager; import org.apache.hadoop.hdfs.net.DomainPeer; import org.apache.hadoop.net.unix.DomainSocket; import org.apache.hadoop.net.unix.DomainSocketWatcher; import com.google.common.base.Preconditions; /** * DfsClientShm is a subclass of ShortCircuitShm which is used by the * DfsClient. * When the UNIX domain socket associated with this shared memory segment * closes unexpectedly, we mark the slots inside this segment as stale. * ShortCircuitReplica objects that contain stale slots are themselves stale, * and will not be used to service new reads or mmap operations. * However, in-progress read or mmap operations will continue to proceed. * Once the last slot is deallocated, the segment can be safely munmapped. */ public class DfsClientShm extends ShortCircuitShm implements DomainSocketWatcher.Handler { /** * The EndpointShmManager associated with this shared memory segment. */ private final EndpointShmManager manager; /** * The UNIX domain socket associated with this DfsClientShm. * We rely on the DomainSocketWatcher to close the socket associated with * this DomainPeer when necessary. */ private final DomainPeer peer; /** * True if this shared memory segment has lost its connection to the * DataNode. * * {@link DfsClientShm#handle} sets this to true. */ private boolean stale = false; DfsClientShm(ShmId shmId, FileInputStream stream, EndpointShmManager manager, DomainPeer peer) throws IOException { super(shmId, stream); this.manager = manager; this.peer = peer; } public EndpointShmManager getEndpointShmManager() { return manager; } public DomainPeer getPeer() { return peer; } /** * Determine if the shared memory segment is stale. * * This must be called with the DfsClientShmManager lock held. * * @return True if the shared memory segment is stale. */ public synchronized boolean isStale() { return stale; } /** * Handle the closure of the UNIX domain socket associated with this shared * memory segment by marking this segment as stale. * * If there are no slots associated with this shared memory segment, it will * be freed immediately in this function. */ @Override public boolean handle(DomainSocket sock) { manager.unregisterShm(getShmId()); synchronized (this) { Preconditions.checkState(!stale); stale = true; boolean hadSlots = false; for (Iterator<Slot> iter = slotIterator(); iter.hasNext(); ) { Slot slot = iter.next(); slot.makeInvalid(); hadSlots = true; } if (!hadSlots) { free(); } } return true; } }