PageRenderTime 60ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/src/main/java/usi2011/repository/cassandra/CassandraGameStatusWithSuperColumnRepository.java

https://github.com/jdubois/usi2011
Java | 308 lines | 250 code | 49 blank | 9 comment | 29 complexity | ff9ea0cfc506c2a0c1552e2e66a29e24 MD5 | raw file
  1. package usi2011.repository.cassandra;
  2. import static com.google.common.collect.Lists.newArrayList;
  3. import static java.lang.Math.min;
  4. import static me.prettyprint.hector.api.factory.HFactory.createMutator;
  5. import static me.prettyprint.hector.api.factory.HFactory.createSuperSliceQuery;
  6. import static org.slf4j.LoggerFactory.getLogger;
  7. import static usi2011.repository.GameStatusRepository.GameStatusSuperColMetadata.GAME_CREATION_TIME;
  8. import static usi2011.repository.GameStatusRepository.GameStatusSuperColMetadata.NB_TWEET_SENT_FOR_MACHINE;
  9. import static usi2011.repository.GameStatusRepository.GameStatusSuperColMetadata.NB_USER_LOGGED_FOR_MACHINE;
  10. import static usi2011.repository.GameStatusRepository.GameStatusSuperColMetadata.QUESTION_1_TIMEFRAME_START;
  11. import static usi2011.repository.GameStatusRepository.GameStatusSuperColMetadata.WHEN_FIRST_LOGGED_IN_MILLISECONDS;
  12. import static usi2011.repository.cassandra.CassandraRepository.cfName;
  13. import static usi2011.util.LogUtil.isDebugEnabled;
  14. import static usi2011.util.LogUtil.isInfoEnabled;
  15. import static usi2011.util.Profiles.HECTOR;
  16. import java.net.InetAddress;
  17. import java.util.List;
  18. import me.prettyprint.cassandra.serializers.IntegerSerializer;
  19. import me.prettyprint.cassandra.serializers.LongSerializer;
  20. import me.prettyprint.cassandra.serializers.StringSerializer;
  21. import me.prettyprint.hector.api.beans.HColumn;
  22. import me.prettyprint.hector.api.beans.HSuperColumn;
  23. import me.prettyprint.hector.api.beans.SuperSlice;
  24. import me.prettyprint.hector.api.factory.HFactory;
  25. import me.prettyprint.hector.api.mutation.Mutator;
  26. import me.prettyprint.hector.api.query.QueryResult;
  27. import me.prettyprint.hector.api.query.SuperColumnQuery;
  28. import me.prettyprint.hector.api.query.SuperSliceQuery;
  29. import org.slf4j.Logger;
  30. import org.springframework.beans.factory.annotation.Autowired;
  31. import org.springframework.context.annotation.Primary;
  32. import org.springframework.context.annotation.Profile;
  33. import org.springframework.jmx.export.annotation.ManagedOperation;
  34. import org.springframework.jmx.export.annotation.ManagedResource;
  35. import org.springframework.stereotype.Component;
  36. import usi2011.domain.GameStatus;
  37. import usi2011.domain.GameStatus.GameStatusBuilder;
  38. import usi2011.repository.GameStatusRepository;
  39. @Component
  40. @ManagedResource
  41. @Profile(HECTOR)
  42. @Primary
  43. public class CassandraGameStatusWithSuperColumnRepository implements GameStatusRepository {
  44. private static final Logger logger = getLogger(CassandraGameStatusWithSuperColumnRepository.class);
  45. private static final StringSerializer stringSerializer = StringSerializer.get();
  46. private static final LongSerializer longSerializer = LongSerializer.get();
  47. private static final IntegerSerializer intSerializer = IntegerSerializer.get();
  48. private static final String uniqueId;
  49. private static String SUPER_COLUMN_FAMILY = cfName(GameStatusSuperColMetadata.class);
  50. @Autowired
  51. private CassandraRepository cassandra;
  52. private Long currentGameCreationTime = null;
  53. static {
  54. try {
  55. uniqueId = InetAddress.getLocalHost().getHostName();
  56. } catch (Exception e) {
  57. throw new IllegalStateException(e);
  58. }
  59. }
  60. @Override
  61. @ManagedOperation
  62. public void reset() {
  63. // no need to truncate anything
  64. // no need to reset the currentGameCreationTime
  65. }
  66. @Override
  67. @ManagedOperation
  68. public void loggedUsers(int nbLoggedUsers) {
  69. if (currentGameCreationTime == null) {
  70. throw new IllegalStateException("Expecting a game to be present...");
  71. }
  72. if (isDebugEnabled) {
  73. logger.debug("Saving loggedUsers {}", nbLoggedUsers);
  74. }
  75. // create our sub column to store first login info
  76. final String key = NB_USER_LOGGED_FOR_MACHINE + "-" + uniqueId;
  77. List<HColumn<String, Long>> cols = newArrayList();
  78. cols.add(HectorUtil.createStringLongColumn(key, nbLoggedUsers));
  79. final Mutator<String> mutator = createMutator(cassandra.keyspace(), stringSerializer);
  80. mutator.addInsertion(cassandra.getDefaultKey(), // row key value (we use one row only)
  81. SUPER_COLUMN_FAMILY, // Super Column Family name
  82. HFactory.createSuperColumn(currentGameCreationTime, // superCol name
  83. cols, // cols in that super col
  84. longSerializer, // serializer for super col name
  85. stringSerializer, // serializer for col name
  86. longSerializer)).// serializer for col value
  87. execute();
  88. }
  89. @Override
  90. @ManagedOperation
  91. public void firstLogin(long firstLoginInMilliseconds) {
  92. if (currentGameCreationTime == null) {
  93. throw new IllegalStateException("Expecting a game to be present...");
  94. }
  95. if (isInfoEnabled) {
  96. logger.info("Saving first login at {}", firstLoginInMilliseconds);
  97. }
  98. // create our sub column to store first login info
  99. final String key = WHEN_FIRST_LOGGED_IN_MILLISECONDS + "-" + uniqueId;
  100. List<HColumn<String, Long>> cols = newArrayList();
  101. cols.add(HectorUtil.createStringLongColumn(key, firstLoginInMilliseconds));
  102. final Mutator<String> mutator = createMutator(cassandra.keyspace(), stringSerializer);
  103. mutator.addInsertion(cassandra.getDefaultKey(), // row key value (we use one row only)
  104. SUPER_COLUMN_FAMILY, // Super Column Family name
  105. HFactory.createSuperColumn(currentGameCreationTime, // superCol name
  106. cols, // cols in that super col
  107. longSerializer, // serializer for super col name
  108. stringSerializer, // serializer for col name
  109. longSerializer)).// serializer for col value
  110. execute();
  111. }
  112. @Override
  113. @ManagedOperation
  114. public void gameCreated(long gameCreationTime) {
  115. if (isInfoEnabled) {
  116. logger.info("Saving game created at {}", gameCreationTime);
  117. }
  118. // create our sub column to store our game info
  119. // we add one redundant col (the gameCreationTime) to please hector.
  120. List<HColumn<String, Long>> cols = newArrayList();
  121. cols.add(HectorUtil.createStringLongColumn(GAME_CREATION_TIME.name(), gameCreationTime));
  122. final Mutator<String> mutator = createMutator(cassandra.keyspace(), stringSerializer);
  123. mutator.addInsertion(cassandra.getDefaultKey(), // row key value (we use one row only)
  124. SUPER_COLUMN_FAMILY, // Super Column Family name
  125. HFactory.createSuperColumn(gameCreationTime, // superCol name
  126. cols, // cols in that super col
  127. longSerializer, // serializer for super col name
  128. stringSerializer, // serializer for col name
  129. longSerializer)).// serializer for col value
  130. execute();
  131. currentGameCreationTime = gameCreationTime;
  132. }
  133. @Override
  134. public void question1TimeframeSTart(long question1TimeframeSTart) {
  135. if (currentGameCreationTime == null) {
  136. throw new IllegalStateException("Expecting a game to be present...");
  137. }
  138. if (isInfoEnabled) {
  139. logger.info("Saving question1TimeframeSTart {}", question1TimeframeSTart);
  140. }
  141. // create our sub column to store first login info
  142. final String key = QUESTION_1_TIMEFRAME_START + "-" + uniqueId;
  143. List<HColumn<String, Long>> cols = newArrayList();
  144. cols.add(HectorUtil.createStringLongColumn(key, question1TimeframeSTart));
  145. final Mutator<String> mutator = createMutator(cassandra.keyspace(), stringSerializer);
  146. mutator.addInsertion(cassandra.getDefaultKey(), // row key value (we use one row only)
  147. SUPER_COLUMN_FAMILY, // Super Column Family name
  148. HFactory.createSuperColumn(currentGameCreationTime, // superCol name
  149. cols, // cols in that super col
  150. longSerializer, // serializer for super col name
  151. stringSerializer, // serializer for col name
  152. longSerializer)).// serializer for col value
  153. execute();
  154. }
  155. @Override
  156. public void tweetSent() {
  157. if (currentGameCreationTime == null) {
  158. throw new IllegalStateException("Expecting a game to be present...");
  159. }
  160. if (isInfoEnabled) {
  161. logger.info("Saving 1 tweet sent for game {}", currentGameCreationTime);
  162. }
  163. // create our sub column to store first login info
  164. final String key = NB_TWEET_SENT_FOR_MACHINE + "-" + uniqueId;
  165. List<HColumn<String, Long>> cols = newArrayList();
  166. cols.add(HectorUtil.createStringLongColumn(key, 1)); // 1 tweet sent by this machine
  167. final Mutator<String> mutator = createMutator(cassandra.keyspace(), stringSerializer);
  168. mutator.addInsertion(cassandra.getDefaultKey(), // row key value (we use one row only)
  169. SUPER_COLUMN_FAMILY, // Super Column Family name
  170. HFactory.createSuperColumn(currentGameCreationTime, // superCol name
  171. cols, // cols in that super col
  172. longSerializer, // serializer for super col name
  173. stringSerializer, // serializer for col name
  174. longSerializer)).// serializer for col value
  175. execute();
  176. }
  177. @Override
  178. public GameStatus getGameStatus() {
  179. final SuperSliceQuery<String, Long, String, Long> ssq = createSuperSliceQuery(cassandra.keyspace(), stringSerializer, longSerializer,
  180. stringSerializer, longSerializer);
  181. SuperSlice<Long,String,Long> result = ssq.setColumnFamily(SUPER_COLUMN_FAMILY) //
  182. .setKey(cassandra.getDefaultKey()) //
  183. .setRange(null, null, true, 1) // true= > we want the most recent game
  184. .execute() //
  185. .get();
  186. if (result.getSuperColumns().isEmpty()) {
  187. return null;
  188. }
  189. HSuperColumn<Long, String, Long> gameSuperCol = result.getSuperColumns().get(0);
  190. GameStatus def = GameStatus.DEFAULT;
  191. long nbOfUsersLogged = def.getNbOfUsersLogged();
  192. long whenFirstLogged = def.getWhenFirstUserLoggedInMilliseconds();
  193. long question1TimeframeSTart = def.getQuestion1TimeframeSTart();
  194. long gameCreationTime = def.getGameCreationTime();
  195. int nbTweetSent = def.getNbTweetSent();
  196. for (HColumn<String, Long> column : gameSuperCol.getColumns()) {
  197. final String key = column.getName();
  198. if (key.startsWith(WHEN_FIRST_LOGGED_IN_MILLISECONDS.name())) {
  199. whenFirstLogged = min(column.getValue(), whenFirstLogged);
  200. } else if (key.startsWith(NB_USER_LOGGED_FOR_MACHINE.name())) {
  201. nbOfUsersLogged += column.getValue();
  202. } else if (key.startsWith(NB_TWEET_SENT_FOR_MACHINE.name())) {
  203. nbTweetSent += column.getValue();
  204. } else if (key.startsWith(QUESTION_1_TIMEFRAME_START.name())) {
  205. question1TimeframeSTart = min(column.getValue(), question1TimeframeSTart);
  206. } else if (key.equals(GAME_CREATION_TIME.name())) {
  207. gameCreationTime = column.getValue();
  208. }
  209. }
  210. currentGameCreationTime = gameCreationTime;
  211. return new GameStatusBuilder() //
  212. .setWhenFirstUserLoggedInMilliseconds(whenFirstLogged) //
  213. .setGameCreationTime(gameCreationTime) //
  214. .setNbOfUsersLogged(nbOfUsersLogged) //
  215. .setQuestion1TimeframeSTart(question1TimeframeSTart) //
  216. .setNbTweetSent(nbTweetSent) //
  217. .build();
  218. }
  219. @Override
  220. public void publishLocalRankingRequestCount(long gameCreationTimeMs, int value) {
  221. publishLocalRankingRequestCount(uniqueId, gameCreationTimeMs, value);
  222. }
  223. @Override
  224. public void publishLocalRankingRequestCount(String machineUid, long gameCreationTimeMs, int value) {
  225. // create our sub column to store our local counter
  226. List<HColumn<String, Integer>> cols = newArrayList();
  227. cols.add(HectorUtil.createStringIntegerColumn(machineUid, value));
  228. final Mutator<String> mutator = createMutator(cassandra.keyspace(), stringSerializer);
  229. mutator.addInsertion(cassandra.getDefaultKey(), // row key value (we use one row only)
  230. cfName(RankingStatusMetadata.class), // Super Column Family name
  231. HFactory.createSuperColumn(gameCreationTimeMs, // superCol name
  232. cols, // cols in that super col
  233. longSerializer, // serializer for super col name
  234. stringSerializer, // serializer for col name
  235. intSerializer)).// serializer for col value
  236. execute();
  237. }
  238. @Override
  239. public int getGlobalRankingRequestCount(long gameCreationTimeMs) {
  240. SuperColumnQuery<String, Long, String, Integer> scq = HFactory.createSuperColumnQuery(cassandra.keyspace(), stringSerializer, longSerializer,
  241. stringSerializer, intSerializer);
  242. QueryResult<HSuperColumn<Long, String, Integer>> result = scq.setKey(cassandra.getDefaultKey()). //
  243. setColumnFamily(cfName(RankingStatusMetadata.class)). //
  244. setSuperName(gameCreationTimeMs).execute();
  245. HSuperColumn<Long, String, Integer> superCol = result.get();
  246. if (superCol == null) {
  247. return 0;
  248. }
  249. List<HColumn<String, Integer>> localCounters = superCol.getColumns();
  250. int globalCounter = 0;
  251. if (localCounters != null) {
  252. for (HColumn<String, Integer> localCounter : localCounters) {
  253. globalCounter += localCounter.getValue();
  254. }
  255. return globalCounter;
  256. }
  257. return 0;
  258. }
  259. }