ByteBuffer key = CassandraUtils.hashKeyBytes((indexName + "~" + node.shard).getBytes("UTF-8"),
CassandraUtils.delimeterBytes, "rsvp".getBytes("UTF-8"));
// Write the reserves
RowMutation rm = new RowMutation(CassandraUtils.keySpace, key);
ByteBuffer id = ByteBufferUtil.bytes(String.valueOf(nextOffset));
ByteBuffer off = id;
rm.add(new QueryPath(CassandraUtils.schemaInfoColumnFamily, id, ByteBuffer.wrap(myToken
.getBytes("UTF-8"))), off, System.currentTimeMillis(), expirationTime);
CassandraUtils.robustInsert(ConsistencyLevel.QUORUM, rm);
// Give it time to sink in, in-case clocks are off across
// nodes...
try
{
Thread.sleep(100);
} catch (InterruptedException e1)
{
}
// Read the columns back
IColumn supercol = null;
int attempts = 0;
while (supercol == null && attempts < CassandraUtils.retryAttempts)
{
try
{
List<Row> rows = CassandraUtils.robustRead(key, new QueryPath(
CassandraUtils.schemaInfoColumnFamily), Arrays.asList(id), ConsistencyLevel.QUORUM);
if (rows == null || rows.size() == 0)
{
continue;
}
if (rows.size() == 1)
{
Row row = rows.get(0);
if (row.cf == null || row.cf.isMarkedForDelete())
{
continue;
}
supercol = rows.get(0).cf.getColumn(id);
}
} catch (IOException e)
{
// let's try again...
}
attempts++;
}
if (supercol == null)
throw new IllegalStateException("just wrote " + offset + ", but didn't read it");
long minTtl = Long.MAX_VALUE;
ByteBuffer winningToken = null;
// See which ones we successfully reserved
for (IColumn c : supercol.getSubColumns())
{
// someone already took this id
if (!(c instanceof ExpiringColumn) && !(c instanceof DeletedColumn))
{
if (logger.isDebugEnabled())
logger.debug(offset + " was taken by " + ByteBufferUtil.string(c.name()));
winningToken = null;
break;
}
// expired reservation
if (c.isMarkedForDelete())
{
continue;
}
if (c.timestamp() < minTtl)
{
minTtl = c.timestamp();
winningToken = c.name();
}
// incase of a tie the token is the tiebreaker
if (c.timestamp() == minTtl && winningToken.compareTo(c.name()) <= 0)
{
winningToken = c.name();
}
}
String winningTokenStr;
try
{
winningTokenStr = winningToken == null ? "" : ByteBufferUtil.string(winningToken);
} catch (CharacterCodingException e)
{
throw new RuntimeException(e);
}
// we won!
if (winningTokenStr.equals(myToken))
{
// Mark this as permanently taken
rm = new RowMutation(CassandraUtils.keySpace, key);
rm.add(new QueryPath(CassandraUtils.schemaInfoColumnFamily, id, ByteBuffer.wrap(myToken
.getBytes("UTF-8"))), off, System.currentTimeMillis());
CassandraUtils.robustInsert(ConsistencyLevel.QUORUM, rm);
// Add to active rsvp list