├── .gitignore
├── README.md
├── pom.xml
└── src
├── main
├── java
│ └── HBaseIA
│ │ └── TwitBase
│ │ └── AsyncUsersTool.java
└── resources
│ └── simplelogger.properties
└── test
└── java
└── HBaseIA
└── TwitBase
└── AppTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | .classpath
3 | .project
4 | .settings/org.eclipse.core.resources.prefs
5 | .settings/org.eclipse.jdt.core.prefs
6 | .settings/org.eclipse.m2e.core.prefs
7 | *.jar
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # HBase In Action: asynchbase TwitBase client
2 |
3 | [http://www.manning.com/dimidukkhurana][0]
4 |
5 | ## Compiling the project
6 |
7 | Code is managed by maven. Be sure to install maven on your platform
8 | before running these commands. Also be aware that HBase is not yet
9 | supported on the OpenJDK platform, the default JVM installed on most
10 | modern Linux distributions. You'll want to install the Oracle (Sun)
11 | Java 6 runtime and make sure it's configured on your `$PATH` before
12 | you continue. Again, on Ubuntu, you may find the [`oab-java6`][1]
13 | utility to be of use.
14 |
15 | To build a self-contained jar:
16 |
17 | $ mvn package
18 |
19 | The jar created using this by default will allow you to interact with
20 | HBase running in standalone mode on your local machine. If you want
21 | to interact with a remote (possibly fully distributed) HBase
22 | deployment, you need to edit the [`HBaseClient`][2] constructor in the
23 | source and recompile the jar.
24 |
25 | ## Using the asynchbase TwitBase client
26 |
27 | This client uses [asynchbase][3] for communication with HBase. The
28 | client assumes you have an existing TwitBase schema containing User
29 | data. Run the application with this command:
30 |
31 | $ java -cp target/twitbase-async-1.0.0.jar \
32 | HBaseIA.TwitBase.AsyncUsersTool update
33 |
34 | ## License
35 |
36 | Copyright (C) 2012 Nick Dimiduk, Amandeep Khurana
37 |
38 | Distributed under the [Apache License, version 2.0][4], the same as HBase.
39 |
40 | [0]: http://www.manning.com/dimidukkhurana
41 | [1]: https://github.com/flexiondotorg/oab-java6
42 | [2]: http://tsunanet.net/~tsuna/asynchbase/api/org/hbase/async/HBaseClient.html
43 | [3]: https://github.com/OpenTSDB/asynchbase
44 | [4]: http://www.apache.org/licenses/LICENSE-2.0.html
45 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
5 | 4.0.0
6 |
7 | HBaseIA
8 | twitbase-async
9 | 1.0.1
10 |
11 | twitbase-async
12 | http://www.manning.com/dimidukkhurana/
13 |
14 |
15 | UTF-8
16 |
17 |
18 |
19 |
20 | org.hbase
21 | asynchbase
22 | 1.3.2
23 |
24 |
25 | org.slf4j
26 | slf4j-api
27 | 1.6.6
28 |
29 |
30 | org.slf4j
31 | slf4j-simple
32 | 1.6.6
33 |
34 |
35 |
36 | junit
37 | junit
38 | 3.8.1
39 | test
40 |
41 |
42 |
43 |
44 |
45 |
46 | org.apache.maven.plugins
47 | maven-compiler-plugin
48 | 2.5.1
49 |
50 | 1.6
51 | 1.6
52 |
53 |
54 |
55 | maven-assembly-plugin
56 | 2.3
57 |
58 |
59 | jar-with-dependencies
60 | package
61 |
62 | single
63 |
64 |
65 |
66 | jar-with-dependencies
67 |
68 | false
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/src/main/java/HBaseIA/TwitBase/AsyncUsersTool.java:
--------------------------------------------------------------------------------
1 | package HBaseIA.TwitBase;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.UUID;
6 |
7 | import org.hbase.async.HBaseClient;
8 | import org.hbase.async.KeyValue;
9 | import org.hbase.async.PutRequest;
10 | import org.hbase.async.Scanner;
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 |
14 | import com.stumbleupon.async.Callback;
15 | import com.stumbleupon.async.Deferred;
16 | import com.stumbleupon.async.DeferredGroupException;
17 |
18 | public class AsyncUsersTool {
19 |
20 | static final byte[] TABLE_NAME = "users".getBytes();
21 | static final byte[] INFO_FAM = "info".getBytes();
22 | static final byte[] PASSWORD_COL = "password".getBytes();
23 | static final byte[] EMAIL_COL = "email".getBytes();
24 |
25 | public static final String usage =
26 | "usertool action ...\n" +
27 | " help - print this message and exit.\n" +
28 | " update - update passwords for all installed users.\n";
29 |
30 | static byte[] mkNewPassword(byte[] seed) {
31 | UUID u = UUID.randomUUID();
32 | return u.toString().replace("-", "").toLowerCase().getBytes();
33 | }
34 |
35 | static void latency() throws Exception {
36 | if (System.currentTimeMillis() % 3 == 0) {
37 | LOG.info("a thread is napping...");
38 | Thread.sleep(1000);
39 | }
40 | }
41 |
42 | static boolean entropy(Boolean val) {
43 | if (System.currentTimeMillis() % 5 == 0) {
44 | LOG.info("entropy strikes!");
45 | return false;
46 | }
47 | return (val == null) ? Boolean.TRUE : val;
48 | }
49 |
50 | static final class UpdateResult {
51 | public String userId;
52 | public boolean success;
53 | }
54 |
55 | @SuppressWarnings("serial")
56 | static final class UpdateFailedException extends Exception {
57 | public UpdateResult result;
58 |
59 | public UpdateFailedException(UpdateResult r) {
60 | this.result = r;
61 | }
62 | }
63 |
64 | @SuppressWarnings("serial")
65 | static final class SendMessageFailedException extends Exception {
66 | public SendMessageFailedException() {
67 | super("Failed to send message!");
68 | }
69 | }
70 |
71 | static final class InterpretResponse
72 | implements Callback {
73 |
74 | private String userId;
75 |
76 | InterpretResponse(String userId) {
77 | this.userId = userId;
78 | }
79 |
80 | public UpdateResult call(Boolean response) throws Exception {
81 | latency();
82 |
83 | UpdateResult r = new UpdateResult();
84 | r.userId = this.userId;
85 | r.success = entropy(response);
86 | if (!r.success)
87 | throw new UpdateFailedException(r);
88 |
89 | latency();
90 | return r;
91 | }
92 |
93 | @Override
94 | public String toString() {
95 | return String.format("InterpretResponse<%s>", userId);
96 | }
97 | }
98 |
99 | static final class ResultToMessage
100 | implements Callback {
101 |
102 | public String call(UpdateResult r) throws Exception {
103 | latency();
104 | String fmt = "password change for user %s successful.";
105 | latency();
106 | return String.format(fmt, r.userId);
107 | }
108 |
109 | @Override
110 | public String toString() {
111 | return "ResultToMessage";
112 | }
113 | }
114 |
115 | static final class FailureToMessage
116 | implements Callback {
117 |
118 | public String call(UpdateFailedException e) throws Exception {
119 | latency();
120 | String fmt = "%s, your password is unchanged!";
121 | latency();
122 | return String.format(fmt, e.result.userId);
123 | }
124 |
125 | @Override
126 | public String toString() {
127 | return "FailureToMessage";
128 | }
129 | }
130 |
131 | static final class SendMessage
132 | implements Callback {
133 |
134 | public Boolean call(String s) throws Exception {
135 | latency();
136 | if (entropy(null))
137 | throw new SendMessageFailedException();
138 | LOG.info(s);
139 | latency();
140 | return Boolean.TRUE;
141 | }
142 |
143 | @Override
144 | public String toString() {
145 | return "SendMessage";
146 | }
147 | }
148 |
149 | static List> doList(HBaseClient client)
150 | throws Throwable {
151 | final Scanner scanner = client.newScanner(TABLE_NAME);
152 | scanner.setFamily(INFO_FAM);
153 | scanner.setQualifier(PASSWORD_COL);
154 |
155 | ArrayList> rows = null;
156 | ArrayList> workers
157 | = new ArrayList>();
158 | while ((rows = scanner.nextRows(1).joinUninterruptibly()) != null) {
159 | LOG.info("received a page of users.");
160 | for (ArrayList row : rows) {
161 | KeyValue kv = row.get(0);
162 | byte[] expected = kv.value();
163 | String userId = new String(kv.key());
164 | PutRequest put = new PutRequest(
165 | TABLE_NAME, kv.key(), kv.family(),
166 | kv.qualifier(), mkNewPassword(expected));
167 | Deferred d = client.compareAndSet(put, expected)
168 | .addCallback(new InterpretResponse(userId))
169 | .addCallbacks(new ResultToMessage(), new FailureToMessage())
170 | .addCallback(new SendMessage());
171 | workers.add(d);
172 | }
173 | }
174 | return workers;
175 | }
176 |
177 | public static void main(String[] args) throws Throwable {
178 | if (args.length == 0 || "help".equals(args[0])) {
179 | System.out.println(usage);
180 | System.exit(0);
181 | }
182 |
183 | final HBaseClient client = new HBaseClient("localhost");
184 |
185 | if ("update".equals(args[0])) {
186 | Deferred> d = Deferred.group(doList(client));
187 | try {
188 | d.join();
189 | } catch (DeferredGroupException e) {
190 | LOG.info(e.getCause().getMessage());
191 | }
192 | }
193 |
194 | client.shutdown().joinUninterruptibly();
195 | }
196 |
197 | static final Logger LOG = LoggerFactory.getLogger(AsyncUsersTool.class);
198 | }
199 |
--------------------------------------------------------------------------------
/src/main/resources/simplelogger.properties:
--------------------------------------------------------------------------------
1 | org.slf4j.simplelogger.showdatetime = false
2 | org.slf4j.simplelogger.showShortLogname = true
3 |
4 | org.slf4j.simplelogger.log.org.hbase.async = warn
5 | org.slf4j.simplelogger.log.org.apache.zookeeper = warn
6 | org.slf4j.simplelogger.log.org.apache.zookeeper.client = error
7 |
--------------------------------------------------------------------------------
/src/test/java/HBaseIA/TwitBase/AppTest.java:
--------------------------------------------------------------------------------
1 | package HBaseIA.TwitBase;
2 |
3 | import junit.framework.Test;
4 | import junit.framework.TestCase;
5 | import junit.framework.TestSuite;
6 |
7 | /**
8 | * Unit test for simple App.
9 | */
10 | public class AppTest
11 | extends TestCase
12 | {
13 | /**
14 | * Create the test case
15 | *
16 | * @param testName name of the test case
17 | */
18 | public AppTest( String testName )
19 | {
20 | super( testName );
21 | }
22 |
23 | /**
24 | * @return the suite of tests being tested
25 | */
26 | public static Test suite()
27 | {
28 | return new TestSuite( AppTest.class );
29 | }
30 |
31 | /**
32 | * Rigourous Test :-)
33 | */
34 | public void testApp()
35 | {
36 | assertTrue( true );
37 | }
38 | }
39 |
--------------------------------------------------------------------------------