commit | author | age
|
5e3521
|
1 |
/* |
JM |
2 |
* Copyright 2013 gitblit.com. |
|
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 |
package com.gitblit.tickets; |
|
17 |
|
|
18 |
import java.net.URI; |
|
19 |
import java.util.ArrayList; |
|
20 |
import java.util.Collections; |
|
21 |
import java.util.List; |
|
22 |
import java.util.Set; |
4d81c9
|
23 |
import java.util.TreeSet; |
5e3521
|
24 |
|
JM |
25 |
import org.apache.commons.pool2.impl.GenericObjectPoolConfig; |
|
26 |
|
|
27 |
import redis.clients.jedis.Client; |
|
28 |
import redis.clients.jedis.Jedis; |
|
29 |
import redis.clients.jedis.JedisPool; |
|
30 |
import redis.clients.jedis.Protocol; |
|
31 |
import redis.clients.jedis.Transaction; |
|
32 |
import redis.clients.jedis.exceptions.JedisException; |
|
33 |
|
|
34 |
import com.gitblit.Keys; |
|
35 |
import com.gitblit.manager.INotificationManager; |
ba5670
|
36 |
import com.gitblit.manager.IPluginManager; |
5e3521
|
37 |
import com.gitblit.manager.IRepositoryManager; |
JM |
38 |
import com.gitblit.manager.IRuntimeManager; |
|
39 |
import com.gitblit.manager.IUserManager; |
|
40 |
import com.gitblit.models.RepositoryModel; |
|
41 |
import com.gitblit.models.TicketModel; |
|
42 |
import com.gitblit.models.TicketModel.Attachment; |
|
43 |
import com.gitblit.models.TicketModel.Change; |
|
44 |
import com.gitblit.utils.ArrayUtils; |
|
45 |
import com.gitblit.utils.StringUtils; |
c42032
|
46 |
import com.google.inject.Inject; |
JM |
47 |
import com.google.inject.Singleton; |
5e3521
|
48 |
|
JM |
49 |
/** |
|
50 |
* Implementation of a ticket service based on a Redis key-value store. All |
|
51 |
* tickets are persisted in the Redis store so it must be configured for |
|
52 |
* durability otherwise tickets are lost on a flush or restart. Tickets are |
|
53 |
* indexed with Lucene and all queries are executed against the Lucene index. |
|
54 |
* |
|
55 |
* @author James Moger |
|
56 |
* |
|
57 |
*/ |
aa1361
|
58 |
@Singleton |
5e3521
|
59 |
public class RedisTicketService extends ITicketService { |
JM |
60 |
|
|
61 |
private final JedisPool pool; |
|
62 |
|
|
63 |
private enum KeyType { |
|
64 |
journal, ticket, counter |
|
65 |
} |
|
66 |
|
aa1361
|
67 |
@Inject |
5e3521
|
68 |
public RedisTicketService( |
JM |
69 |
IRuntimeManager runtimeManager, |
ba5670
|
70 |
IPluginManager pluginManager, |
5e3521
|
71 |
INotificationManager notificationManager, |
JM |
72 |
IUserManager userManager, |
|
73 |
IRepositoryManager repositoryManager) { |
|
74 |
|
|
75 |
super(runtimeManager, |
ba5670
|
76 |
pluginManager, |
5e3521
|
77 |
notificationManager, |
JM |
78 |
userManager, |
|
79 |
repositoryManager); |
|
80 |
|
|
81 |
String redisUrl = settings.getString(Keys.tickets.redis.url, ""); |
|
82 |
this.pool = createPool(redisUrl); |
|
83 |
} |
|
84 |
|
|
85 |
@Override |
|
86 |
public RedisTicketService start() { |
c42032
|
87 |
log.info("{} started", getClass().getSimpleName()); |
JM |
88 |
if (!isReady()) { |
|
89 |
log.warn("{} is not ready!", getClass().getSimpleName()); |
|
90 |
} |
5e3521
|
91 |
return this; |
JM |
92 |
} |
|
93 |
|
|
94 |
@Override |
|
95 |
protected void resetCachesImpl() { |
|
96 |
} |
|
97 |
|
|
98 |
@Override |
|
99 |
protected void resetCachesImpl(RepositoryModel repository) { |
|
100 |
} |
|
101 |
|
|
102 |
@Override |
|
103 |
protected void close() { |
|
104 |
pool.destroy(); |
|
105 |
} |
|
106 |
|
|
107 |
@Override |
|
108 |
public boolean isReady() { |
|
109 |
return pool != null; |
|
110 |
} |
|
111 |
|
|
112 |
/** |
|
113 |
* Constructs a key for use with a key-value data store. |
|
114 |
* |
|
115 |
* @param key |
|
116 |
* @param repository |
|
117 |
* @param id |
|
118 |
* @return a key |
|
119 |
*/ |
|
120 |
private String key(RepositoryModel repository, KeyType key, String id) { |
|
121 |
StringBuilder sb = new StringBuilder(); |
|
122 |
sb.append(repository.name).append(':'); |
|
123 |
sb.append(key.name()); |
|
124 |
if (!StringUtils.isEmpty(id)) { |
|
125 |
sb.append(':'); |
|
126 |
sb.append(id); |
|
127 |
} |
|
128 |
return sb.toString(); |
|
129 |
} |
|
130 |
|
|
131 |
/** |
|
132 |
* Constructs a key for use with a key-value data store. |
|
133 |
* |
|
134 |
* @param key |
|
135 |
* @param repository |
|
136 |
* @param id |
|
137 |
* @return a key |
|
138 |
*/ |
|
139 |
private String key(RepositoryModel repository, KeyType key, long id) { |
|
140 |
return key(repository, key, "" + id); |
|
141 |
} |
|
142 |
|
|
143 |
private boolean isNull(String value) { |
|
144 |
return value == null || "nil".equals(value); |
|
145 |
} |
|
146 |
|
|
147 |
private String getUrl() { |
|
148 |
Jedis jedis = pool.getResource(); |
|
149 |
try { |
|
150 |
if (jedis != null) { |
|
151 |
Client client = jedis.getClient(); |
|
152 |
return client.getHost() + ":" + client.getPort() + "/" + client.getDB(); |
|
153 |
} |
|
154 |
} catch (JedisException e) { |
|
155 |
pool.returnBrokenResource(jedis); |
|
156 |
jedis = null; |
|
157 |
} finally { |
|
158 |
if (jedis != null) { |
|
159 |
pool.returnResource(jedis); |
|
160 |
} |
|
161 |
} |
|
162 |
return null; |
|
163 |
} |
|
164 |
|
|
165 |
/** |
|
166 |
* Ensures that we have a ticket for this ticket id. |
|
167 |
* |
|
168 |
* @param repository |
|
169 |
* @param ticketId |
|
170 |
* @return true if the ticket exists |
|
171 |
*/ |
|
172 |
@Override |
|
173 |
public boolean hasTicket(RepositoryModel repository, long ticketId) { |
|
174 |
if (ticketId <= 0L) { |
|
175 |
return false; |
|
176 |
} |
|
177 |
Jedis jedis = pool.getResource(); |
|
178 |
if (jedis == null) { |
|
179 |
return false; |
|
180 |
} |
|
181 |
try { |
|
182 |
Boolean exists = jedis.exists(key(repository, KeyType.journal, ticketId)); |
4d537b
|
183 |
return exists != null && exists; |
5e3521
|
184 |
} catch (JedisException e) { |
JM |
185 |
log.error("failed to check hasTicket from Redis @ " + getUrl(), e); |
|
186 |
pool.returnBrokenResource(jedis); |
|
187 |
jedis = null; |
|
188 |
} finally { |
|
189 |
if (jedis != null) { |
|
190 |
pool.returnResource(jedis); |
|
191 |
} |
|
192 |
} |
|
193 |
return false; |
|
194 |
} |
|
195 |
|
4d81c9
|
196 |
@Override |
JM |
197 |
public Set<Long> getIds(RepositoryModel repository) { |
|
198 |
Set<Long> ids = new TreeSet<Long>(); |
|
199 |
Jedis jedis = pool.getResource(); |
|
200 |
try {// account for migrated tickets |
|
201 |
Set<String> keys = jedis.keys(key(repository, KeyType.journal, "*")); |
|
202 |
for (String tkey : keys) { |
|
203 |
// {repo}:journal:{id} |
|
204 |
String id = tkey.split(":")[2]; |
|
205 |
long ticketId = Long.parseLong(id); |
|
206 |
ids.add(ticketId); |
|
207 |
} |
|
208 |
} catch (JedisException e) { |
|
209 |
log.error("failed to assign new ticket id in Redis @ " + getUrl(), e); |
|
210 |
pool.returnBrokenResource(jedis); |
|
211 |
jedis = null; |
|
212 |
} finally { |
|
213 |
if (jedis != null) { |
|
214 |
pool.returnResource(jedis); |
|
215 |
} |
|
216 |
} |
|
217 |
return ids; |
|
218 |
} |
|
219 |
|
5e3521
|
220 |
/** |
JM |
221 |
* Assigns a new ticket id. |
|
222 |
* |
|
223 |
* @param repository |
|
224 |
* @return a new long ticket id |
|
225 |
*/ |
|
226 |
@Override |
|
227 |
public synchronized long assignNewId(RepositoryModel repository) { |
|
228 |
Jedis jedis = pool.getResource(); |
|
229 |
try { |
|
230 |
String key = key(repository, KeyType.counter, null); |
|
231 |
String val = jedis.get(key); |
|
232 |
if (isNull(val)) { |
4d81c9
|
233 |
long lastId = 0; |
JM |
234 |
Set<Long> ids = getIds(repository); |
|
235 |
for (long id : ids) { |
|
236 |
if (id > lastId) { |
|
237 |
lastId = id; |
|
238 |
} |
|
239 |
} |
|
240 |
jedis.set(key, "" + lastId); |
5e3521
|
241 |
} |
JM |
242 |
long ticketNumber = jedis.incr(key); |
|
243 |
return ticketNumber; |
|
244 |
} catch (JedisException e) { |
|
245 |
log.error("failed to assign new ticket id in Redis @ " + getUrl(), e); |
|
246 |
pool.returnBrokenResource(jedis); |
|
247 |
jedis = null; |
|
248 |
} finally { |
|
249 |
if (jedis != null) { |
|
250 |
pool.returnResource(jedis); |
|
251 |
} |
|
252 |
} |
|
253 |
return 0L; |
|
254 |
} |
|
255 |
|
|
256 |
/** |
|
257 |
* Returns all the tickets in the repository. Querying tickets from the |
|
258 |
* repository requires deserializing all tickets. This is an expensive |
|
259 |
* process and not recommended. Tickets should be indexed by Lucene and |
|
260 |
* queries should be executed against that index. |
|
261 |
* |
|
262 |
* @param repository |
|
263 |
* @param filter |
|
264 |
* optional filter to only return matching results |
|
265 |
* @return a list of tickets |
|
266 |
*/ |
|
267 |
@Override |
|
268 |
public List<TicketModel> getTickets(RepositoryModel repository, TicketFilter filter) { |
|
269 |
Jedis jedis = pool.getResource(); |
|
270 |
List<TicketModel> list = new ArrayList<TicketModel>(); |
|
271 |
if (jedis == null) { |
|
272 |
return list; |
|
273 |
} |
|
274 |
try { |
|
275 |
// Deserialize each journal, build the ticket, and optionally filter |
|
276 |
Set<String> keys = jedis.keys(key(repository, KeyType.journal, "*")); |
|
277 |
for (String key : keys) { |
|
278 |
// {repo}:journal:{id} |
|
279 |
String id = key.split(":")[2]; |
|
280 |
long ticketId = Long.parseLong(id); |
|
281 |
List<Change> changes = getJournal(jedis, repository, ticketId); |
|
282 |
if (ArrayUtils.isEmpty(changes)) { |
|
283 |
log.warn("Empty journal for {}:{}", repository, ticketId); |
|
284 |
continue; |
|
285 |
} |
|
286 |
TicketModel ticket = TicketModel.buildTicket(changes); |
|
287 |
ticket.project = repository.projectPath; |
|
288 |
ticket.repository = repository.name; |
|
289 |
ticket.number = ticketId; |
|
290 |
|
|
291 |
// add the ticket, conditionally, to the list |
|
292 |
if (filter == null) { |
|
293 |
list.add(ticket); |
|
294 |
} else { |
|
295 |
if (filter.accept(ticket)) { |
|
296 |
list.add(ticket); |
|
297 |
} |
|
298 |
} |
|
299 |
} |
|
300 |
|
|
301 |
// sort the tickets by creation |
|
302 |
Collections.sort(list); |
|
303 |
} catch (JedisException e) { |
|
304 |
log.error("failed to retrieve tickets from Redis @ " + getUrl(), e); |
|
305 |
pool.returnBrokenResource(jedis); |
|
306 |
jedis = null; |
|
307 |
} finally { |
|
308 |
if (jedis != null) { |
|
309 |
pool.returnResource(jedis); |
|
310 |
} |
|
311 |
} |
|
312 |
return list; |
|
313 |
} |
|
314 |
|
|
315 |
/** |
4d81c9
|
316 |
* Retrieves the ticket from the repository. |
5e3521
|
317 |
* |
JM |
318 |
* @param repository |
|
319 |
* @param ticketId |
|
320 |
* @return a ticket, if it exists, otherwise null |
|
321 |
*/ |
|
322 |
@Override |
|
323 |
protected TicketModel getTicketImpl(RepositoryModel repository, long ticketId) { |
|
324 |
Jedis jedis = pool.getResource(); |
|
325 |
if (jedis == null) { |
|
326 |
return null; |
|
327 |
} |
|
328 |
|
|
329 |
try { |
|
330 |
List<Change> changes = getJournal(jedis, repository, ticketId); |
|
331 |
if (ArrayUtils.isEmpty(changes)) { |
|
332 |
log.warn("Empty journal for {}:{}", repository, ticketId); |
|
333 |
return null; |
|
334 |
} |
|
335 |
TicketModel ticket = TicketModel.buildTicket(changes); |
|
336 |
ticket.project = repository.projectPath; |
|
337 |
ticket.repository = repository.name; |
|
338 |
ticket.number = ticketId; |
|
339 |
log.debug("rebuilt ticket {} from Redis @ {}", ticketId, getUrl()); |
|
340 |
return ticket; |
|
341 |
} catch (JedisException e) { |
|
342 |
log.error("failed to retrieve ticket from Redis @ " + getUrl(), e); |
|
343 |
pool.returnBrokenResource(jedis); |
|
344 |
jedis = null; |
|
345 |
} finally { |
|
346 |
if (jedis != null) { |
|
347 |
pool.returnResource(jedis); |
|
348 |
} |
|
349 |
} |
|
350 |
return null; |
|
351 |
} |
|
352 |
|
|
353 |
/** |
4d81c9
|
354 |
* Retrieves the journal for the ticket. |
JM |
355 |
* |
|
356 |
* @param repository |
|
357 |
* @param ticketId |
|
358 |
* @return a journal, if it exists, otherwise null |
|
359 |
*/ |
|
360 |
@Override |
|
361 |
protected List<Change> getJournalImpl(RepositoryModel repository, long ticketId) { |
|
362 |
Jedis jedis = pool.getResource(); |
|
363 |
if (jedis == null) { |
|
364 |
return null; |
|
365 |
} |
|
366 |
|
|
367 |
try { |
|
368 |
List<Change> changes = getJournal(jedis, repository, ticketId); |
|
369 |
if (ArrayUtils.isEmpty(changes)) { |
|
370 |
log.warn("Empty journal for {}:{}", repository, ticketId); |
|
371 |
return null; |
|
372 |
} |
|
373 |
return changes; |
|
374 |
} catch (JedisException e) { |
|
375 |
log.error("failed to retrieve journal from Redis @ " + getUrl(), e); |
|
376 |
pool.returnBrokenResource(jedis); |
|
377 |
jedis = null; |
|
378 |
} finally { |
|
379 |
if (jedis != null) { |
|
380 |
pool.returnResource(jedis); |
|
381 |
} |
|
382 |
} |
|
383 |
return null; |
|
384 |
} |
|
385 |
|
|
386 |
/** |
5e3521
|
387 |
* Returns the journal for the specified ticket. |
JM |
388 |
* |
|
389 |
* @param repository |
|
390 |
* @param ticketId |
|
391 |
* @return a list of changes |
|
392 |
*/ |
|
393 |
private List<Change> getJournal(Jedis jedis, RepositoryModel repository, long ticketId) throws JedisException { |
|
394 |
if (ticketId <= 0L) { |
|
395 |
return new ArrayList<Change>(); |
|
396 |
} |
|
397 |
List<String> entries = jedis.lrange(key(repository, KeyType.journal, ticketId), 0, -1); |
|
398 |
if (entries.size() > 0) { |
|
399 |
// build a json array from the individual entries |
|
400 |
StringBuilder sb = new StringBuilder(); |
|
401 |
sb.append("["); |
|
402 |
for (String entry : entries) { |
|
403 |
sb.append(entry).append(','); |
|
404 |
} |
|
405 |
sb.setLength(sb.length() - 1); |
|
406 |
sb.append(']'); |
|
407 |
String journal = sb.toString(); |
|
408 |
|
|
409 |
return TicketSerializer.deserializeJournal(journal); |
|
410 |
} |
|
411 |
return new ArrayList<Change>(); |
|
412 |
} |
|
413 |
|
|
414 |
@Override |
|
415 |
public boolean supportsAttachments() { |
|
416 |
return false; |
|
417 |
} |
|
418 |
|
|
419 |
/** |
|
420 |
* Retrieves the specified attachment from a ticket. |
|
421 |
* |
|
422 |
* @param repository |
|
423 |
* @param ticketId |
|
424 |
* @param filename |
|
425 |
* @return an attachment, if found, null otherwise |
|
426 |
*/ |
|
427 |
@Override |
|
428 |
public Attachment getAttachment(RepositoryModel repository, long ticketId, String filename) { |
|
429 |
return null; |
|
430 |
} |
|
431 |
|
|
432 |
/** |
|
433 |
* Deletes a ticket. |
|
434 |
* |
|
435 |
* @param ticket |
|
436 |
* @return true if successful |
|
437 |
*/ |
|
438 |
@Override |
|
439 |
protected boolean deleteTicketImpl(RepositoryModel repository, TicketModel ticket, String deletedBy) { |
|
440 |
boolean success = false; |
|
441 |
if (ticket == null) { |
|
442 |
throw new RuntimeException("must specify a ticket!"); |
|
443 |
} |
|
444 |
|
|
445 |
Jedis jedis = pool.getResource(); |
|
446 |
if (jedis == null) { |
|
447 |
return false; |
|
448 |
} |
|
449 |
|
|
450 |
try { |
|
451 |
// atomically remove ticket |
|
452 |
Transaction t = jedis.multi(); |
|
453 |
t.del(key(repository, KeyType.ticket, ticket.number)); |
|
454 |
t.del(key(repository, KeyType.journal, ticket.number)); |
|
455 |
t.exec(); |
|
456 |
|
|
457 |
success = true; |
|
458 |
log.debug("deleted ticket {} from Redis @ {}", "" + ticket.number, getUrl()); |
|
459 |
} catch (JedisException e) { |
|
460 |
log.error("failed to delete ticket from Redis @ " + getUrl(), e); |
|
461 |
pool.returnBrokenResource(jedis); |
|
462 |
jedis = null; |
|
463 |
} finally { |
|
464 |
if (jedis != null) { |
|
465 |
pool.returnResource(jedis); |
|
466 |
} |
|
467 |
} |
|
468 |
|
|
469 |
return success; |
|
470 |
} |
|
471 |
|
|
472 |
/** |
|
473 |
* Commit a ticket change to the repository. |
|
474 |
* |
|
475 |
* @param repository |
|
476 |
* @param ticketId |
|
477 |
* @param change |
|
478 |
* @return true, if the change was committed |
|
479 |
*/ |
|
480 |
@Override |
|
481 |
protected boolean commitChangeImpl(RepositoryModel repository, long ticketId, Change change) { |
|
482 |
Jedis jedis = pool.getResource(); |
|
483 |
if (jedis == null) { |
|
484 |
return false; |
|
485 |
} |
|
486 |
try { |
|
487 |
List<Change> changes = getJournal(jedis, repository, ticketId); |
|
488 |
changes.add(change); |
|
489 |
// build a new effective ticket from the changes |
|
490 |
TicketModel ticket = TicketModel.buildTicket(changes); |
|
491 |
|
|
492 |
String object = TicketSerializer.serialize(ticket); |
|
493 |
String journal = TicketSerializer.serialize(change); |
|
494 |
|
|
495 |
// atomically store ticket |
|
496 |
Transaction t = jedis.multi(); |
|
497 |
t.set(key(repository, KeyType.ticket, ticketId), object); |
|
498 |
t.rpush(key(repository, KeyType.journal, ticketId), journal); |
|
499 |
t.exec(); |
|
500 |
|
|
501 |
log.debug("updated ticket {} in Redis @ {}", "" + ticketId, getUrl()); |
|
502 |
return true; |
|
503 |
} catch (JedisException e) { |
|
504 |
log.error("failed to update ticket cache in Redis @ " + getUrl(), e); |
|
505 |
pool.returnBrokenResource(jedis); |
|
506 |
jedis = null; |
|
507 |
} finally { |
|
508 |
if (jedis != null) { |
|
509 |
pool.returnResource(jedis); |
|
510 |
} |
|
511 |
} |
|
512 |
return false; |
|
513 |
} |
|
514 |
|
|
515 |
/** |
|
516 |
* Deletes all Tickets for the rpeository from the Redis key-value store. |
|
517 |
* |
|
518 |
*/ |
|
519 |
@Override |
|
520 |
protected boolean deleteAllImpl(RepositoryModel repository) { |
|
521 |
Jedis jedis = pool.getResource(); |
|
522 |
if (jedis == null) { |
|
523 |
return false; |
|
524 |
} |
|
525 |
|
|
526 |
boolean success = false; |
|
527 |
try { |
|
528 |
Set<String> keys = jedis.keys(repository.name + ":*"); |
|
529 |
if (keys.size() > 0) { |
|
530 |
Transaction t = jedis.multi(); |
|
531 |
t.del(keys.toArray(new String[keys.size()])); |
|
532 |
t.exec(); |
|
533 |
} |
|
534 |
success = true; |
|
535 |
} catch (JedisException e) { |
|
536 |
log.error("failed to delete all tickets in Redis @ " + getUrl(), e); |
|
537 |
pool.returnBrokenResource(jedis); |
|
538 |
jedis = null; |
|
539 |
} finally { |
|
540 |
if (jedis != null) { |
|
541 |
pool.returnResource(jedis); |
|
542 |
} |
|
543 |
} |
|
544 |
return success; |
|
545 |
} |
|
546 |
|
|
547 |
@Override |
|
548 |
protected boolean renameImpl(RepositoryModel oldRepository, RepositoryModel newRepository) { |
|
549 |
Jedis jedis = pool.getResource(); |
|
550 |
if (jedis == null) { |
|
551 |
return false; |
|
552 |
} |
|
553 |
|
|
554 |
boolean success = false; |
|
555 |
try { |
|
556 |
Set<String> oldKeys = jedis.keys(oldRepository.name + ":*"); |
|
557 |
Transaction t = jedis.multi(); |
|
558 |
for (String oldKey : oldKeys) { |
|
559 |
String newKey = newRepository.name + oldKey.substring(oldKey.indexOf(':')); |
|
560 |
t.rename(oldKey, newKey); |
|
561 |
} |
|
562 |
t.exec(); |
|
563 |
success = true; |
|
564 |
} catch (JedisException e) { |
|
565 |
log.error("failed to rename tickets in Redis @ " + getUrl(), e); |
|
566 |
pool.returnBrokenResource(jedis); |
|
567 |
jedis = null; |
|
568 |
} finally { |
|
569 |
if (jedis != null) { |
|
570 |
pool.returnResource(jedis); |
|
571 |
} |
|
572 |
} |
|
573 |
return success; |
|
574 |
} |
|
575 |
|
|
576 |
private JedisPool createPool(String url) { |
|
577 |
JedisPool pool = null; |
|
578 |
if (!StringUtils.isEmpty(url)) { |
|
579 |
try { |
|
580 |
URI uri = URI.create(url); |
|
581 |
if (uri.getScheme() != null && uri.getScheme().equalsIgnoreCase("redis")) { |
|
582 |
int database = Protocol.DEFAULT_DATABASE; |
|
583 |
String password = null; |
|
584 |
if (uri.getUserInfo() != null) { |
|
585 |
password = uri.getUserInfo().split(":", 2)[1]; |
|
586 |
} |
|
587 |
if (uri.getPath().indexOf('/') > -1) { |
|
588 |
database = Integer.parseInt(uri.getPath().split("/", 2)[1]); |
|
589 |
} |
|
590 |
pool = new JedisPool(new GenericObjectPoolConfig(), uri.getHost(), uri.getPort(), Protocol.DEFAULT_TIMEOUT, password, database); |
|
591 |
} else { |
|
592 |
pool = new JedisPool(url); |
|
593 |
} |
|
594 |
} catch (JedisException e) { |
|
595 |
log.error("failed to create a Redis pool!", e); |
|
596 |
} |
|
597 |
} |
|
598 |
return pool; |
|
599 |
} |
|
600 |
|
|
601 |
@Override |
|
602 |
public String toString() { |
|
603 |
String url = getUrl(); |
|
604 |
return getClass().getSimpleName() + " (" + (url == null ? "DISABLED" : url) + ")"; |
|
605 |
} |
|
606 |
} |