OpenTSDB源码分析之TSDB-UID表操作(修改)

来源:互联网 发布:mac safari打不开网页 编辑:程序博客网 时间:2024/05/29 12:09

为了方便研究将tsdb-uid表的修改操作抽取出来,代码如下:

package net.opentsdb.tools;import java.nio.charset.Charset;import java.util.ArrayList;import java.util.Arrays;import java.util.concurrent.ConcurrentHashMap;import net.opentsdb.core.TSDB;import net.opentsdb.uid.NoSuchUniqueName;import net.opentsdb.utils.Config;import org.hbase.async.DeleteRequest;import org.hbase.async.GetRequest;import org.hbase.async.HBaseClient;import org.hbase.async.HBaseException;import org.hbase.async.KeyValue;import org.hbase.async.PutRequest;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.stumbleupon.async.Callback;import com.stumbleupon.async.Deferred;public class TestTsdbuidModify {private static final Logger LOG = LoggerFactory.getLogger(TestTsdbuidModify.class);private static final Charset CHARSET = Charset.forName("ISO-8859-1");private static final byte[] ID_FAMILY = toBytes("id");private static final byte[] NAME_FAMILY = toBytes("name");private static final short MAX_ATTEMPTS_PUT = 6;private static final short INITIAL_EXP_BACKOFF_DELAY = 800;private final HBaseClient client;private final byte[] table;private final byte[] kind;private final short id_width;private final ConcurrentHashMap<String, byte[]> name_cache = new ConcurrentHashMap<String, byte[]>();private final ConcurrentHashMap<String, String> id_cache = new ConcurrentHashMap<String, String>();private volatile int cache_hits;private volatile int cache_misses;public TestTsdbuidModify(final HBaseClient client, final byte[] table, final String kind, final int width) {this.client = client;this.table = table;if (kind.isEmpty()) {throw new IllegalArgumentException("Empty string as 'kind' argument!");}this.kind = toBytes(kind);if (width < 1 || width > 8) {throw new IllegalArgumentException("Invalid width: " + width);}this.id_width = (short) width;}public static void main(String[] args) throws Exception {args = new String[] { "rename", "metrics", "a1", "m1" };ArgP argp = new ArgP();CliOptions.addCommon(argp);CliOptions.addVerbose(argp);argp.addOption("--idwidth", "N", "Number of bytes on which the UniqueId is encoded.");argp.addOption("--ignore-case", "Ignore case distinctions when matching a regexp.");argp.addOption("-i", "Short for --ignore-case.");args = CliOptions.parse(argp, args);final byte[] table = argp.get("--uidtable", "tsdb-uid").getBytes();final short idwidth = (argp.has("--idwidth") ? Short.parseShort(argp.get("--idwidth")) : 3);if (idwidth <= 0) {System.exit(3);}final boolean ignorecase = argp.has("--ignore-case") || argp.has("-i");Config config = CliOptions.getConfig(argp);final TSDB tsdb = new TSDB(config);tsdb.getClient().ensureTableExists(config.getString("tsd.storage.hbase.uid_table")).joinUninterruptibly();argp = null;int rc;try {rc = runCommand(tsdb, table, idwidth, ignorecase, args);} finally {try {tsdb.getClient().shutdown().joinUninterruptibly();LOG.info("Gracefully shutdown the TSD");} catch (Exception e) {LOG.error("Unexpected exception while shutting down", e);rc = 42;}}System.exit(rc);}private static int runCommand(final TSDB tsdb, final byte[] table, final short idwidth, final boolean ignorecase, final String[] args) {/** * 新增 assign metrics t1 */if (args[0].equals("assign")) {}/** * 查找 grep t grep metrics t11 */if (args[0].equals("grep")) {}/** * 修改 */if (args[0].equals("rename")) {return rename(tsdb.getClient(), table, idwidth, args);}/** * 删除 */if (args[0].equals("delete")) {}return 0;}private static int rename(final HBaseClient client, final byte[] table, final short idwidth, final String[] args) {final String kind = args[1];final String oldname = args[2];final String newname = args[3];final TestTsdbuidModify uid = new TestTsdbuidModify(client, table, kind, (int) idwidth);try {uid.rename(oldname, newname);} catch (HBaseException e) {LOG.error("error while processing renaming " + oldname + " to " + newname, e);return 3;} catch (NoSuchUniqueName e) {LOG.error(e.getMessage());return 1;}System.out.println(kind + ' ' + oldname + " -> " + newname);return 0;}public void rename(final String oldname, final String newname) {final byte[] row = getId(oldname);//System.out.println(Arrays.toString(row));//System.out.println(bytes2Long(row));//System.exit(0);{byte[] id = null;try {id = getId(newname);} catch (NoSuchUniqueName e) {// OK, we don't want the new name to be assigned.}if (id != null) {throw new IllegalArgumentException("When trying rename(\"" + oldname + "\", \"" + newname + "\") on " + this + ": new name already"+ " assigned ID=" + Arrays.toString(id));}}final byte[] newnameb = toBytes(newname);// Update the reverse mapping first, so that if we die before updating// the forward mapping we don't run the risk of "publishing" a// partially assigned ID. The reverse mapping on its own is harmless// but the forward mapping without reverse mapping is bad.try {final PutRequest reverse_mapping = new PutRequest(table, row, NAME_FAMILY, kind, newnameb);hbasePutWithRetry(reverse_mapping, MAX_ATTEMPTS_PUT, INITIAL_EXP_BACKOFF_DELAY);} catch (HBaseException e) {LOG.error("When trying rename(\"" + oldname + "\", \"" + newname + "\") on " + this + ": Failed to update reverse" + " mapping for ID="+ Arrays.toString(row), e);throw e;}// Now create the new forward mapping.try {final PutRequest forward_mapping = new PutRequest(table, newnameb, ID_FAMILY, kind, row);hbasePutWithRetry(forward_mapping, MAX_ATTEMPTS_PUT, INITIAL_EXP_BACKOFF_DELAY);} catch (HBaseException e) {LOG.error("When trying rename(\"" + oldname + "\", \"" + newname + "\") on " + this + ": Failed to create the"+ " new forward mapping with ID=" + Arrays.toString(row), e);throw e;}// Update cache.addIdToCache(newname, row); // add new name -> IDid_cache.put(fromBytes(row), newname); // update ID -> new namename_cache.remove(oldname); // remove old name -> ID// Delete the old forward mapping.try {final DeleteRequest old_forward_mapping = new DeleteRequest(table, toBytes(oldname), ID_FAMILY, kind);client.delete(old_forward_mapping).joinUninterruptibly();} catch (HBaseException e) {LOG.error("When trying rename(\"" + oldname + "\", \"" + newname + "\") on " + this + ": Failed to remove the"+ " old forward mapping for ID=" + Arrays.toString(row), e);throw e;} catch (Exception e) {final String msg = "Unexpected exception when trying rename(\"" + oldname + "\", \"" + newname + "\") on " + this+ ": Failed to remove the" + " old forward mapping for ID=" + Arrays.toString(row);LOG.error("WTF?  " + msg, e);throw new RuntimeException(msg, e);}// Success!}private void hbasePutWithRetry(final PutRequest put, short attempts, short wait) throws HBaseException {// TO-DO(tsuna): Remove once this code is async.put.setBufferable(false);while (attempts-- > 0) {try {client.put(put).joinUninterruptibly();return;} catch (HBaseException e) {if (attempts > 0) {LOG.error("Put failed, attempts left=" + attempts + " (retrying in " + wait + " ms), put=" + put, e);try {Thread.sleep(wait);} catch (InterruptedException ie) {throw new RuntimeException("interrupted", ie);}wait *= 2;} else {throw e;}} catch (Exception e) {LOG.error("WTF?  Unexpected exception type, put=" + put, e);}}throw new IllegalStateException("This code should never be reached!");}public byte[] getId(final String name) throws NoSuchUniqueName, HBaseException {try {return getIdAsync(name).joinUninterruptibly();} catch (RuntimeException e) {throw e;} catch (Exception e) {throw new RuntimeException("Should never be here", e);}}public Deferred<byte[]> getIdAsync(final String name) {LOG.debug("--先从缓冲区中找---");/** * 先从缓冲区中找 */final byte[] id = getIdFromCache(name);if (id != null) {cache_hits++;return Deferred.fromResult(id);}cache_misses++;class GetIdCB implements Callback<byte[], byte[]> {public byte[] call(final byte[] id) {LOG.debug("---处理2---对getIdFromHBase(name)查找结果进行处理:没找到抛出NoSuchUniqueName异常,找到将id,name放入缓存");if (id == null) {throw new NoSuchUniqueName(kind(), name);}if (id.length != id_width) {throw new IllegalStateException("Found id.length = " + id.length + " which is != " + id_width + " required for '" + kind() + '\'');}addIdToCache(name, id);addNameToCache(id, name);return id;}}/** * 从HBase中查找 没有找到就抛出NoSuchUniqueName异常 找到的话就把(name,id)放入缓冲区 返回id */LOG.debug("---查询2---利用name通过getIdFromHBase(name)查找标签是否存在");Deferred<byte[]> d = getIdFromHBase(name).addCallback(new GetIdCB());return d;}private byte[] getIdFromCache(final String name) {return name_cache.get(name);}/** * 查找表中是否已存在标签 *  * @param name * @return */private Deferred<byte[]> getIdFromHBase(final String name) {return hbaseGet(toBytes(name), ID_FAMILY);}/** * Returns the cell of the specified row key, using family:kind. */private Deferred<byte[]> hbaseGet(final byte[] key, final byte[] family) {final GetRequest get = new GetRequest(table, key);// kind为列簇修饰符metricsget.family(family).qualifier(kind);class GetCB implements Callback<byte[], ArrayList<KeyValue>> {public byte[] call(final ArrayList<KeyValue> row) {LOG.debug("---处理3---对HBaseClient.get(get)方法进行回调处理");if (row == null || row.isEmpty()) {return null;}return row.get(0).value();}}LOG.debug("---查询3---先利用HBaseClient.get(get)来在HBase中的tsdb-uid表中查找有没有行键这name.toByets()的行");return client.get(get).addCallback(new GetCB());}private void addIdToCache(final String name, final byte[] id) {byte[] found = name_cache.get(name);if (found == null) {found = name_cache.putIfAbsent(name, Arrays.copyOf(id, id.length));}if (found != null && !Arrays.equals(found, id)) {throw new IllegalStateException("name=" + name + " => id=" + Arrays.toString(id) + ", already mapped to " + Arrays.toString(found));}}private void addNameToCache(final byte[] id, final String name) {final String key = fromBytes(id);String found = id_cache.get(key);if (found == null) {found = id_cache.putIfAbsent(key, name);}if (found != null && !found.equals(name)) {throw new IllegalStateException("id=" + Arrays.toString(id) + " => name=" + name + ", already mapped to " + found);}}private static byte[] toBytes(final String s) {return s.getBytes(CHARSET);}public String kind() {return fromBytes(kind);}private static String fromBytes(final byte[] b) {return new String(b, CHARSET);}public static long bytes2Long(byte[] byteNum) {      long num = 0;      for (int ix = 0; ix < 3; ++ix) {          num <<= 8;          num |= (byteNum[ix] & 0xff);      }      return num;  }}


原创粉丝点击