码迷,mamicode.com
首页 > 其他好文 > 详细

tree路径匹配抽象(2)

时间:2015-03-02 13:22:55      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:

接着上一篇的 tree路径匹配抽象(1),我们开始看如何对tree进行索引,akka的路径匹配包含了远程节点的匹配,这样就得引入多个通信机制(akka采用消息),为了简化,我们先假设只在一个本地tree中进行索引:

object ActorSelection {//...省略



  /**

   * Construct an ActorSelection from the given string representing a path

   * relative to the given target. This operation has to create all the

   * matching magic, so it is preferable to cache its result if the

   * intention is to send messages frequently.

   */

  def apply(anchorRef: ActorRef, path: String): ActorSelection = apply(anchorRef, path.split("/+"))//ActorRef可以被当作当前路径的引用



  /**

   * Construct an ActorSelection from the given string representing a path

   * relative to the given target. This operation has to create all the

   * matching magic, so it is preferable to cache its result if the

   * intention is to send messages frequently.

   */

  def apply(anchorRef: ActorRef, elements: Iterable[String]): ActorSelection = {    val compiled: immutable.IndexedSeq[SelectionPathElement] = elements.collect({      case x if !x.isEmpty ?        if ((x.indexOf(‘?‘) != -1) || (x.indexOf(‘*‘) != -1)) SelectChildPattern(x)        else if (x == "..") SelectParent        else SelectChildName(x)

    })(scala.collection.breakOut)//直接转换为immutable.IndexedSeq[SelectionPathElement]

    new ActorSelection with ScalaActorSelection {      override val anchor = anchorRef      override val path = compiled

    }

  }//------上面是将字符串转化为SelectionPathElement,下面则是根据SelectionPathElement进行索引tree值

  /**

   * INTERNAL API

   * The receive logic for ActorSelectionMessage. The idea is to recursively descend as far as possible

   * with local refs and hand over to that “foreign” child when we encounter it.

   */

  private[akka] def deliverSelection(anchor: InternalActorRef, sender: ActorRef, sel: ActorSelectionMessage): Unit =    if (sel.elements.isEmpty)

      anchor.tell(sel.msg, sender)//自己

    else {      val iter = sel.elements.iterator      @tailrec def rec(ref: InternalActorRef): Unit = {

        ref match {          case refWithCell: ActorRefWithCell ?            def emptyRef = new EmptyLocalActorRef(refWithCell.provider, anchor.path / sel.elements.map(_.toString),

              refWithCell.underlying.system.eventStream)



            iter.next() match {              case SelectParent ?                val parent = ref.getParent                if (iter.isEmpty)

                  parent.tell(sel.msg, sender)                else

                  rec(parent)              case SelectChildName(name) ?                val child = refWithCell.getSingleChild(name)                if (child == Nobody) {                  // don‘t send to emptyRef after wildcard fan-out

                  if (!sel.wildcardFanOut) emptyRef.tell(sel, sender)

                } else if (iter.isEmpty)

                  child.tell(sel.msg, sender)                else

                  rec(child)              case p: SelectChildPattern ?                // fan-out when there is a wildcard

                val chldr = refWithCell.children                if (iter.isEmpty) {                  // leaf

                  val matchingChildren = chldr.filter(c ? p.pattern.matcher(c.path.name).matches)                  if (matchingChildren.isEmpty && !sel.wildcardFanOut)

                    emptyRef.tell(sel, sender)                  else

                    matchingChildren.foreach(_.tell(sel.msg, sender))

                } else {                  val matchingChildren = chldr.filter(c ? p.pattern.matcher(c.path.name).matches)                  // don‘t send to emptyRef after wildcard fan-out 

                  if (matchingChildren.isEmpty && !sel.wildcardFanOut)

                    emptyRef.tell(sel, sender)                  else {                    val m = sel.copy(elements = iter.toVector,

                      wildcardFanOut = sel.wildcardFanOut || matchingChildren.size > 1)

                    matchingChildren.foreach(c ? deliverSelection(c.asInstanceOf[InternalActorRef], sender, m))

                  }

                }

            }          //case _ ?

            // foreign ref, continue by sending ActorSelectionMessage to it with remaining elements

            //ref.tell(sel.copy(elements = iter.toVector), sender)

        }

      }



      rec(anchor)

    }

}

既然path允许正则索引,那么path最好有个命名规则,akka的命名规则为:

/**

   * This Regular Expression is used to validate a path element (Actor Name).

   * Since Actors form a tree, it is addressable using an URL, therefore an Actor Name has to conform to:

   * http://www.ietf.org/rfc/rfc2396.txt

   */

  val ElementRegex = """(?:[-\w:@&=+,.!~*‘_;]|%\p{XDigit}{2})(?:[-\w:@&=+,.!~*‘$_;]|%\p{XDigit}{2})*""".r


tree路径匹配抽象(2)

标签:

原文地址:http://my.oschina.net/myprogworld/blog/381197

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!