001package org.cache2k.impl; 002 003/* 004 * #%L 005 * cache2k core package 006 * %% 007 * Copyright (C) 2000 - 2015 headissue GmbH, Munich 008 * %% 009 * This program is free software: you can redistribute it and/or modify 010 * it under the terms of the GNU General Public License as 011 * published by the Free Software Foundation, either version 3 of the 012 * License, or (at your option) any later version. 013 * 014 * This program is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 017 * GNU General Public License for more details. 018 * 019 * You should have received a copy of the GNU General Public 020 * License along with this program. If not, see 021 * <http://www.gnu.org/licenses/gpl-3.0.html>. 022 * #L% 023 */ 024 025import org.cache2k.ClosableIterator; 026import org.cache2k.impl.threading.Futures; 027import org.cache2k.storage.StorageEntry; 028 029import java.util.concurrent.Future; 030 031/** 032 * Not used now, aggregation prototype 033 * 034 * @author Jens Wilke; created: 2014-06-04 035 */ 036public class AggregationStorageAdapter extends StorageAdapter implements StorageAdapter.Parent { 037 038 StorageAdapter.Parent parent; 039 BaseCache cache; 040 StorageAdapter[] storages; 041 042 @Override 043 public void open() { 044 for (StorageAdapter a : storages) { 045 a.open(); 046 } 047 } 048 049 @Override 050 public void flush() { 051 for (StorageAdapter a : storages) { 052 a.flush(); 053 } 054 } 055 056 @Override 057 public void purge() { 058 for (StorageAdapter a : storages) { 059 a.purge(); 060 } 061 } 062 063 @Override 064 public Future<Void> shutdown() { 065 Futures.WaitForAllFuture<Void> _waitForAll = new Futures.WaitForAllFuture<Void>(); 066 for (StorageAdapter a : storages) { 067 _waitForAll.add(a.shutdown()); 068 } 069 return _waitForAll; 070 } 071 072 @Override 073 public boolean checkStorageStillDisconnectedForClear() { 074 boolean _flag = true; 075 for (StorageAdapter a : storages) { 076 _flag &= a.checkStorageStillDisconnectedForClear(); 077 } 078 return _flag; 079 } 080 081 @Override 082 public void disconnectStorageForClear() { 083 for (StorageAdapter a : storages) { 084 a.disconnectStorageForClear(); 085 } 086 } 087 088 @Override 089 public Future<Void> clearAndReconnect() { 090 Futures.WaitForAllFuture<Void> _waitForAllFuture = new Futures.WaitForAllFuture<Void>(); 091 for (StorageAdapter a : storages) { 092 _waitForAllFuture.add(a.clearAndReconnect()); 093 } 094 return _waitForAllFuture; 095 } 096 097 /** 098 * Send put to all storage instances. Delegated instance can will decide whether 099 * it really puts or not (passivation / no - passivation). The put is called 100 * sequentially. 101 */ 102 @Override 103 public void put(Entry e, long _nextRefreshTime) { 104 for (StorageAdapter a : storages) { 105 a.put(e, _nextRefreshTime); 106 } 107 } 108 109 /** 110 * Ask storages for the entry. The get is tried in the order of the storages until 111 * an entry is found. 112 */ 113 @Override 114 public StorageEntry get(Object key) { 115 for (StorageAdapter a : storages) { 116 StorageEntry e = a.get(key); 117 if (e != null) { 118 return e; 119 } 120 } 121 return null; 122 } 123 124 @Override 125 public boolean remove(Object key) { 126 boolean f = false; 127 for (StorageAdapter a : storages) { 128 f |= a.remove(key); 129 } 130 return f; 131 } 132 133 @Override 134 public void evict(Entry e) { 135 for (StorageAdapter a : storages) { 136 a.evict(e); 137 } 138 } 139 140 @Override 141 public void expire(Entry e) { 142 for (StorageAdapter a : storages) { 143 a.expire(e); 144 } 145 } 146 147 /** 148 * Use the last storage, which should be the biggest and contain 149 * all entries. 150 */ 151 @Override 152 public ClosableIterator<Entry> iterateAll() { 153 return storages[storages.length - 1].iterateAll(); 154 } 155 156 @Override 157 public int getTotalEntryCount() { 158 int cnt = 0; 159 for (StorageAdapter a : storages) { 160 cnt = Math.max(a.getTotalEntryCount(), cnt); 161 } 162 return cnt; 163 } 164 165 @Override 166 public int getAlert() { 167 int _level = 0; 168 for (StorageAdapter a : storages) { 169 if (a.getAlert() > _level) { 170 _level = a.getAlert(); 171 } 172 } 173 return _level; 174 } 175 176 /** Bad thing occurred, we do not what storage is to be blamed. Disable completely */ 177 @Override 178 public void disable(Throwable t) { 179 synchronized (cache.lock) { 180 parent.resetStorage(this, new NoopStorageAdapter(cache)); 181 parent = null; 182 for (StorageAdapter a : storages) { 183 a.disable(t); 184 } 185 } 186 } 187 188 @Override 189 public void resetStorage(final StorageAdapter _current, final StorageAdapter _new) { 190 synchronized (cache.lock) { 191 if (parent == null) { return; } 192 if (_new instanceof NoopStorageAdapter) { 193 if (storages.length == 1) { 194 parent.resetStorage(this, _new); 195 } else { 196 final StorageAdapter[] sa = new StorageAdapter[storages.length - 1]; 197 synchronized (sa) { 198 int i = 0; 199 for (StorageAdapter a : storages) { 200 if (a != _current) { 201 sa[i++] = a; 202 } 203 } 204 } 205 storages = sa; 206 } 207 } else { 208 final StorageAdapter[] sa = new StorageAdapter[storages.length]; 209 synchronized (sa) { 210 int i = 0; 211 for (StorageAdapter a : storages) { 212 if (a != _current) { 213 sa[i++] = a; 214 } else { 215 sa[i++] = _new; 216 } 217 } 218 } 219 storages = sa; 220 } 221 } 222 } 223 224 @Override 225 public Future<Void> cancelTimerJobs() { 226 Futures.WaitForAllFuture<Void> w = new Futures.WaitForAllFuture<Void>(); 227 for (StorageAdapter s : storages) { 228 Future<Void> f = s.cancelTimerJobs(); 229 if (f != null) { 230 w.add(f); 231 } 232 } 233 return w; 234 } 235 236}