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    }