86ded59b346ab6984ca4594826d4d9f5716cb5d4
[lttng-ust.git] /
1 /*
2 * Copyright (C) 2015 - EfficiOS Inc., Alexandre Montplaisir <alexmonthy@efficios.com>
3 *
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 package org.lttng.ust.agent.context;
19
20 import java.io.IOException;
21 import java.util.HashMap;
22 import java.util.Map;
23 import java.util.concurrent.ConcurrentHashMap;
24 import java.util.regex.Matcher;
25 import java.util.regex.Pattern;
26
27 /**
28 * The singleton manager of {@link IContextInfoRetriever} objects.
29 *
30 * @author Alexandre Montplaisir
31 */
32 public final class ContextInfoManager {
33
34 private static final String SHARED_LIBRARY_NAME = "lttng-ust-context-jni";
35
36 private static final Pattern VALID_CONTEXT_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9_\\.]+$");
37
38 private static ContextInfoManager instance;
39
40 private final Map<String, IContextInfoRetriever> contextInfoRetrievers = new ConcurrentHashMap<String, IContextInfoRetriever>();
41 private final Map<String, Long> contextInforRetrieverRefs = new HashMap<String, Long>();
42
43 private final Object retrieverLock = new Object();
44
45 /** Singleton class, constructor should not be accessed directly */
46 private ContextInfoManager() {
47 }
48
49 /**
50 * Get the singleton instance.
51 *
52 * <p>
53 * Usage of this class requires the "liblttng-ust-context-jni.so" native
54 * library to be present on the system and available (passing
55 * -Djava.library.path=path to the JVM may be needed).
56 * </p>
57 *
58 * @return The singleton instance
59 * @throws IOException
60 * If the shared library cannot be found.
61 * @throws SecurityException
62 * We will forward any SecurityExcepion that may be thrown when
63 * trying to load the JNI library.
64 */
65 public static synchronized ContextInfoManager getInstance() throws IOException, SecurityException {
66 if (instance == null) {
67 try {
68 System.loadLibrary(SHARED_LIBRARY_NAME);
69 } catch (UnsatisfiedLinkError e) {
70 throw new IOException(e);
71 }
72 instance = new ContextInfoManager();
73 }
74 return instance;
75 }
76
77 /**
78 * Register a new context info retriever.
79 *
80 * <p>
81 * Each context info retriever is registered with a given "retriever name",
82 * which specifies the namespace of the context elements. This name is
83 * specified separately from the retriever objects, which would allow
84 * register the same retriever under different namespaces for example.
85 * </p>
86 *
87 * <p>
88 * If the method returns false (indicating registration failure), then the
89 * retriever object will *not* be used for context information.
90 * </p>
91 *
92 * @param retrieverName
93 * The name to register to the context retriever object with.
94 * @param contextInfoRetriever
95 * The context info retriever to register
96 * @return True if the retriever was successfully registered, false if there
97 * was an error, for example if a retriever is already registered
98 * with that name.
99 */
100 public boolean registerContextInfoRetriever(String retrieverName, IContextInfoRetriever contextInfoRetriever) {
101 synchronized (retrieverLock) {
102 if (!validateRetrieverName(retrieverName)) {
103 return false;
104 }
105
106 if (contextInfoRetrievers.containsKey(retrieverName)) {
107 /*
108 * There is already a retriever registered with that name,
109 * refuse the new registration.
110 */
111 return false;
112 }
113 /*
114 * Inform LTTng-UST of the new retriever. The names have to start
115 * with "$app." on the UST side!
116 */
117 long ref = LttngContextApi.registerProvider("$app." + retrieverName);
118 if (ref == 0) {
119 return false;
120 }
121
122 contextInfoRetrievers.put(retrieverName, contextInfoRetriever);
123 contextInforRetrieverRefs.put(retrieverName, Long.valueOf(ref));
124
125 return true;
126 }
127 }
128
129 /**
130 * Unregister a previously added context info retriever.
131 *
132 * This method has no effect if the retriever was not already registered.
133 *
134 * @param retrieverName
135 * The context info retriever to unregister
136 * @return True if unregistration was successful, false if there was an
137 * error
138 */
139 public boolean unregisterContextInfoRetriever(String retrieverName) {
140 synchronized (retrieverLock) {
141 if (!contextInfoRetrievers.containsKey(retrieverName)) {
142 /*
143 * There was no retriever registered with that name.
144 */
145 return false;
146 }
147 contextInfoRetrievers.remove(retrieverName);
148 long ref = contextInforRetrieverRefs.remove(retrieverName).longValue();
149
150 /* Unregister the retriever on the UST side too */
151 LttngContextApi.unregisterProvider(ref);
152
153 return true;
154 }
155 }
156
157 /**
158 * Return the context info retriever object registered with the given name.
159 *
160 * @param retrieverName
161 * The retriever name to look for
162 * @return The corresponding retriever object, or <code>null</code> if there
163 * was none
164 */
165 public IContextInfoRetriever getContextInfoRetriever(String retrieverName) {
166 return contextInfoRetrievers.get(retrieverName);
167 }
168
169 /**
170 * Validate that the given retriever name contains only the allowed
171 * characters, which are alphanumerical characters, period "." and
172 * underscore "_". The name must also not start with a number.
173 */
174 private static boolean validateRetrieverName(String contextName) {
175 if (contextName.isEmpty()) {
176 return false;
177 }
178
179 /* First character must not be a number */
180 if (Character.isDigit(contextName.charAt(0))) {
181 return false;
182 }
183
184 /* Validate the other characters of the string */
185 Matcher matcher = VALID_CONTEXT_NAME_PATTERN.matcher(contextName);
186 return matcher.matches();
187 }
188 }
This page took 0.054059 seconds and 3 git commands to generate.