View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.util.compaction;
19  
20  import com.google.common.base.Optional;
21  import com.google.common.collect.Lists;
22  import com.google.common.collect.Maps;
23  import com.google.common.collect.Sets;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Set;
27  import java.util.concurrent.locks.ReadWriteLock;
28  import java.util.concurrent.locks.ReentrantReadWriteLock;
29  import org.apache.hadoop.hbase.ServerName;
30  import org.apache.hadoop.hbase.classification.InterfaceAudience;
31  
32  @InterfaceAudience.Private
33  class ClusterCompactionQueues {
34  
35    private final Map<ServerName, List<MajorCompactionRequest>> compactionQueues;
36    private final Set<ServerName> compactingServers;
37    private final ReadWriteLock lock;
38    private final int concurrentServers;
39  
40    ClusterCompactionQueues(int concurrentServers) {
41      this.concurrentServers = concurrentServers;
42  
43      this.compactionQueues = Maps.newHashMap();
44      this.lock = new ReentrantReadWriteLock();
45      this.compactingServers = Sets.newHashSet();
46    }
47  
48    void addToCompactionQueue(ServerName serverName, MajorCompactionRequest info) {
49      this.lock.writeLock().lock();
50      try {
51        List<MajorCompactionRequest> result = this.compactionQueues.get(serverName);
52        if (result == null) {
53          result = Lists.newArrayList();
54          compactionQueues.put(serverName, result);
55        }
56        result.add(info);
57      } finally {
58        this.lock.writeLock().unlock();
59      }
60    }
61  
62    boolean hasWorkItems() {
63      lock.readLock().lock();
64      try {
65        for (List<MajorCompactionRequest> majorCompactionRequests : this.compactionQueues.values()) {
66          if (!majorCompactionRequests.isEmpty()) {
67            return true;
68          }
69        }
70        return false;
71      } finally {
72        lock.readLock().unlock();
73      }
74    }
75  
76    int getCompactionRequestsLeftToFinish() {
77      lock.readLock().lock();
78      try {
79        int size = 0;
80        for (List<MajorCompactionRequest> queue : compactionQueues.values()) {
81          size += queue.size();
82        }
83        return size;
84      } finally {
85        lock.readLock().unlock();
86      }
87    }
88  
89    List<MajorCompactionRequest> getQueue(ServerName serverName) {
90      lock.readLock().lock();
91      try {
92        return compactionQueues.get(serverName);
93      } finally {
94        lock.readLock().unlock();
95      }
96    }
97  
98    MajorCompactionRequest reserveForCompaction(ServerName serverName) {
99      lock.writeLock().lock();
100     try {
101       if (!compactionQueues.get(serverName).isEmpty()) {
102         compactingServers.add(serverName);
103         return compactionQueues.get(serverName).remove(0);
104       }
105       return null;
106     } finally {
107       lock.writeLock().unlock();
108     }
109   }
110 
111   void releaseCompaction(ServerName serverName) {
112     lock.writeLock().lock();
113     try {
114       compactingServers.remove(serverName);
115     } finally {
116       lock.writeLock().unlock();
117     }
118   }
119 
120   boolean atCapacity() {
121     lock.readLock().lock();
122     try {
123       return compactingServers.size() >= concurrentServers;
124     } finally {
125       lock.readLock().unlock();
126     }
127   }
128 
129   Optional<ServerName> getLargestQueueFromServersNotCompacting() {
130     lock.readLock().lock();
131     try {
132       Sets.SetView<ServerName> difference =
133           Sets.difference(compactionQueues.keySet(), compactingServers);
134       ServerName serverName = null;
135       int maxItems = 0;
136       for (ServerName server : difference) {
137         if (compactionQueues.get(server).size() > maxItems) {
138           maxItems = compactionQueues.get(server).size();
139           serverName = server;
140         }
141       }
142       return Optional.fromNullable(serverName);
143     } finally {
144       lock.readLock().unlock();
145     }
146   }
147 }