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 }