Disable to create duplicate (with same IP Address) PCEP sessions.
[bgpcep.git] / pcep / impl / src / main / java / org / opendaylight / protocol / pcep / impl / PCEPPeerRegistry.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.protocol.pcep.impl;
10
11 import com.google.common.base.Optional;
12 import com.google.common.cache.Cache;
13 import com.google.common.cache.CacheBuilder;
14 import java.util.Arrays;
15 import java.util.HashMap;
16 import java.util.Map;
17 import java.util.concurrent.Callable;
18 import java.util.concurrent.ExecutionException;
19 import java.util.concurrent.TimeUnit;
20 import javax.annotation.concurrent.GuardedBy;
21 import javax.annotation.concurrent.ThreadSafe;
22
23 @ThreadSafe
24 final class PCEPPeerRegistry {
25
26     /**
27      * The maximum lifetime for which we should hold on to a session ID before assuming it is okay to reuse it.
28      */
29     private static final long ID_CACHE_SECONDS = 3 * 3600;
30
31     /**
32      * The total amount of time we should remember a peer having been present, unless some other pressure forces us to
33      * forget about it due to {@link PEER_CACHE_SIZE}.
34      */
35     private static final long PEER_CACHE_SECONDS = 24 * 3600;
36
37     /**
38      * Maximum total number of peers we keep track of. Combined with {@link PEER_CACHE_SECONDS}, this defines how many
39      * peers we can see turn around.
40      */
41     private static final long PEER_CACHE_SIZE = 1024;
42
43     @GuardedBy("this")
44     private final Cache<ByteArrayWrapper, PeerRecord> formerClients = CacheBuilder.newBuilder().expireAfterAccess(PEER_CACHE_SECONDS,
45             TimeUnit.SECONDS).maximumSize(PEER_CACHE_SIZE).build();
46
47     @GuardedBy("this")
48     private final Map<ByteArrayWrapper, SessionReference> sessions = new HashMap<>();
49
50     protected interface SessionReference extends AutoCloseable {
51         Short getSessionId();
52     }
53
54
55     protected synchronized Optional<SessionReference> getSessionReference(final byte[] clientAddress) {
56         final SessionReference sessionReference = this.sessions.get(new ByteArrayWrapper(clientAddress));
57         if (sessionReference != null) {
58             return Optional.of(sessionReference);
59         }
60         return Optional.absent();
61     }
62
63     protected synchronized Optional<SessionReference> removeSessionReference(final byte[] clientAddress) {
64         final SessionReference sessionReference = this.sessions.remove(new ByteArrayWrapper(clientAddress));
65         if (sessionReference != null) {
66             return Optional.of(sessionReference);
67         }
68         return Optional.absent();
69     }
70
71     protected synchronized void putSessionReference(final byte[] clientAddress, final SessionReference sessionReference) {
72         this.sessions.put(new ByteArrayWrapper(clientAddress), sessionReference);
73     }
74
75     protected synchronized Short nextSession(final byte[] clientAddress) throws ExecutionException {
76         final PeerRecord peer = this.formerClients.get(new ByteArrayWrapper(clientAddress), new Callable<PeerRecord>() {
77             @Override
78             public PeerRecord call() {
79                 return new PeerRecord(ID_CACHE_SECONDS, null);
80             }
81         });
82
83         return peer.allocId();
84     }
85
86     protected synchronized void releaseSession(final byte[] clientAddress, final short sessionId) throws ExecutionException {
87         this.formerClients.get(new ByteArrayWrapper(clientAddress), new Callable<PeerRecord>() {
88             @Override
89             public PeerRecord call() {
90                 return new PeerRecord(ID_CACHE_SECONDS, sessionId);
91             }
92         });
93     }
94
95     private static final class ByteArrayWrapper {
96
97         private final byte[] byteArray;
98
99         public ByteArrayWrapper(final byte[] byteArray) {
100             this.byteArray = byteArray;
101         }
102
103         @Override
104         public int hashCode() {
105             return Arrays.hashCode(byteArray);
106         }
107
108         @Override
109         public boolean equals(Object obj) {
110             if (this == obj) {
111                 return true;
112             }
113             if (!(obj instanceof ByteArrayWrapper)) {
114                 return false;
115             }
116             return Arrays.equals(byteArray, ((ByteArrayWrapper) obj).byteArray);
117         }
118     }
119 }