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}