Line data Source code
1 : // Copyright (C) 2013 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.index; 16 : 17 : import com.google.common.annotations.VisibleForTesting; 18 : import com.google.common.collect.Lists; 19 : import com.google.gerrit.extensions.events.LifecycleListener; 20 : import java.util.Collection; 21 : import java.util.Collections; 22 : import java.util.concurrent.CopyOnWriteArrayList; 23 : import java.util.concurrent.atomic.AtomicReference; 24 : 25 : /** Dynamic pointers to the index versions used for searching and writing. */ 26 : public abstract class IndexCollection<K, V, I extends Index<K, V>> implements LifecycleListener { 27 : private final CopyOnWriteArrayList<I> writeIndexes; 28 : private final AtomicReference<I> searchIndex; 29 : 30 151 : protected IndexCollection() { 31 151 : this.writeIndexes = Lists.newCopyOnWriteArrayList(); 32 151 : this.searchIndex = new AtomicReference<>(); 33 151 : } 34 : 35 : /** Returns the current search index version. */ 36 : public I getSearchIndex() { 37 151 : return searchIndex.get(); 38 : } 39 : 40 : public void setSearchIndex(I index) { 41 151 : setSearchIndex(index, true); 42 151 : } 43 : 44 : @VisibleForTesting 45 : public void setSearchIndex(I index, boolean closeOld) { 46 151 : I old = searchIndex.getAndSet(index); 47 151 : if (closeOld && old != null && old != index && !writeIndexes.contains(old)) { 48 1 : old.close(); 49 : } 50 151 : } 51 : 52 : public Collection<I> getWriteIndexes() { 53 151 : return Collections.unmodifiableCollection(writeIndexes); 54 : } 55 : 56 : public synchronized I addWriteIndex(I index) { 57 151 : int version = index.getSchema().getVersion(); 58 151 : for (int i = 0; i < writeIndexes.size(); i++) { 59 10 : if (writeIndexes.get(i).getSchema().getVersion() == version) { 60 9 : return writeIndexes.set(i, index); 61 : } 62 : } 63 151 : writeIndexes.add(index); 64 151 : return null; 65 : } 66 : 67 : public synchronized void removeWriteIndex(int version) { 68 1 : int removeIndex = -1; 69 1 : for (int i = 0; i < writeIndexes.size(); i++) { 70 1 : if (writeIndexes.get(i).getSchema().getVersion() == version) { 71 1 : removeIndex = i; 72 1 : break; 73 : } 74 : } 75 1 : if (removeIndex >= 0) { 76 : try { 77 1 : writeIndexes.get(removeIndex).close(); 78 : } finally { 79 1 : writeIndexes.remove(removeIndex); 80 : } 81 : } 82 1 : } 83 : 84 : public I getWriteIndex(int version) { 85 2 : for (I i : writeIndexes) { 86 2 : if (i.getSchema().getVersion() == version) { 87 2 : return i; 88 : } 89 0 : } 90 0 : return null; 91 : } 92 : 93 : @Override 94 151 : public void start() {} 95 : 96 : @Override 97 : public void stop() { 98 151 : I read = searchIndex.get(); 99 151 : if (read != null) { 100 151 : read.close(); 101 : } 102 151 : for (I write : writeIndexes) { 103 151 : if (write != read) { 104 0 : write.close(); 105 : } 106 151 : } 107 151 : } 108 : }