/mstu/sem10/distributed_systems/project/cutephrog/CutePhrog/src/ru/cutephrog/MembersRegistry.scala
Scala | 106 lines | 82 code | 17 blank | 7 comment | 12 complexity | bc3bd42d9041cfab192e0100673e3670 MD5 | raw file
- package ru.cutephrog
- import scala.util.Random
- import scala.collection.mutable.{Map => MMap, Set => MSet}
- import java.security.MessageDigest
- import org.jgroups.Address
- import com.mongodb.casbah.Imports._
- import java.nio.ByteBuffer
- import java.net.URL
- /**
- * Created by IntelliJ IDEA.
- * User: dvolosnykh
- * Date: 16.09.11
- * Time: 22:24
- * To change this template use File | Settings | File Templates.
- */
- private[cutephrog]
- final class MembersRegistry(db: MongoDB) {
- private[this] val replicas = MMap.empty[Long, Address]
- val members = MSet.empty[Address]
- def membersLeaved(leavedMemebers: Set[Address]) {
- synchronized {
- members --= leavedMemebers
- replicas retain { (_, member) => !leavedMemebers.contains(member) }
- leavedMemebers foreach { member => db(member.toString).dropCollection() }
- }
- }
- def memberLeaved(leavedMemeber: Address) {
- synchronized {
- membersLeaved(Set(leavedMemeber))
- }
- }
- def memberEntered(member: Address) {
- synchronized {
- val seed = MembersRegistry.hash(member.toString)
- val random = new Random(seed)
- members += member
- for (_ <- 1 until MembersRegistry.MEMBER_REPLICAS) {
- replicas += (random.nextLong() -> member)
- }
- db(member.toString)
- }
- }
- def store(member: Address, urls: List[URL]): Option[List[URL]] = synchronized {
- val collection = db(MembersRegistry.MEMBERS_COLLECTION)
- val strUrls = urls map { _.toString }
- val query = MongoDBObject(MembersRegistry.ATTR_MEMBER -> member.toString)
- collection.update(query, $addToSet(MembersRegistry.ATTR_URLS) $each strUrls, true, true)
- collection.update(query, $inc(MembersRegistry.ATTR_COUNT -> strUrls.size), true, true)
- val obj = collection.findOne(query).get
- val count = obj.getAs[Int](MembersRegistry.ATTR_COUNT).get
- if (count >= MembersRegistry.URLS_STORE_LIMIT) {
- collection.update(query, $unset(MembersRegistry.ATTR_URLS, MembersRegistry.ATTR_COUNT))
- val anyList = obj.getAs[BasicDBList](MembersRegistry.ATTR_URLS).get.toList
- Some(anyList.map(u => new URL(u.asInstanceOf[String])))
- } else {
- None
- }
- }
- def memberInCharge(item: Long): Address = synchronized {
- val min = replicas.minBy{ entry => entry._1 - item }(UnsignedOrdering)
- min._2
- }
- override def toString = "%s".format(members.toString())
- }
- private[cutephrog]
- object UnsignedOrdering extends Ordering[Long] {
- def compare(x: Long, y: Long): Int = {
- val sameSign = (x < 0) == (y < 0)
- if (sameSign) {
- if (x < y) -1 else if (x > y) 1 else 0
- } else {
- if (x < 0) 1 else -1
- }
- }
- }
- private[cutephrog]
- object MembersRegistry {
- private val MEMBER_REPLICAS = 500
- private val MEMBERS_COLLECTION = "members"
- private val ATTR_MEMBER = "member"
- private val ATTR_URLS = "urls"
- private val ATTR_COUNT = "count"
- private val URLS_STORE_LIMIT = 1024
- def md5sum(message: String) = MessageDigest.getInstance("MD5").digest(message.getBytes)
- def hash(message: String): Long = {
- val buf = ByteBuffer.wrap(md5sum(message))
- buf.getLong ^ buf.getLong
- }
- }