UrlChecker.java
1 |
package org.dataone.cn.rest; |
---|---|
2 |
|
3 |
import java.util.concurrent.ExecutorService; |
4 |
import java.util.concurrent.Executors; |
5 |
|
6 |
import org.dataone.client.v1.itk.D1Client; |
7 |
import org.dataone.service.exceptions.InvalidToken; |
8 |
import org.dataone.service.exceptions.NotAuthorized; |
9 |
import org.dataone.service.exceptions.NotFound; |
10 |
import org.dataone.service.exceptions.NotImplemented; |
11 |
import org.dataone.service.exceptions.ServiceFailure; |
12 |
import org.dataone.service.types.v1.DescribeResponse; |
13 |
import org.dataone.service.types.v1.Identifier; |
14 |
import org.dataone.service.types.v1.NodeReference; |
15 |
|
16 |
|
17 |
/**
|
18 |
* A proof-of-concept class to address the feature request to confirm the
|
19 |
* navigatability of the location header in the resolve response.
|
20 |
*
|
21 |
* The basic idea is that mn.describe is called against all completed replicas
|
22 |
* concurrently, and use the url of the first sucessful responder.
|
23 |
*
|
24 |
* This call represents the Runnable that sets the state of a shared object,
|
25 |
* another class called ConfirmedNode.
|
26 |
*
|
27 |
* Lightweight implementation requires correct use of
|
28 |
*
|
29 |
* @author rnahf
|
30 |
*
|
31 |
*/
|
32 |
class UrlChecker implements Runnable { |
33 |
|
34 |
/** the amount of time to wait for a response from all of the checks */
|
35 |
static final int CALL_TIMEOUT_MS = 30_000; |
36 |
|
37 |
|
38 |
private NodeReference node;
|
39 |
private Identifier pid;
|
40 |
private ConfirmedNode result;
|
41 |
|
42 |
UrlChecker(NodeReference node, Identifier pid, ConfirmedNode result) { |
43 |
this.node = node;
|
44 |
this.pid = pid;
|
45 |
this.result = result;
|
46 |
} |
47 |
|
48 |
@Override
|
49 |
public void run() { |
50 |
try {
|
51 |
|
52 |
DescribeResponse dr = D1Client.getMN(node).describe(pid); |
53 |
|
54 |
if (dr != null) { |
55 |
result.setNodeReference(node); |
56 |
} |
57 |
} catch (InvalidToken | NotAuthorized | NotImplemented | ServiceFailure
|
58 |
| NotFound e) { |
59 |
; // do nothing except return
|
60 |
} |
61 |
|
62 |
} |
63 |
|
64 |
|
65 |
/**
|
66 |
* this is an example workflow that probably could be improved
|
67 |
* @throws InterruptedException
|
68 |
*/
|
69 |
public static void main() throws InterruptedException { |
70 |
|
71 |
|
72 |
// TODO: the real solution will have to handle the executor lifecycle (shutdown)
|
73 |
// TODO: match the number of threads in the pool to the number of nodes to check,
|
74 |
// since it will never be too many...
|
75 |
// Q: should we use the fork-join pool since thread number should be low
|
76 |
|
77 |
ExecutorService es = Executors.newFixedThreadPool(5); |
78 |
ConfirmedNode cn = new ConfirmedNode();
|
79 |
|
80 |
|
81 |
// create the runnables
|
82 |
UrlChecker curl1 = new UrlChecker(new NodeReference(), new Identifier(), cn); |
83 |
UrlChecker curl2 = new UrlChecker(new NodeReference(), new Identifier(), cn); |
84 |
|
85 |
// run the runnables
|
86 |
es.submit(curl1); |
87 |
es.submit(curl2); |
88 |
|
89 |
// wait for result, but not forever
|
90 |
long start = System.currentTimeMillis(); |
91 |
NodeReference validNode = null;
|
92 |
do {
|
93 |
Thread.sleep(50); |
94 |
validNode = cn.getNodeReference(); |
95 |
if (validNode != null) { |
96 |
break;
|
97 |
} |
98 |
} while (System.currentTimeMillis() - start < CALL_TIMEOUT_MS); |
99 |
|
100 |
} |
101 |
|
102 |
|
103 |
|
104 |
} |