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.client;
019
020 import java.io.FileInputStream;
021 import java.io.IOException;
022 import java.util.Iterator;
023
024 import org.apache.hadoop.hdfs.ShortCircuitShm;
025 import org.apache.hadoop.hdfs.client.DfsClientShmManager.EndpointShmManager;
026 import org.apache.hadoop.hdfs.net.DomainPeer;
027 import org.apache.hadoop.net.unix.DomainSocket;
028 import org.apache.hadoop.net.unix.DomainSocketWatcher;
029
030 import com.google.common.base.Preconditions;
031
032 /**
033 * DfsClientShm is a subclass of ShortCircuitShm which is used by the
034 * DfsClient.
035 * When the UNIX domain socket associated with this shared memory segment
036 * closes unexpectedly, we mark the slots inside this segment as stale.
037 * ShortCircuitReplica objects that contain stale slots are themselves stale,
038 * and will not be used to service new reads or mmap operations.
039 * However, in-progress read or mmap operations will continue to proceed.
040 * Once the last slot is deallocated, the segment can be safely munmapped.
041 */
042 public class DfsClientShm extends ShortCircuitShm
043 implements DomainSocketWatcher.Handler {
044 /**
045 * The EndpointShmManager associated with this shared memory segment.
046 */
047 private final EndpointShmManager manager;
048
049 /**
050 * The UNIX domain socket associated with this DfsClientShm.
051 * We rely on the DomainSocketWatcher to close the socket associated with
052 * this DomainPeer when necessary.
053 */
054 private final DomainPeer peer;
055
056 /**
057 * True if this shared memory segment has lost its connection to the
058 * DataNode.
059 *
060 * {@link DfsClientShm#handle} sets this to true.
061 */
062 private boolean stale = false;
063
064 DfsClientShm(ShmId shmId, FileInputStream stream, EndpointShmManager manager,
065 DomainPeer peer) throws IOException {
066 super(shmId, stream);
067 this.manager = manager;
068 this.peer = peer;
069 }
070
071 public EndpointShmManager getEndpointShmManager() {
072 return manager;
073 }
074
075 public DomainPeer getPeer() {
076 return peer;
077 }
078
079 /**
080 * Determine if the shared memory segment is stale.
081 *
082 * This must be called with the DfsClientShmManager lock held.
083 *
084 * @return True if the shared memory segment is stale.
085 */
086 public synchronized boolean isStale() {
087 return stale;
088 }
089
090 /**
091 * Handle the closure of the UNIX domain socket associated with this shared
092 * memory segment by marking this segment as stale.
093 *
094 * If there are no slots associated with this shared memory segment, it will
095 * be freed immediately in this function.
096 */
097 @Override
098 public boolean handle(DomainSocket sock) {
099 manager.unregisterShm(getShmId());
100 synchronized (this) {
101 Preconditions.checkState(!stale);
102 stale = true;
103 boolean hadSlots = false;
104 for (Iterator<Slot> iter = slotIterator(); iter.hasNext(); ) {
105 Slot slot = iter.next();
106 slot.makeInvalid();
107 hadSlots = true;
108 }
109 if (!hadSlots) {
110 free();
111 }
112 }
113 return true;
114 }
115 }