001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 package org.apache.hadoop.hdfs.shortcircuit;
019
020 import java.io.FileInputStream;
021 import java.io.IOException;
022 import java.util.Iterator;
023
024 import org.apache.hadoop.hdfs.net.DomainPeer;
025 import org.apache.hadoop.hdfs.shortcircuit.DfsClientShmManager.EndpointShmManager;
026 import org.apache.hadoop.net.unix.DomainSocket;
027 import org.apache.hadoop.net.unix.DomainSocketWatcher;
028
029 import com.google.common.base.Preconditions;
030
031 /**
032 * DfsClientShm is a subclass of ShortCircuitShm which is used by the
033 * DfsClient.
034 * When the UNIX domain socket associated with this shared memory segment
035 * closes unexpectedly, we mark the slots inside this segment as disconnected.
036 * ShortCircuitReplica objects that contain disconnected slots are stale,
037 * and will not be used to service new reads or mmap operations.
038 * However, in-progress read or mmap operations will continue to proceed.
039 * Once the last slot is deallocated, the segment can be safely munmapped.
040 *
041 * Slots may also become stale because the associated replica has been deleted
042 * on the DataNode. In this case, the DataNode will clear the 'valid' bit.
043 * The client will then see these slots as stale (see
044 * #{ShortCircuitReplica#isStale}).
045 */
046 public class DfsClientShm extends ShortCircuitShm
047 implements DomainSocketWatcher.Handler {
048 /**
049 * The EndpointShmManager associated with this shared memory segment.
050 */
051 private final EndpointShmManager manager;
052
053 /**
054 * The UNIX domain socket associated with this DfsClientShm.
055 * We rely on the DomainSocketWatcher to close the socket associated with
056 * this DomainPeer when necessary.
057 */
058 private final DomainPeer peer;
059
060 /**
061 * True if this shared memory segment has lost its connection to the
062 * DataNode.
063 *
064 * {@link DfsClientShm#handle} sets this to true.
065 */
066 private boolean disconnected = false;
067
068 DfsClientShm(ShmId shmId, FileInputStream stream, EndpointShmManager manager,
069 DomainPeer peer) throws IOException {
070 super(shmId, stream);
071 this.manager = manager;
072 this.peer = peer;
073 }
074
075 public EndpointShmManager getEndpointShmManager() {
076 return manager;
077 }
078
079 public DomainPeer getPeer() {
080 return peer;
081 }
082
083 /**
084 * Determine if the shared memory segment is disconnected from the DataNode.
085 *
086 * This must be called with the DfsClientShmManager lock held.
087 *
088 * @return True if the shared memory segment is stale.
089 */
090 public synchronized boolean isDisconnected() {
091 return disconnected;
092 }
093
094 /**
095 * Handle the closure of the UNIX domain socket associated with this shared
096 * memory segment by marking this segment as stale.
097 *
098 * If there are no slots associated with this shared memory segment, it will
099 * be freed immediately in this function.
100 */
101 @Override
102 public boolean handle(DomainSocket sock) {
103 manager.unregisterShm(getShmId());
104 synchronized (this) {
105 Preconditions.checkState(!disconnected);
106 disconnected = true;
107 boolean hadSlots = false;
108 for (Iterator<Slot> iter = slotIterator(); iter.hasNext(); ) {
109 Slot slot = iter.next();
110 slot.makeInvalid();
111 hadSlots = true;
112 }
113 if (!hadSlots) {
114 free();
115 }
116 }
117 return true;
118 }
119 }