2 * Copyright (c) 2016 Cisco Systems, Inc. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.lispflowmapping.implementation.timebucket.containers;
10 import java.util.ArrayList;
11 import java.util.List;
12 import org.opendaylight.lispflowmapping.implementation.MappingSystem;
13 import org.opendaylight.lispflowmapping.lisp.type.MappingData;
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
15 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory;
19 * Created by Shakib Ahmed on 12/1/16.
21 public class TimeBucketWheel {
22 private static final Logger LOG = LoggerFactory.getLogger(TimeBucketWheel.class);
24 private int currentBucketId;
25 private int numberOfBuckets;
26 private long lastRotationTimestamp;
28 private List<TimeBucket> bucketList;
30 private long timeFrame;
32 public TimeBucketWheel(int numberOfBuckets, long mappingRecordValidityInMilis, MappingSystem mappingSystem) {
34 if (numberOfBuckets <= 1) {
35 throw new IllegalArgumentException("Expected number of buckets "
36 + "in TimeBucketMappingContainer to be more 1");
39 this.numberOfBuckets = numberOfBuckets;
41 initializeBucketList(mappingSystem);
42 timeFrame = (long) Math.ceil(1.0 * mappingRecordValidityInMilis / (numberOfBuckets - 1));
43 lastRotationTimestamp = System.currentTimeMillis();
47 private void initializeBucketList(MappingSystem mappingSystem) {
48 bucketList = new ArrayList<>();
49 for (int i = 0; i < numberOfBuckets; i++) {
50 bucketList.add(new TimeBucket(mappingSystem));
54 public int add(Eid key, MappingData mappingData, long timestamp) {
55 clearExpiredMappingAndRotate(timestamp);
56 int timeBucketId = getProperBucketId(timestamp);
58 TimeBucket properTimeBucket = getBucket(timeBucketId);
59 properTimeBucket.add(key, mappingData);
63 public int refreshMappping(Eid key, MappingData newMappingData, long timestamp, int bucketId) {
64 TimeBucket timeBucket = getBucket(bucketId);
65 timeBucket.removeFromBucketOnly(key);
66 return add(key, newMappingData, timestamp);
69 public void removeMapping(Eid key, int bucketId) {
70 TimeBucket timeBucket = getBucket(bucketId);
71 timeBucket.removeFromBucketOnly(key);
74 private int getLastBucketId() {
75 return (currentBucketId - 1 + numberOfBuckets) % numberOfBuckets;
78 private int getProperBucketId(long timestamp) {
79 if (timestamp > lastRotationTimestamp) {
80 //after rotation we are at current
81 return currentBucketId;
84 int relativeBucketId = (int) ((lastRotationTimestamp - timestamp) / timeFrame);
85 if (relativeBucketId >= numberOfBuckets) {
87 LOG.error("The mapping that is being added is too old! This should not happen.");
88 return getLastBucketId();
91 return (this.currentBucketId + relativeBucketId) % numberOfBuckets;
94 private TimeBucket getBucket(int bucketId) {
95 return bucketList.get(bucketId);
98 public void clearExpiredMappingAndRotate() {
99 clearExpiredMappingAndRotate(System.currentTimeMillis());
102 public void clearExpiredMappingAndRotate(long currentStamp) {
103 int numberOfRotationToPerform = getNumberOfRotationsToPerform(currentStamp);
105 long timeForwarded = 0;
107 while (numberOfRotationToPerform > 0) {
108 clearExpiredBucket();
110 numberOfRotationToPerform--;
111 timeForwarded += timeFrame;
114 lastRotationTimestamp = lastRotationTimestamp + timeForwarded;
117 private int getNumberOfRotationsToPerform(long currentStamp) {
118 if (currentStamp < lastRotationTimestamp) {
122 long durationInMillis = (currentStamp - lastRotationTimestamp);
124 int numberOfRotationToPerform = (int) (1.0 * durationInMillis / timeFrame);
125 numberOfRotationToPerform = Math.min(numberOfRotationToPerform, numberOfBuckets);
127 return numberOfRotationToPerform;
130 private void clearExpiredBucket() {
131 int timeoutBucketId = getLastBucketId();
132 clearSpecificBucket(timeoutBucketId);
135 private void clearSpecificBucket(int bucketId) {
136 TimeBucket bucket = getBucket(bucketId);
137 bucket.clearBucket();
140 private void rotate() {
141 currentBucketId = getLastBucketId();