| /** |
| * 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.shortcircuit; |
| |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.util.Iterator; |
| |
| import org.apache.hadoop.hdfs.net.DomainPeer; |
| import org.apache.hadoop.hdfs.shortcircuit.DfsClientShmManager.EndpointShmManager; |
| 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 disconnected. |
| * ShortCircuitReplica objects that contain disconnected slots are 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. |
| * |
| * Slots may also become stale because the associated replica has been deleted |
| * on the DataNode. In this case, the DataNode will clear the 'valid' bit. |
| * The client will then see these slots as stale (see |
| * #{ShortCircuitReplica#isStale}). |
| */ |
| 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 disconnected = 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 disconnected from the DataNode. |
| * |
| * This must be called with the DfsClientShmManager lock held. |
| * |
| * @return True if the shared memory segment is stale. |
| */ |
| public synchronized boolean isDisconnected() { |
| return disconnected; |
| } |
| |
| /** |
| * 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(!disconnected); |
| disconnected = true; |
| boolean hadSlots = false; |
| for (Iterator<Slot> iter = slotIterator(); iter.hasNext(); ) { |
| Slot slot = iter.next(); |
| slot.makeInvalid(); |
| hadSlots = true; |
| } |
| if (!hadSlots) { |
| free(); |
| } |
| } |
| return true; |
| } |
| } |