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
9 package org.opendaylight.lispflowmapping.implementation.timebucket.containers;
11 import java.util.ArrayList;
12 import java.util.List;
14 import org.opendaylight.lispflowmapping.implementation.MappingSystem;
15 import org.opendaylight.lispflowmapping.lisp.type.MappingData;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
21 * Created by Shakib Ahmed on 12/1/16.
23 public class TimeBucketWheel {
24 private static final Logger LOG = LoggerFactory.getLogger(TimeBucketWheel.class);
26 private int currentBucketId;
27 private int numberOfBuckets;
28 private long lastRotationTimestamp;
30 private List<TimeBucket> bucketList;
32 private long timeFrame;
34 public TimeBucketWheel(int numberOfBuckets, long mappingRecordValidityInMilis, MappingSystem mappingSystem) {
36 if (numberOfBuckets <= 1) {
37 throw new IllegalArgumentException("Expected number of buckets "
38 + "in TimeBucketMappingContainer to be more 1");
41 this.numberOfBuckets = numberOfBuckets;
43 initializeBucketList(mappingSystem);
44 timeFrame = (long) Math.ceil(1.0 * mappingRecordValidityInMilis / (numberOfBuckets - 1));
45 lastRotationTimestamp = System.currentTimeMillis();
49 private void initializeBucketList(MappingSystem mappingSystem) {
50 bucketList = new ArrayList<>();
51 for (int i = 0; i < numberOfBuckets; i++) {
52 bucketList.add(new TimeBucket(mappingSystem));
56 public int add(Eid key, MappingData mappingData, long timestamp) {
57 clearExpiredMappingAndRotate(timestamp);
58 int timeBucketId = getProperBucketId(timestamp);
60 TimeBucket properTimeBucket = getBucket(timeBucketId);
61 properTimeBucket.add(key, mappingData);
65 public int refreshMappping(Eid key, MappingData newMappingData, long timestamp, int bucketId) {
66 TimeBucket timeBucket = getBucket(bucketId);
67 timeBucket.removeFromBucketOnly(key);
68 return add(key, newMappingData, timestamp);
71 public void removeMapping(Eid key, int bucketId) {
72 TimeBucket timeBucket = getBucket(bucketId);
73 timeBucket.removeFromBucketOnly(key);
76 private int getLastBucketId() {
77 return (currentBucketId - 1 + numberOfBuckets) % numberOfBuckets;
80 private int getProperBucketId(long timestamp) {
81 if (timestamp > lastRotationTimestamp) {
82 //after rotation we are at current
83 return currentBucketId;
86 int relativeBucketId = (int) ((lastRotationTimestamp - timestamp) / timeFrame);
87 if (relativeBucketId >= numberOfBuckets) {
89 LOG.error("The mapping that is being added is too old! This should not happen.");
90 return getLastBucketId();
93 return (this.currentBucketId + relativeBucketId) % numberOfBuckets;
96 private TimeBucket getBucket(int bucketId) {
97 return bucketList.get(bucketId);
100 public void clearExpiredMappingAndRotate() {
101 clearExpiredMappingAndRotate(System.currentTimeMillis());
104 public void clearExpiredMappingAndRotate(long currentStamp) {
105 int numberOfRotationToPerform = getNumberOfRotationsToPerform(currentStamp);
107 long timeForwarded = 0;
109 while (numberOfRotationToPerform > 0) {
110 clearExpiredBucket();
112 numberOfRotationToPerform--;
113 timeForwarded += timeFrame;
116 lastRotationTimestamp = lastRotationTimestamp + timeForwarded;
119 private int getNumberOfRotationsToPerform(long currentStamp) {
120 if (currentStamp < lastRotationTimestamp) {
124 long durationInMillis = (currentStamp - lastRotationTimestamp);
126 int numberOfRotationToPerform = (int) (1.0 * durationInMillis / timeFrame);
127 numberOfRotationToPerform = Math.min(numberOfRotationToPerform, numberOfBuckets);
129 return numberOfRotationToPerform;
132 private void clearExpiredBucket() {
133 int timeoutBucketId = getLastBucketId();
134 clearSpecificBucket(timeoutBucketId);
137 private void clearSpecificBucket(int bucketId) {
138 TimeBucket bucket = getBucket(bucketId);
139 bucket.clearBucket();
142 private void rotate() {
143 currentBucketId = getLastBucketId();