e5adb54ad50f8c4cf325b8a217ee79e778907e85
[hc2vpp.git] /
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
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
17 package io.fd.honeycomb.translate.v3po.util.cache;
18
19 import static com.google.common.base.Preconditions.checkNotNull;
20
21 import com.google.common.base.Optional;
22 import io.fd.honeycomb.translate.v3po.util.cache.exceptions.check.DumpCheckFailedException;
23 import io.fd.honeycomb.translate.v3po.util.cache.exceptions.execution.DumpExecutionFailedException;
24 import io.fd.honeycomb.translate.v3po.util.cache.noop.NoopDumpPostProcessingFunction;
25 import io.fd.honeycomb.v3po.translate.ModificationCache;
26 import javax.annotation.Nonnull;
27 import org.openvpp.jvpp.dto.JVppReplyDump;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 /**
32  * Manager responsible for returning Data object dumps<br> either from cache or by invoking specified {@link
33  * EntityDumpExecutor}
34  */
35 public final class DumpCacheManager<T extends JVppReplyDump, U> {
36
37     private static final Logger LOG = LoggerFactory.getLogger(DumpCacheManager.class);
38
39     private final EntityDumpExecutor<T, U> dumpExecutor;
40     private final EntityDumpNonEmptyCheck<T> dumpNonEmptyCheck;
41     private final EntityDumpPostProcessingFunction<T> postProcessor;
42
43     private DumpCacheManager(DumpCacheManagerBuilder<T, U> builder) {
44         this.dumpExecutor = builder.dumpExecutor;
45         this.dumpNonEmptyCheck = builder.dumpNonEmptyCheck;
46         this.postProcessor = builder.postProcessingFunction;
47     }
48
49     /**
50      * Returns {@link Optional<T>} of dump
51      */
52     public Optional<T> getDump(@Nonnull String entityKey, @Nonnull ModificationCache cache)
53             throws DumpExecutionFailedException {
54
55         //this key binding to every log has its logic ,because every customizer have its own cache manager and if
56         //there is need for debugging/fixing some complex call with a lot of data,you can get lost in those logs
57         LOG.debug("Loading dump for KEY[{}]", entityKey);
58
59         T dump = (T) cache.get(entityKey);
60
61         if (dump == null) {
62             LOG.debug("Dump for KEY[{}] not present in cache,invoking dump executor", entityKey);
63
64             dump = dumpExecutor.executeDump();
65
66             //this is not a critical exception, so its only logged here
67             try {
68                 dumpNonEmptyCheck.assertNotEmpty(dump);
69             } catch (DumpCheckFailedException e) {
70                 LOG.warn("Dump for KEY[{}] has been resolved as empty", entityKey, e);
71                 return Optional.absent();
72             }
73
74             //no need to check if post processor active,if wasnt set,default no-op will be used
75             LOG.debug("Post-processing dump for KEY[{}]", entityKey);
76             dump = postProcessor.apply(dump);
77
78             LOG.debug("Caching dump for KEY[{}]", entityKey);
79             cache.put(entityKey, dump);
80             return Optional.of(dump);
81         } else {
82             return Optional.of(dump);
83         }
84     }
85
86     public static final class DumpCacheManagerBuilder<T extends JVppReplyDump, U> {
87
88         private EntityDumpExecutor<T, U> dumpExecutor;
89         private EntityDumpNonEmptyCheck<T> dumpNonEmptyCheck;
90         private EntityDumpPostProcessingFunction<T> postProcessingFunction;
91
92         public DumpCacheManagerBuilder() {
93             //for cases when user does not set specific post-processor
94             postProcessingFunction = new NoopDumpPostProcessingFunction<T>();
95         }
96
97         public DumpCacheManagerBuilder<T, U> withExecutor(@Nonnull EntityDumpExecutor<T, U> executor) {
98             this.dumpExecutor = executor;
99             return this;
100         }
101
102         public DumpCacheManagerBuilder<T, U> withNonEmptyPredicate(@Nonnull EntityDumpNonEmptyCheck<T> check) {
103             this.dumpNonEmptyCheck = check;
104             return this;
105         }
106
107         public DumpCacheManagerBuilder<T, U> withPostProcessingFunction(
108                 EntityDumpPostProcessingFunction<T> postProcessingFunction) {
109             this.postProcessingFunction = postProcessingFunction;
110             return this;
111         }
112
113         public DumpCacheManager<T, U> build() {
114             checkNotNull(dumpExecutor, "Dump executor cannot be null");
115             checkNotNull(dumpNonEmptyCheck, "Dump verifier cannot be null");
116             checkNotNull(postProcessingFunction,
117                     "Dump post-processor cannot be null cannot be null, default implementation is used if its not set");
118
119             return new DumpCacheManager<>(this);
120         }
121     }
122 }
123
124