PageRenderTime 45ms CodeModel.GetById 8ms app.highlight 32ms RepoModel.GetById 1ms app.codeStats 1ms

/hazelcast/src/main/java/com/hazelcast/impl/AbstractRecord.java

https://bitbucket.org/gabral6_gmailcom/hazelcast
Java | 490 lines | 382 code | 86 blank | 22 comment | 112 complexity | 83f6253d1ac3b5368d66057435db161c MD5 | raw file
  1/*
  2 * Copyright (c) 2008-2013, Hazelcast, Inc. All Rights Reserved.
  3 *
  4 * Licensed under the Apache License, Version 2.0 (the "License");
  5 * you may not use this file except in compliance with the License.
  6 * You may obtain a copy of the License at
  7 *
  8 * http://www.apache.org/licenses/LICENSE-2.0
  9 *
 10 * Unless required by applicable law or agreed to in writing, software
 11 * distributed under the License is distributed on an "AS IS" BASIS,
 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 * See the License for the specific language governing permissions and
 14 * limitations under the License.
 15 */
 16
 17package com.hazelcast.impl;
 18
 19import com.hazelcast.impl.base.DistributedLock;
 20import com.hazelcast.impl.base.ScheduledAction;
 21import com.hazelcast.impl.concurrentmap.ValueHolder;
 22import com.hazelcast.nio.Address;
 23import com.hazelcast.nio.Data;
 24import com.hazelcast.util.Clock;
 25
 26import java.util.*;
 27import java.util.concurrent.ConcurrentHashMap;
 28
 29import static com.hazelcast.nio.IOUtil.toObject;
 30
 31@SuppressWarnings("VolatileLongOrDoubleField")
 32public abstract class AbstractRecord extends AbstractSimpleRecord implements Record {
 33
 34    protected volatile int hits = 0;
 35    protected volatile long version = 0;
 36    protected volatile long maxIdleMillis = Long.MAX_VALUE;
 37    protected volatile long writeTime = -1;
 38    protected volatile long removeTime = 0;
 39    protected volatile long lastAccessTime = 0;
 40    protected volatile long lastStoredTime = 0;
 41    protected volatile long creationTime = 0;
 42    protected volatile long expirationTime = Long.MAX_VALUE;
 43    protected volatile long lastUpdateTime = 0;
 44    protected volatile boolean dirty = false;
 45
 46    protected volatile DistributedLock lock = null;
 47
 48    protected volatile OptionalInfo optionalInfo = null;
 49
 50    public AbstractRecord(CMap cmap, int blockId, Data key, long ttl, long maxIdleMillis, long id) {
 51        super(blockId, cmap, id, key);
 52        this.setCreationTime(Clock.currentTimeMillis());
 53        this.setTTL(ttl);
 54        this.maxIdleMillis = (maxIdleMillis == 0) ? Long.MAX_VALUE : maxIdleMillis;
 55        this.setVersion(0);
 56    }
 57
 58    public void runBackupOps() {
 59        final Set<VersionedBackupOp> backupOps = getBackupOps();
 60        if (backupOps != null && !backupOps.isEmpty()) {
 61            Iterator<VersionedBackupOp> it = backupOps.iterator();
 62            while (it.hasNext()) {
 63                VersionedBackupOp bo = it.next();
 64                if (bo.getVersion() < getVersion() + 1) {
 65                    it.remove();
 66                } else if (bo.getVersion() == getVersion() + 1) {
 67                    bo.run();
 68                    setVersion(bo.getVersion());
 69                    it.remove();
 70                } else {
 71                    return;
 72                }
 73            }
 74        }
 75    }
 76
 77    public void addBackupOp(VersionedBackupOp bo) {
 78        if (getBackupOps() == null) {
 79            setBackupOps(new TreeSet<VersionedBackupOp>());
 80        }
 81        getBackupOps().add(bo);
 82        if (getBackupOps().size() > 4) {
 83            forceBackupOps();
 84        }
 85    }
 86
 87    public void forceBackupOps() {
 88        if (getBackupOps() == null) return;
 89        Iterator<VersionedBackupOp> it = getBackupOps().iterator();
 90        while (it.hasNext()) {
 91            VersionedBackupOp v = it.next();
 92            v.run();
 93            setVersion(v.getVersion());
 94            it.remove();
 95        }
 96    }
 97
 98    public Object getKey() {
 99        return toObject(key);
100    }
101
102    public Long[] getIndexes() {
103        if (optionalInfo == null) return null;
104        return getOptionalInfo().indexes;
105    }
106
107    public byte[] getIndexTypes() {
108        if (optionalInfo == null) return null;
109        return getOptionalInfo().indexTypes;
110    }
111
112    public void setIndexes(Long[] indexes, byte[] indexTypes) {
113        if (indexes != null) {
114            this.getOptionalInfo().indexes = indexes;
115            this.getOptionalInfo().indexTypes = indexTypes;
116        }
117    }
118
119    // called from ServiceThread
120    public boolean lock(int threadId, Address address) {
121        invalidateValueCache();
122        final DistributedLock dl = lock;
123        if (dl == null) {
124            lock = new DistributedLock(address, threadId);
125            return true;
126        }
127        if (dl.lock(address, threadId)) {
128            lock = dl;
129            return true;
130        }
131        return false;
132    }
133
134    // called from ServiceThread
135    public boolean unlock(int threadId, Address address) {
136        invalidateValueCache();
137        final DistributedLock dl = lock;
138        return dl == null || dl.unlock(address, threadId);
139    }
140
141    public boolean testLock(int threadId, Address address) {
142        final DistributedLock dl = lock;
143        return dl == null || dl.testLock(threadId, address);
144    }
145
146    public DistributedLock getLock() {
147        return lock;
148    }
149
150    public void setLock(DistributedLock lock) {
151        this.lock = lock;
152    }
153
154    public boolean isLocked() {
155        final DistributedLock dl = lock;
156        return dl != null && dl.isLocked();
157    }
158
159    public int getLockCount() {
160        final DistributedLock dl = lock;
161        return (dl == null) ? 0 : dl.getLockCount();
162    }
163
164    // called from ServiceThread
165    public void clearLock() {
166        lock = null;
167    }
168
169    public Address getLockAddress() {
170        final DistributedLock dl = lock;
171        return (dl == null) ? null : dl.getLockAddress();
172    }
173
174    public long getLockAcquireTime() {
175        final DistributedLock dl = lock;
176        return (dl != null ? dl.getAcquireTime() : -1L);
177    }
178
179    protected void invalidateValueCache() {
180    }
181
182    public void addScheduledAction(ScheduledAction scheduledAction) {
183        if (getScheduledActions() == null) {
184            setScheduledActions(new LinkedList<ScheduledAction>());
185        }
186        getScheduledActions().add(scheduledAction);
187    }
188
189    public boolean isRemovable() {
190        return !isActive() && valueCount() <= 0 && getLockCount() <= 0 && !hasListener()
191               && getScheduledActionCount() == 0 && getBackupOpCount() == 0;
192    }
193
194    public boolean isEvictable() {
195        return getLockCount() <= 0 && !hasListener() && getScheduledActionCount() == 0;
196    }
197
198    public boolean hasListener() {
199        return getListeners() != null && getListeners().size() > 0;
200    }
201
202    public void addListener(Address address, boolean returnValue) {
203        if (getListeners() == null) {
204            setMapListeners(new ConcurrentHashMap<Address, Boolean>(1));
205        }
206        getListeners().put(address, returnValue);
207    }
208
209    public void removeListener(Address address) {
210        if (getListeners() == null) {
211            return;
212        }
213        getListeners().remove(address);
214    }
215
216    public void setLastUpdated() {
217        if (expirationTime != Long.MAX_VALUE && expirationTime > 0) {
218            long ttl = expirationTime - (lastUpdateTime > 0L ? lastUpdateTime : creationTime);
219            setTTL(ttl);
220        }
221        setLastUpdateTime(Clock.currentTimeMillis());
222    }
223
224    public void setLastAccessed() {
225        setLastAccessTime(Clock.currentTimeMillis());
226        incrementHits();
227    }
228
229    public long getExpirationTime() {
230        return expirationTime;
231    }
232
233    public long getRemainingTTL() {
234        if (expirationTime == Long.MAX_VALUE) {
235            return Long.MAX_VALUE;
236        } else {
237            long ttl = expirationTime - Clock.currentTimeMillis();
238            return (ttl < 0) ? 1 : ttl;
239        }
240    }
241
242    public long getRemainingIdle() {
243        if (maxIdleMillis == Long.MAX_VALUE) {
244            return Long.MAX_VALUE;
245        } else {
246            long lastTouch = Math.max(lastAccessTime, creationTime);
247            long idle = Clock.currentTimeMillis() - lastTouch;
248            return maxIdleMillis - idle;
249        }
250    }
251
252    public void setMaxIdle(long idle) {
253        if (idle <= 0 || idle == Long.MAX_VALUE) {
254            maxIdleMillis = Long.MAX_VALUE;
255        } else {
256            maxIdleMillis = idle;
257        }
258    }
259
260    public void setExpirationTime(final long expTime) {
261        if (expTime <= 0) {
262            this.expirationTime = Long.MAX_VALUE;
263        } else {
264            this.expirationTime = expTime;
265        }
266    }
267
268    public void setTTL(long ttl) {
269        if (ttl <= 0 || ttl == Long.MAX_VALUE) {
270            setExpirationTime(Long.MAX_VALUE);
271        } else {
272            setExpirationTime(Clock.currentTimeMillis() + ttl);
273        }
274    }
275
276    public void setInvalid() {
277        expirationTime = (Clock.currentTimeMillis() - 10);
278    }
279
280    public boolean isValid(long now) {
281        if (expirationTime == Long.MAX_VALUE && maxIdleMillis == Long.MAX_VALUE) {
282            return true;
283        }
284        long lastTouch = Math.max(lastUpdateTime, Math.max(lastAccessTime, creationTime));
285        long idle = now - lastTouch;
286        return expirationTime > now && (maxIdleMillis > idle);
287    }
288
289    public boolean isValid() {
290        return active && isValid(Clock.currentTimeMillis());
291    }
292
293    public void markRemoved() {
294        setActive(false);
295        setRemoveTime(Clock.currentTimeMillis());
296    }
297
298    public void setActive() {
299        setRemoveTime(0);
300        setActive(true);
301    }
302
303    public long getVersion() {
304        return version;
305    }
306
307    public void setVersion(long version) {
308        this.version = version;
309    }
310
311    public void incrementVersion() {
312        this.version++;
313    }
314
315    public long getCreationTime() {
316        return creationTime;
317    }
318
319    public void setCreationTime(long newValue) {
320        creationTime = newValue;
321    }
322
323    public long getLastAccessTime() {
324        return lastAccessTime;
325    }
326
327    public void setLastAccessTime(long lastAccessTime) {
328        this.lastAccessTime = lastAccessTime;
329    }
330
331    public long getLastUpdateTime() {
332        return lastUpdateTime;
333    }
334
335    public void setLastUpdateTime(long lastUpdateTime) {
336        this.lastUpdateTime = lastUpdateTime;
337    }
338
339    public int getHits() {
340        return hits;
341    }
342
343    public void incrementHits() {
344        hits++;
345    }
346
347    public void setActive(boolean active) {
348        this.active = active;
349        invalidateValueCache();
350    }
351
352    public Collection<ValueHolder> getMultiValues() {
353        if (optionalInfo == null) return null;
354        return getOptionalInfo().lsMultiValues;
355    }
356
357    public void setMultiValues(Collection<ValueHolder> lsValues) {
358        if (lsValues != null || optionalInfo != null) {
359            this.getOptionalInfo().lsMultiValues = lsValues;
360        }
361    }
362
363    public int getBackupOpCount() {
364        if (optionalInfo == null) return 0;
365        return (getOptionalInfo().backupOps == null) ? 0 : getOptionalInfo().backupOps.size();
366    }
367
368    public SortedSet<VersionedBackupOp> getBackupOps() {
369        return getOptionalInfo().backupOps;
370    }
371
372    public void setBackupOps(SortedSet<VersionedBackupOp> backupOps) {
373        if (backupOps != null) {
374            this.getOptionalInfo().backupOps = backupOps;
375        }
376    }
377
378    public boolean isDirty() {
379        return dirty;
380    }
381
382    public void setDirty(boolean dirty) {
383        this.dirty = dirty;
384    }
385
386    public long getWriteTime() {
387        return writeTime;
388    }
389
390    public void setWriteTime(long writeTime) {
391        this.writeTime = writeTime;
392    }
393
394    public long getRemoveTime() {
395        return removeTime;
396    }
397
398    public void setRemoveTime(long removeTime) {
399        this.removeTime = removeTime;
400    }
401
402    public boolean hasScheduledAction() {
403        return optionalInfo != null && optionalInfo.lsScheduledActions != null &&
404               optionalInfo.lsScheduledActions.size() > 0;
405    }
406
407    public List<ScheduledAction> getScheduledActions() {
408        if (optionalInfo == null) return null;
409        return getOptionalInfo().lsScheduledActions;
410    }
411
412    public void setScheduledActions(List<ScheduledAction> lsScheduledActions) {
413        if (lsScheduledActions != null) {
414            this.getOptionalInfo().lsScheduledActions = lsScheduledActions;
415        }
416    }
417
418    public Map<Address, Boolean> getListeners() {
419        if (optionalInfo == null) return null;
420        return getOptionalInfo().mapListeners;
421    }
422
423    public void setMapListeners(Map<Address, Boolean> mapListeners) {
424        if (mapListeners != null) {
425            this.getOptionalInfo().mapListeners = mapListeners;
426        }
427    }
428
429    public int getScheduledActionCount() {
430        if (optionalInfo == null) return 0;
431        return (getOptionalInfo().lsScheduledActions == null) ? 0 : getOptionalInfo().lsScheduledActions.size();
432    }
433
434    public OptionalInfo getOptionalInfo() {
435        if (optionalInfo == null) {
436            optionalInfo = new OptionalInfo();
437        }
438        return optionalInfo;
439    }
440
441    public void setLastStoredTime(long lastStoredTime) {
442        this.lastStoredTime = lastStoredTime;
443    }
444
445    public long getLastStoredTime() {
446        return lastStoredTime;
447    }
448
449    public boolean isRemoved() {
450        return !active && removeTime > 0;
451    }
452
453    /**
454     * True if record is not removed (map.remove() ...)
455     * and either is not active or not valid or has not value (may because of locking)
456     */
457    public boolean isLoadable() {
458        return !isRemoved() && (!isActive() || !isValid() || !hasValueData());
459    }
460
461    public int hashCode() {
462        return super.hashCode();
463    }
464
465    public boolean equals(Object o) {
466        if (this == o) return true;
467        if (!(o instanceof AbstractRecord)) return false;
468        Record record = (Record) o;
469        return record.getId() == getId();
470    }
471
472    public String toString() {
473        return "Record key=" + getKeyData() + ", active=" + isActive()
474               + ", version=" + getVersion() + ", removable=" + isRemovable()
475               + ", evictable=" + isEvictable() + ", valueCount= " + valueCount()
476               + ", isLocked= " + isLocked() + ", scheduled= " + getScheduledActionCount()
477               ;
478
479    }
480
481    class OptionalInfo {
482
483        volatile Collection<ValueHolder> lsMultiValues = null; // multimap values
484        Long[] indexes; // indexes of the current value;
485        byte[] indexTypes; // index types of the current value;
486        List<ScheduledAction> lsScheduledActions = null;
487        SortedSet<VersionedBackupOp> backupOps = null;
488        Map<Address, Boolean> mapListeners = null;
489    }
490}