001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.activemq.kaha.impl.container; 018 019import java.io.IOException; 020import java.util.ArrayList; 021import java.util.List; 022 023import org.apache.activemq.kaha.ContainerId; 024import org.apache.activemq.kaha.RuntimeStoreException; 025import org.apache.activemq.kaha.StoreEntry; 026import org.apache.activemq.kaha.impl.DataManager; 027import org.apache.activemq.kaha.impl.data.Item; 028import org.apache.activemq.kaha.impl.index.DiskIndexLinkedList; 029import org.apache.activemq.kaha.impl.index.IndexItem; 030import org.apache.activemq.kaha.impl.index.IndexLinkedList; 031import org.apache.activemq.kaha.impl.index.IndexManager; 032import org.apache.activemq.kaha.impl.index.VMIndexLinkedList; 033import org.slf4j.Logger; 034import org.slf4j.LoggerFactory; 035 036/** 037 * Implementation of a ListContainer 038 * 039 * 040 */ 041public abstract class BaseContainerImpl { 042 043 private static final Logger LOG = LoggerFactory.getLogger(BaseContainerImpl.class); 044 protected IndexItem root; 045 protected IndexLinkedList indexList; 046 protected IndexManager indexManager; 047 protected DataManager dataManager; 048 protected ContainerId containerId; 049 protected boolean loaded; 050 protected boolean closed; 051 protected boolean initialized; 052 protected boolean persistentIndex; 053 054 protected BaseContainerImpl(ContainerId id, IndexItem root, IndexManager indexManager, DataManager dataManager, boolean persistentIndex) { 055 this.containerId = id; 056 this.root = root; 057 this.indexManager = indexManager; 058 this.dataManager = dataManager; 059 this.persistentIndex = persistentIndex; 060 } 061 062 public ContainerId getContainerId() { 063 return containerId; 064 } 065 066 public synchronized void init() { 067 if (!initialized) { 068 if (!initialized) { 069 initialized = true; 070 if (this.indexList == null) { 071 if (persistentIndex) { 072 this.indexList = new DiskIndexLinkedList(indexManager, root); 073 } else { 074 this.indexList = new VMIndexLinkedList(root); 075 } 076 } 077 } 078 } 079 } 080 081 public synchronized void clear() { 082 if (indexList != null) { 083 indexList.clear(); 084 } 085 } 086 087 /** 088 * @return the indexList 089 */ 090 public IndexLinkedList getList() { 091 return indexList; 092 } 093 094 /** 095 * @param indexList the indexList to set 096 */ 097 public void setList(IndexLinkedList indexList) { 098 this.indexList = indexList; 099 } 100 101 public abstract void unload(); 102 103 public abstract void load(); 104 105 public abstract int size(); 106 107 protected abstract Object getValue(StoreEntry currentItem); 108 109 protected abstract void remove(IndexItem currentItem); 110 111 protected final synchronized IndexLinkedList getInternalList() { 112 return indexList; 113 } 114 115 public final synchronized void close() { 116 unload(); 117 closed = true; 118 } 119 120 /* 121 * (non-Javadoc) 122 * 123 * @see org.apache.activemq.kaha.ListContainer#isLoaded() 124 */ 125 public final synchronized boolean isLoaded() { 126 checkClosed(); 127 return loaded; 128 } 129 130 /* 131 * (non-Javadoc) 132 * 133 * @see org.apache.activemq.kaha.ListContainer#getId() 134 */ 135 public final Object getId() { 136 checkClosed(); 137 return containerId.getKey(); 138 } 139 140 public DataManager getDataManager() { 141 return dataManager; 142 } 143 144 public IndexManager getIndexManager() { 145 return indexManager; 146 } 147 148 public final synchronized void expressDataInterest() throws IOException { 149 long nextItem = root.getNextItem(); 150 while (nextItem != Item.POSITION_NOT_SET) { 151 IndexItem item = indexManager.getIndex(nextItem); 152 item.setOffset(nextItem); 153 dataManager.addInterestInFile(item.getKeyFile()); 154 dataManager.addInterestInFile(item.getValueFile()); 155 nextItem = item.getNextItem(); 156 } 157 } 158 159 protected final void doClear() { 160 checkClosed(); 161 loaded = true; 162 List<IndexItem> indexList = new ArrayList<IndexItem>(); 163 try { 164 init(); 165 long nextItem = root.getNextItem(); 166 while (nextItem != Item.POSITION_NOT_SET) { 167 IndexItem item = new IndexItem(); 168 item.setOffset(nextItem); 169 indexList.add(item); 170 nextItem = item.getNextItem(); 171 } 172 root.setNextItem(Item.POSITION_NOT_SET); 173 storeIndex(root); 174 for (int i = 0; i < indexList.size(); i++) { 175 IndexItem item = indexList.get(i); 176 dataManager.removeInterestInFile(item.getKeyFile()); 177 dataManager.removeInterestInFile(item.getValueFile()); 178 indexManager.freeIndex(item); 179 } 180 indexList.clear(); 181 } catch (IOException e) { 182 LOG.error("Failed to clear Container " + getId(), e); 183 throw new RuntimeStoreException(e); 184 } 185 } 186 187 protected final void delete(final IndexItem keyItem, final IndexItem prevItem, final IndexItem nextItem) { 188 if (keyItem != null) { 189 try { 190 root = indexList.getRoot(); 191 IndexItem prev = prevItem == null ? root : prevItem; 192 IndexItem next = (nextItem == null || !nextItem.equals(root)) ? nextItem : null; 193 dataManager.removeInterestInFile(keyItem.getKeyFile()); 194 dataManager.removeInterestInFile(keyItem.getValueFile()); 195 if (next != null) { 196 prev.setNextItem(next.getOffset()); 197 next.setPreviousItem(prev.getOffset()); 198 updateIndexes(next); 199 } else { 200 prev.setNextItem(Item.POSITION_NOT_SET); 201 } 202 updateIndexes(prev); 203 indexManager.freeIndex(keyItem); 204 } catch (IOException e) { 205 LOG.error("Failed to delete " + keyItem, e); 206 throw new RuntimeStoreException(e); 207 } 208 } 209 } 210 211 protected final void checkClosed() { 212 if (closed) { 213 throw new RuntimeStoreException("The store is closed"); 214 } 215 } 216 217 protected void storeIndex(IndexItem item) throws IOException { 218 indexManager.storeIndex(item); 219 } 220 221 protected void updateIndexes(IndexItem item) throws IOException { 222 indexManager.updateIndexes(item); 223 } 224 225 protected final boolean isRoot(StoreEntry item) { 226 return item != null && root != null && (root == item || root.getOffset() == item.getOffset()); 227 // return item != null && indexRoot != null && indexRoot == item; 228 } 229 230}