PageRenderTime 47ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/core/src/main/java/org/apache/hadoop/hbase/stargate/RowSpec.java

https://github.com/strategist922/hbase-stargate-1
Java | 380 lines | 320 code | 31 blank | 29 comment | 77 complexity | 20559f8dfd7f31d174b53bf7606c4dd2 MD5 | raw file
  1. /*
  2. * Copyright 2010 The Apache Software Foundation
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one
  5. * or more contributor license agreements. See the NOTICE file
  6. * distributed with this work for additional information
  7. * regarding copyright ownership. The ASF licenses this file
  8. * to you under the Apache License, Version 2.0 (the
  9. * "License"); you may not use this file except in compliance
  10. * with the License. You may obtain a copy of the License at
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS,
  16. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. */
  20. package org.apache.hadoop.hbase.stargate;
  21. import java.util.Collection;
  22. import java.util.TreeSet;
  23. import org.apache.hadoop.hbase.HColumnDescriptor;
  24. import org.apache.hadoop.hbase.HConstants;
  25. import org.apache.hadoop.hbase.util.Bytes;
  26. /**
  27. * Parses a path based row/column/timestamp specification into its component
  28. * elements.
  29. * <p>
  30. *
  31. */
  32. public class RowSpec {
  33. public static final long DEFAULT_START_TIMESTAMP = 0;
  34. public static final long DEFAULT_END_TIMESTAMP = Long.MAX_VALUE;
  35. private byte[] row = HConstants.EMPTY_START_ROW;
  36. private byte[] endRow = null;
  37. private TreeSet<byte[]> columns =
  38. new TreeSet<byte[]>(Bytes.BYTES_COMPARATOR);
  39. private long startTime = DEFAULT_START_TIMESTAMP;
  40. private long endTime = DEFAULT_END_TIMESTAMP;
  41. private int maxVersions = HColumnDescriptor.DEFAULT_VERSIONS;
  42. private int maxValues = Integer.MAX_VALUE;
  43. public RowSpec(String path) throws IllegalArgumentException {
  44. int i = 0;
  45. while (path.charAt(i) == '/') {
  46. i++;
  47. }
  48. i = parseRowKeys(path, i);
  49. i = parseColumns(path, i);
  50. i = parseTimestamp(path, i);
  51. i = parseQueryParams(path, i);
  52. }
  53. private int parseRowKeys(final String path, int i)
  54. throws IllegalArgumentException {
  55. StringBuilder startRow = new StringBuilder();
  56. StringBuilder endRow = null;
  57. try {
  58. char c;
  59. boolean doEndRow = false;
  60. while (i < path.length() && (c = path.charAt(i)) != '/') {
  61. if (c == ',') {
  62. doEndRow = true;
  63. i++;
  64. break;
  65. }
  66. startRow.append(c);
  67. i++;
  68. }
  69. i++;
  70. this.row = Bytes.toBytes(startRow.toString());
  71. if (doEndRow) {
  72. endRow = new StringBuilder();
  73. while ((c = path.charAt(i)) != '/') {
  74. endRow.append(c);
  75. i++;
  76. }
  77. i++;
  78. }
  79. } catch (IndexOutOfBoundsException e) {
  80. throw new IllegalArgumentException(e);
  81. }
  82. // HBase does not support wildcards on row keys so we will emulate a
  83. // suffix glob by synthesizing appropriate start and end row keys for
  84. // table scanning
  85. if (startRow.charAt(startRow.length() - 1) == '*') {
  86. if (endRow != null)
  87. throw new IllegalArgumentException("invalid path: start row "+
  88. "specified with wildcard");
  89. this.row = Bytes.toBytes(startRow.substring(0,
  90. startRow.lastIndexOf("*")));
  91. this.endRow = new byte[this.row.length + 1];
  92. System.arraycopy(this.row, 0, this.endRow, 0, this.row.length);
  93. this.endRow[this.row.length] = (byte)255;
  94. } else {
  95. this.row = Bytes.toBytes(startRow.toString());
  96. if (endRow != null) {
  97. this.endRow = Bytes.toBytes(endRow.toString());
  98. }
  99. }
  100. return i;
  101. }
  102. private int parseColumns(final String path, int i)
  103. throws IllegalArgumentException {
  104. if (i >= path.length()) {
  105. return i;
  106. }
  107. try {
  108. char c;
  109. StringBuilder column = new StringBuilder();
  110. boolean hasColon = false;
  111. while (i < path.length() && (c = path.charAt(i)) != '/') {
  112. if (c == ',') {
  113. if (column.length() < 1) {
  114. throw new IllegalArgumentException("invalid path");
  115. }
  116. if (!hasColon) {
  117. column.append(':');
  118. }
  119. this.columns.add(Bytes.toBytes(column.toString()));
  120. column = new StringBuilder();
  121. hasColon = false;
  122. i++;
  123. continue;
  124. }
  125. if (c == ':') {
  126. hasColon = true;
  127. }
  128. column.append(c);
  129. i++;
  130. }
  131. i++;
  132. // trailing list entry
  133. if (column.length() > 1) {
  134. if (!hasColon) {
  135. column.append(':');
  136. }
  137. this.columns.add(Bytes.toBytes(column.toString()));
  138. }
  139. } catch (IndexOutOfBoundsException e) {
  140. throw new IllegalArgumentException(e);
  141. }
  142. return i;
  143. }
  144. private int parseTimestamp(final String path, int i)
  145. throws IllegalArgumentException {
  146. if (i >= path.length()) {
  147. return i;
  148. }
  149. long time0 = 0, time1 = 0;
  150. try {
  151. char c = 0;
  152. StringBuilder stamp = new StringBuilder();
  153. while (i < path.length()) {
  154. c = path.charAt(i);
  155. if (c == '/' || c == ',') {
  156. break;
  157. }
  158. stamp.append(c);
  159. i++;
  160. }
  161. try {
  162. time0 = Long.valueOf(stamp.toString());
  163. } catch (NumberFormatException e) {
  164. throw new IllegalArgumentException(e);
  165. }
  166. if (c == ',') {
  167. stamp = new StringBuilder();
  168. i++;
  169. while (i < path.length() && ((c = path.charAt(i)) != '/')) {
  170. stamp.append(c);
  171. i++;
  172. }
  173. try {
  174. time1 = Long.valueOf(stamp.toString());
  175. } catch (NumberFormatException e) {
  176. throw new IllegalArgumentException(e);
  177. }
  178. }
  179. if (c == '/') {
  180. i++;
  181. }
  182. } catch (IndexOutOfBoundsException e) {
  183. throw new IllegalArgumentException(e);
  184. }
  185. if (time1 != 0) {
  186. startTime = time0;
  187. endTime = time1;
  188. } else {
  189. endTime = time0;
  190. }
  191. return i;
  192. }
  193. private int parseQueryParams(final String path, int i) {
  194. while (i < path.length()) {
  195. char c = path.charAt(i);
  196. if (c != '?' && c != '&') {
  197. break;
  198. }
  199. if (++i > path.length()) {
  200. break;
  201. }
  202. char what = path.charAt(i);
  203. if (++i > path.length()) {
  204. break;
  205. }
  206. c = path.charAt(i);
  207. if (c != '=') {
  208. throw new IllegalArgumentException("malformed query parameter");
  209. }
  210. if (++i > path.length()) {
  211. break;
  212. }
  213. switch (what) {
  214. case 'm': {
  215. StringBuilder sb = new StringBuilder();
  216. while (i <= path.length()) {
  217. c = path.charAt(i);
  218. if (c < '0' || c > '9') {
  219. i--;
  220. break;
  221. }
  222. sb.append(c);
  223. }
  224. maxVersions = Integer.valueOf(sb.toString());
  225. } break;
  226. case 'n': {
  227. StringBuilder sb = new StringBuilder();
  228. while (i <= path.length()) {
  229. c = path.charAt(i);
  230. if (c < '0' || c > '9') {
  231. i--;
  232. break;
  233. }
  234. sb.append(c);
  235. }
  236. maxValues = Integer.valueOf(sb.toString());
  237. } break;
  238. default:
  239. throw new IllegalArgumentException("unknown parameter '" + c + "'");
  240. }
  241. }
  242. return i;
  243. }
  244. public RowSpec(byte[] startRow, byte[] endRow, byte[][] columns,
  245. long startTime, long endTime, int maxVersions) {
  246. this.row = startRow;
  247. this.endRow = endRow;
  248. if (columns != null) {
  249. for (byte[] col: columns) {
  250. this.columns.add(col);
  251. }
  252. }
  253. this.startTime = startTime;
  254. this.endTime = endTime;
  255. this.maxVersions = maxVersions;
  256. }
  257. public RowSpec(byte[] startRow, byte[] endRow, Collection<byte[]> columns,
  258. long startTime, long endTime, int maxVersions) {
  259. this.row = startRow;
  260. this.endRow = endRow;
  261. if (columns != null) {
  262. this.columns.addAll(columns);
  263. }
  264. this.startTime = startTime;
  265. this.endTime = endTime;
  266. this.maxVersions = maxVersions;
  267. }
  268. public boolean isSingleRow() {
  269. return endRow == null;
  270. }
  271. public int getMaxVersions() {
  272. return maxVersions;
  273. }
  274. public void setMaxVersions(final int maxVersions) {
  275. this.maxVersions = maxVersions;
  276. }
  277. public int getMaxValues() {
  278. return maxValues;
  279. }
  280. public void setMaxValues(final int maxValues) {
  281. this.maxValues = maxValues;
  282. }
  283. public boolean hasColumns() {
  284. return !columns.isEmpty();
  285. }
  286. public byte[] getRow() {
  287. return row;
  288. }
  289. public byte[] getStartRow() {
  290. return row;
  291. }
  292. public boolean hasEndRow() {
  293. return endRow != null;
  294. }
  295. public byte[] getEndRow() {
  296. return endRow;
  297. }
  298. public void addColumn(final byte[] column) {
  299. columns.add(column);
  300. }
  301. public byte[][] getColumns() {
  302. return columns.toArray(new byte[columns.size()][]);
  303. }
  304. public boolean hasTimestamp() {
  305. return (startTime == 0) && (endTime != Long.MAX_VALUE);
  306. }
  307. public long getTimestamp() {
  308. return endTime;
  309. }
  310. public long getStartTime() {
  311. return startTime;
  312. }
  313. public void setStartTime(final long startTime) {
  314. this.startTime = startTime;
  315. }
  316. public long getEndTime() {
  317. return endTime;
  318. }
  319. public void setEndTime(long endTime) {
  320. this.endTime = endTime;
  321. }
  322. public String toString() {
  323. StringBuilder result = new StringBuilder();
  324. result.append("{startRow => '");
  325. if (row != null) {
  326. result.append(Bytes.toString(row));
  327. }
  328. result.append("', endRow => '");
  329. if (endRow != null) {
  330. result.append(Bytes.toString(endRow));
  331. }
  332. result.append("', columns => [");
  333. for (byte[] col: columns) {
  334. result.append(" '");
  335. result.append(Bytes.toString(col));
  336. result.append("'");
  337. }
  338. result.append(" ], startTime => ");
  339. result.append(Long.toString(startTime));
  340. result.append(", endTime => ");
  341. result.append(Long.toString(endTime));
  342. result.append(", maxVersions => ");
  343. result.append(Integer.toString(maxVersions));
  344. result.append(", maxValues => ");
  345. result.append(Integer.toString(maxValues));
  346. result.append("}");
  347. return result.toString();
  348. }
  349. }