PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/mstu/sem10/distributed_systems/project/cutephrog/CutePhrog/src/ru/cutephrog/MembersRegistry.scala

https://gitlab.com/dvolosnykh/education
Scala | 106 lines | 82 code | 17 blank | 7 comment | 12 complexity | bc3bd42d9041cfab192e0100673e3670 MD5 | raw file
  1. package ru.cutephrog
  2. import scala.util.Random
  3. import scala.collection.mutable.{Map => MMap, Set => MSet}
  4. import java.security.MessageDigest
  5. import org.jgroups.Address
  6. import com.mongodb.casbah.Imports._
  7. import java.nio.ByteBuffer
  8. import java.net.URL
  9. /**
  10. * Created by IntelliJ IDEA.
  11. * User: dvolosnykh
  12. * Date: 16.09.11
  13. * Time: 22:24
  14. * To change this template use File | Settings | File Templates.
  15. */
  16. private[cutephrog]
  17. final class MembersRegistry(db: MongoDB) {
  18. private[this] val replicas = MMap.empty[Long, Address]
  19. val members = MSet.empty[Address]
  20. def membersLeaved(leavedMemebers: Set[Address]) {
  21. synchronized {
  22. members --= leavedMemebers
  23. replicas retain { (_, member) => !leavedMemebers.contains(member) }
  24. leavedMemebers foreach { member => db(member.toString).dropCollection() }
  25. }
  26. }
  27. def memberLeaved(leavedMemeber: Address) {
  28. synchronized {
  29. membersLeaved(Set(leavedMemeber))
  30. }
  31. }
  32. def memberEntered(member: Address) {
  33. synchronized {
  34. val seed = MembersRegistry.hash(member.toString)
  35. val random = new Random(seed)
  36. members += member
  37. for (_ <- 1 until MembersRegistry.MEMBER_REPLICAS) {
  38. replicas += (random.nextLong() -> member)
  39. }
  40. db(member.toString)
  41. }
  42. }
  43. def store(member: Address, urls: List[URL]): Option[List[URL]] = synchronized {
  44. val collection = db(MembersRegistry.MEMBERS_COLLECTION)
  45. val strUrls = urls map { _.toString }
  46. val query = MongoDBObject(MembersRegistry.ATTR_MEMBER -> member.toString)
  47. collection.update(query, $addToSet(MembersRegistry.ATTR_URLS) $each strUrls, true, true)
  48. collection.update(query, $inc(MembersRegistry.ATTR_COUNT -> strUrls.size), true, true)
  49. val obj = collection.findOne(query).get
  50. val count = obj.getAs[Int](MembersRegistry.ATTR_COUNT).get
  51. if (count >= MembersRegistry.URLS_STORE_LIMIT) {
  52. collection.update(query, $unset(MembersRegistry.ATTR_URLS, MembersRegistry.ATTR_COUNT))
  53. val anyList = obj.getAs[BasicDBList](MembersRegistry.ATTR_URLS).get.toList
  54. Some(anyList.map(u => new URL(u.asInstanceOf[String])))
  55. } else {
  56. None
  57. }
  58. }
  59. def memberInCharge(item: Long): Address = synchronized {
  60. val min = replicas.minBy{ entry => entry._1 - item }(UnsignedOrdering)
  61. min._2
  62. }
  63. override def toString = "%s".format(members.toString())
  64. }
  65. private[cutephrog]
  66. object UnsignedOrdering extends Ordering[Long] {
  67. def compare(x: Long, y: Long): Int = {
  68. val sameSign = (x < 0) == (y < 0)
  69. if (sameSign) {
  70. if (x < y) -1 else if (x > y) 1 else 0
  71. } else {
  72. if (x < 0) 1 else -1
  73. }
  74. }
  75. }
  76. private[cutephrog]
  77. object MembersRegistry {
  78. private val MEMBER_REPLICAS = 500
  79. private val MEMBERS_COLLECTION = "members"
  80. private val ATTR_MEMBER = "member"
  81. private val ATTR_URLS = "urls"
  82. private val ATTR_COUNT = "count"
  83. private val URLS_STORE_LIMIT = 1024
  84. def md5sum(message: String) = MessageDigest.getInstance("MD5").digest(message.getBytes)
  85. def hash(message: String): Long = {
  86. val buf = ByteBuffer.wrap(md5sum(message))
  87. buf.getLong ^ buf.getLong
  88. }
  89. }