@Test public void getOrCreateIdPutsReverseMappingFirst() { uid = new UniqueId(client, table, kind, 3); when(client.get(anyGet())) .thenReturn(Deferred.<ArrayList<KeyValue>>fromResult(null)); when(client.atomicIncrement(incrementForRow(MAXID))) .thenReturn(Deferred.fromResult(6L)); when(client.compareAndSet(anyPut(), emptyArray())) .thenReturn(Deferred.fromResult(true)); final byte[] id = { 0, 0, 6 }; final byte[] row = { 'f', 'o', 'o' }; assertArrayEquals(id, uid.getOrCreateId("foo")); final InOrder order = inOrder(client); order.verify(client).get(anyGet()); order.verify(client).atomicIncrement(incrementForRow(MAXID)); order.verify(client).compareAndSet(putForRow(id), emptyArray()); order.verify(client).compareAndSet(putForRow(row), emptyArray()); }
public byte[] getOrCreateId(String name) throws HBaseException { short attempt = MAX_ATTEMPTS_ASSIGN_ID; HBaseException hbe = null; while (attempt-- > 0) { try { return getId(name); } catch (NoSuchUniqueName e) { LOG.info("Creating an ID for kind='" + kind() + "' name='" + name + '\''); } final long id; byte row[]; try { id = client.atomicIncrement(new AtomicIncrementRequest(table, MAXID_ROW, ID_FAMILY, kind)) .joinUninterruptibly(); row = Bytes.fromLong(id); LOG.info("Got ID=" + id + " for kind='" + kind() + "' name='" + name + "'"); if (row.length < idWidth) { throw new IllegalStateException("OMG, row.length = " + row.length + " which is less than " + idWidth + " for id=" + id + " row=" + Arrays.toString(row)); } for (int i = 0; i < row.length - idWidth; i++) { if (row[i] != 0) { final String message = "All Unique IDs for " + kind() + " on " + idWidth + " bytes are already assigned!"; LOG.error("OMG " + message); throw new IllegalStateException(message); } } row = Arrays.copyOfRange(row, row.length - idWidth, row.length); } catch (HBaseException e) { LOG.error("Failed to assign an ID, atomic increment on row=" + Arrays.toString(MAXID_ROW) + " column='" + fromBytes(ID_FAMILY) + ':' + kind() + '\'', e); hbe = e; continue; } catch (IllegalStateException e) { throw e; } catch (Exception e) { LOG.error("WTF? Unexpected exception type when assigning an ID," + " ICV on row=" + Arrays.toString(MAXID_ROW) + " column='" + fromBytes(ID_FAMILY) + ':' + kind() + '\'', e); continue; } try { final PutRequest reverse_mapping = new PutRequest( table, row, NAME_FAMILY, kind, toBytes(name)); if (!client.compareAndSet(reverse_mapping, HBaseClient.EMPTY_ARRAY) .joinUninterruptibly()) { LOG.error("WTF! Failed to CAS reverse mapping: " + reverse_mapping + " -- run an fsck against the UID table!"); } } catch (HBaseException e) { LOG.error("Failed to CAS reverse mapping! ID leaked: " + id + " of kind " + kind(), e); hbe = e; continue; } catch (Exception e) { LOG.error("WTF, should never be here! ID leaked: " + id + " of kind " + kind(), e); continue; } try { final PutRequest forward_mapping = new PutRequest( table, toBytes(name), ID_FAMILY, kind, row); if (!client.compareAndSet(forward_mapping, HBaseClient.EMPTY_ARRAY) .joinUninterruptibly()) { LOG.warn("Race condition: tried to assign ID " + id + " to " + kind() + ":" + name + ", but CAS failed on " + forward_mapping + ", which indicates this UID must have" + " been allocated concurrently by another TSD. So ID " + id + " was leaked."); continue; } } catch (HBaseException e) { LOG.error("Failed to Put reverse mapping! ID leaked: " + id + " of kind " + kind(), e); hbe = e; continue; } catch (Exception e) { LOG.error("WTF, should never be here! ID leaked: " + id + " of kind " + kind(), e); continue; } addIdToCache(name, row); addNameToCache(row, name); return row; } if (hbe == null) { throw new IllegalStateException("Should never happen!"); } LOG.error("Failed to assign an ID for kind='" + kind() + "' name='" + name + "'", hbe); throw hbe; }
UniqueId implements UniqueIdInterface { public byte[] getOrCreateId(String name) throws HBaseException { short attempt = MAX_ATTEMPTS_ASSIGN_ID; HBaseException hbe = null; while (attempt-- > 0) { try { return getId(name); } catch (NoSuchUniqueName e) { LOG.info("Creating an ID for kind='" + kind() + "' name='" + name + '\''); } final long id; byte row[]; try { id = client.atomicIncrement(new AtomicIncrementRequest(table, MAXID_ROW, ID_FAMILY, kind)) .joinUninterruptibly(); row = Bytes.fromLong(id); LOG.info("Got ID=" + id + " for kind='" + kind() + "' name='" + name + "'"); if (row.length < idWidth) { throw new IllegalStateException("OMG, row.length = " + row.length + " which is less than " + idWidth + " for id=" + id + " row=" + Arrays.toString(row)); } for (int i = 0; i < row.length - idWidth; i++) { if (row[i] != 0) { final String message = "All Unique IDs for " + kind() + " on " + idWidth + " bytes are already assigned!"; LOG.error("OMG " + message); throw new IllegalStateException(message); } } row = Arrays.copyOfRange(row, row.length - idWidth, row.length); } catch (HBaseException e) { LOG.error("Failed to assign an ID, atomic increment on row=" + Arrays.toString(MAXID_ROW) + " column='" + fromBytes(ID_FAMILY) + ':' + kind() + '\'', e); hbe = e; continue; } catch (IllegalStateException e) { throw e; } catch (Exception e) { LOG.error("WTF? Unexpected exception type when assigning an ID," + " ICV on row=" + Arrays.toString(MAXID_ROW) + " column='" + fromBytes(ID_FAMILY) + ':' + kind() + '\'', e); continue; } try { final PutRequest reverse_mapping = new PutRequest( table, row, NAME_FAMILY, kind, toBytes(name)); if (!client.compareAndSet(reverse_mapping, HBaseClient.EMPTY_ARRAY) .joinUninterruptibly()) { LOG.error("WTF! Failed to CAS reverse mapping: " + reverse_mapping + " -- run an fsck against the UID table!"); } } catch (HBaseException e) { LOG.error("Failed to CAS reverse mapping! ID leaked: " + id + " of kind " + kind(), e); hbe = e; continue; } catch (Exception e) { LOG.error("WTF, should never be here! ID leaked: " + id + " of kind " + kind(), e); continue; } try { final PutRequest forward_mapping = new PutRequest( table, toBytes(name), ID_FAMILY, kind, row); if (!client.compareAndSet(forward_mapping, HBaseClient.EMPTY_ARRAY) .joinUninterruptibly()) { LOG.warn("Race condition: tried to assign ID " + id + " to " + kind() + ":" + name + ", but CAS failed on " + forward_mapping + ", which indicates this UID must have" + " been allocated concurrently by another TSD. So ID " + id + " was leaked."); continue; } } catch (HBaseException e) { LOG.error("Failed to Put reverse mapping! ID leaked: " + id + " of kind " + kind(), e); hbe = e; continue; } catch (Exception e) { LOG.error("WTF, should never be here! ID leaked: " + id + " of kind " + kind(), e); continue; } addIdToCache(name, row); addNameToCache(row, name); return row; } if (hbe == null) { throw new IllegalStateException("Should never happen!"); } LOG.error("Failed to assign an ID for kind='" + kind() + "' name='" + name + "'", hbe); throw hbe; } }
UniqueId implements UniqueIdInterface { public byte[] getOrCreateId(String name) throws HBaseException { short attempt = MAX_ATTEMPTS_ASSIGN_ID; HBaseException hbe = null; while (attempt-- > 0) { try { return getId(name); } catch (NoSuchUniqueName e) { LOG.info("Creating an ID for kind='" + kind() + "' name='" + name + '\''); } final long id; byte row[]; try { id = client.atomicIncrement(new AtomicIncrementRequest(table, MAXID_ROW, ID_FAMILY, kind)) .joinUninterruptibly(); row = Bytes.fromLong(id); LOG.info("Got ID=" + id + " for kind='" + kind() + "' name='" + name + "'"); if (row.length < idWidth) { throw new IllegalStateException("OMG, row.length = " + row.length + " which is less than " + idWidth + " for id=" + id + " row=" + Arrays.toString(row)); } for (int i = 0; i < row.length - idWidth; i++) { if (row[i] != 0) { final String message = "All Unique IDs for " + kind() + " on " + idWidth + " bytes are already assigned!"; LOG.error("OMG " + message); throw new IllegalStateException(message); } } row = Arrays.copyOfRange(row, row.length - idWidth, row.length); } catch (HBaseException e) { LOG.error("Failed to assign an ID, atomic increment on row=" + Arrays.toString(MAXID_ROW) + " column='" + fromBytes(ID_FAMILY) + ':' + kind() + '\'', e); hbe = e; continue; } catch (IllegalStateException e) { throw e; } catch (Exception e) { LOG.error("WTF? Unexpected exception type when assigning an ID," + " ICV on row=" + Arrays.toString(MAXID_ROW) + " column='" + fromBytes(ID_FAMILY) + ':' + kind() + '\'', e); continue; } try { final PutRequest reverse_mapping = new PutRequest( table, row, NAME_FAMILY, kind, toBytes(name)); if (!client.compareAndSet(reverse_mapping, HBaseClient.EMPTY_ARRAY) .joinUninterruptibly()) { LOG.error("WTF! Failed to CAS reverse mapping: " + reverse_mapping + " -- run an fsck against the UID table!"); } } catch (HBaseException e) { LOG.error("Failed to CAS reverse mapping! ID leaked: " + id + " of kind " + kind(), e); hbe = e; continue; } catch (Exception e) { LOG.error("WTF, should never be here! ID leaked: " + id + " of kind " + kind(), e); continue; } try { final PutRequest forward_mapping = new PutRequest( table, toBytes(name), ID_FAMILY, kind, row); if (!client.compareAndSet(forward_mapping, HBaseClient.EMPTY_ARRAY) .joinUninterruptibly()) { LOG.warn("Race condition: tried to assign ID " + id + " to " + kind() + ":" + name + ", but CAS failed on " + forward_mapping + ", which indicates this UID must have" + " been allocated concurrently by another TSD. So ID " + id + " was leaked."); continue; } } catch (HBaseException e) { LOG.error("Failed to Put reverse mapping! ID leaked: " + id + " of kind " + kind(), e); hbe = e; continue; } catch (Exception e) { LOG.error("WTF, should never be here! ID leaked: " + id + " of kind " + kind(), e); continue; } addIdToCache(name, row); addNameToCache(row, name); return row; } if (hbe == null) { throw new IllegalStateException("Should never happen!"); } LOG.error("Failed to assign an ID for kind='" + kind() + "' name='" + name + "'", hbe); throw hbe; } UniqueId(final HBaseClient client, final byte[] table, final String kind,
                    final int width); }
UniqueId implements UniqueIdInterface { public byte[] getOrCreateId(String name) throws HBaseException { short attempt = MAX_ATTEMPTS_ASSIGN_ID; HBaseException hbe = null; while (attempt-- > 0) { try { return getId(name); } catch (NoSuchUniqueName e) { LOG.info("Creating an ID for kind='" + kind() + "' name='" + name + '\''); } final long id; byte row[]; try { id = client.atomicIncrement(new AtomicIncrementRequest(table, MAXID_ROW, ID_FAMILY, kind)) .joinUninterruptibly(); row = Bytes.fromLong(id); LOG.info("Got ID=" + id + " for kind='" + kind() + "' name='" + name + "'"); if (row.length < idWidth) { throw new IllegalStateException("OMG, row.length = " + row.length + " which is less than " + idWidth + " for id=" + id + " row=" + Arrays.toString(row)); } for (int i = 0; i < row.length - idWidth; i++) { if (row[i] != 0) { final String message = "All Unique IDs for " + kind() + " on " + idWidth + " bytes are already assigned!"; LOG.error("OMG " + message); throw new IllegalStateException(message); } } row = Arrays.copyOfRange(row, row.length - idWidth, row.length); } catch (HBaseException e) { LOG.error("Failed to assign an ID, atomic increment on row=" + Arrays.toString(MAXID_ROW) + " column='" + fromBytes(ID_FAMILY) + ':' + kind() + '\'', e); hbe = e; continue; } catch (IllegalStateException e) { throw e; } catch (Exception e) { LOG.error("WTF? Unexpected exception type when assigning an ID," + " ICV on row=" + Arrays.toString(MAXID_ROW) + " column='" + fromBytes(ID_FAMILY) + ':' + kind() + '\'', e); continue; } try { final PutRequest reverse_mapping = new PutRequest( table, row, NAME_FAMILY, kind, toBytes(name)); if (!client.compareAndSet(reverse_mapping, HBaseClient.EMPTY_ARRAY) .joinUninterruptibly()) { LOG.error("WTF! Failed to CAS reverse mapping: " + reverse_mapping + " -- run an fsck against the UID table!"); } } catch (HBaseException e) { LOG.error("Failed to CAS reverse mapping! ID leaked: " + id + " of kind " + kind(), e); hbe = e; continue; } catch (Exception e) { LOG.error("WTF, should never be here! ID leaked: " + id + " of kind " + kind(), e); continue; } try { final PutRequest forward_mapping = new PutRequest( table, toBytes(name), ID_FAMILY, kind, row); if (!client.compareAndSet(forward_mapping, HBaseClient.EMPTY_ARRAY) .joinUninterruptibly()) { LOG.warn("Race condition: tried to assign ID " + id + " to " + kind() + ":" + name + ", but CAS failed on " + forward_mapping + ", which indicates this UID must have" + " been allocated concurrently by another TSD. So ID " + id + " was leaked."); continue; } } catch (HBaseException e) { LOG.error("Failed to Put reverse mapping! ID leaked: " + id + " of kind " + kind(), e); hbe = e; continue; } catch (Exception e) { LOG.error("WTF, should never be here! ID leaked: " + id + " of kind " + kind(), e); continue; } addIdToCache(name, row); addNameToCache(row, name); return row; } if (hbe == null) { throw new IllegalStateException("Should never happen!"); } LOG.error("Failed to assign an ID for kind='" + kind() + "' name='" + name + "'", hbe); throw hbe; } UniqueId(final HBaseClient client, final byte[] table, final String kind,
                    final int width); int cacheHits(); int cacheMisses(); int cacheSize(); String kind(); short width(); void dropCaches(); String getName(final byte[] id); byte[] getId(final String name); byte[] getOrCreateId(String name); List<String> suggest(final String search); void rename(final String oldname, final String newname); String toString(); }
UniqueId implements UniqueIdInterface { public byte[] getOrCreateId(String name) throws HBaseException { short attempt = MAX_ATTEMPTS_ASSIGN_ID; HBaseException hbe = null; while (attempt-- > 0) { try { return getId(name); } catch (NoSuchUniqueName e) { LOG.info("Creating an ID for kind='" + kind() + "' name='" + name + '\''); } final long id; byte row[]; try { id = client.atomicIncrement(new AtomicIncrementRequest(table, MAXID_ROW, ID_FAMILY, kind)) .joinUninterruptibly(); row = Bytes.fromLong(id); LOG.info("Got ID=" + id + " for kind='" + kind() + "' name='" + name + "'"); if (row.length < idWidth) { throw new IllegalStateException("OMG, row.length = " + row.length + " which is less than " + idWidth + " for id=" + id + " row=" + Arrays.toString(row)); } for (int i = 0; i < row.length - idWidth; i++) { if (row[i] != 0) { final String message = "All Unique IDs for " + kind() + " on " + idWidth + " bytes are already assigned!"; LOG.error("OMG " + message); throw new IllegalStateException(message); } } row = Arrays.copyOfRange(row, row.length - idWidth, row.length); } catch (HBaseException e) { LOG.error("Failed to assign an ID, atomic increment on row=" + Arrays.toString(MAXID_ROW) + " column='" + fromBytes(ID_FAMILY) + ':' + kind() + '\'', e); hbe = e; continue; } catch (IllegalStateException e) { throw e; } catch (Exception e) { LOG.error("WTF? Unexpected exception type when assigning an ID," + " ICV on row=" + Arrays.toString(MAXID_ROW) + " column='" + fromBytes(ID_FAMILY) + ':' + kind() + '\'', e); continue; } try { final PutRequest reverse_mapping = new PutRequest( table, row, NAME_FAMILY, kind, toBytes(name)); if (!client.compareAndSet(reverse_mapping, HBaseClient.EMPTY_ARRAY) .joinUninterruptibly()) { LOG.error("WTF! Failed to CAS reverse mapping: " + reverse_mapping + " -- run an fsck against the UID table!"); } } catch (HBaseException e) { LOG.error("Failed to CAS reverse mapping! ID leaked: " + id + " of kind " + kind(), e); hbe = e; continue; } catch (Exception e) { LOG.error("WTF, should never be here! ID leaked: " + id + " of kind " + kind(), e); continue; } try { final PutRequest forward_mapping = new PutRequest( table, toBytes(name), ID_FAMILY, kind, row); if (!client.compareAndSet(forward_mapping, HBaseClient.EMPTY_ARRAY) .joinUninterruptibly()) { LOG.warn("Race condition: tried to assign ID " + id + " to " + kind() + ":" + name + ", but CAS failed on " + forward_mapping + ", which indicates this UID must have" + " been allocated concurrently by another TSD. So ID " + id + " was leaked."); continue; } } catch (HBaseException e) { LOG.error("Failed to Put reverse mapping! ID leaked: " + id + " of kind " + kind(), e); hbe = e; continue; } catch (Exception e) { LOG.error("WTF, should never be here! ID leaked: " + id + " of kind " + kind(), e); continue; } addIdToCache(name, row); addNameToCache(row, name); return row; } if (hbe == null) { throw new IllegalStateException("Should never happen!"); } LOG.error("Failed to assign an ID for kind='" + kind() + "' name='" + name + "'", hbe); throw hbe; } UniqueId(final HBaseClient client, final byte[] table, final String kind,
                    final int width); int cacheHits(); int cacheMisses(); int cacheSize(); String kind(); short width(); void dropCaches(); String getName(final byte[] id); byte[] getId(final String name); byte[] getOrCreateId(String name); List<String> suggest(final String search); void rename(final String oldname, final String newname); String toString();  }