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 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 */ 046public 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}