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