Actor not creating enough threads

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Actor not creating enough threads

Baldur Norddahl-5
Hi,

I am trying to create 10 parallel threads to do some work. But for some reason I only get 3 threads. What am I doing wrong? Is there a way to control how many threads the Actor library will use?

The following program will give output like this:

Creating actor #1
Creating actor #2
Creating actor #3
Creating actor #4
Creating actor #5
Creating actor #6
Creating actor #7
Creating actor #8
Creating actor #9
Creating actor #10
Scanning(3) vlan3: 79.98.195.4
Scanning(1) vlan3: 79.98.195.2
Scanning(2) vlan3: 79.98.195.3
vlan3 79.98.195.2 has MAC [00:23:8B:EA:5B:D2]
Scanning(1) vlan3: 79.98.195.12
Scanning(3) vlan3: 79.98.195.13
Scanning(2) vlan3: 79.98.195.14
vlan3 79.98.195.13 has MAC [00:18:39:BF:C3:E5]
Scanning(3) vlan3: 79.98.195.15
Scanning(1) vlan3: 79.98.195.16
Scanning(2) vlan3: 79.98.195.17
Scanning(3) vlan3: 79.98.195.18
vlan3 79.98.195.18 has MAC [00:21:9B:08:B7:9E]
Scanning(3) vlan3: 79.98.195.19
Scanning(1) vlan3: 79.98.195.20
...

As you can see, it is doing all the work in actor 1 to 3 and ignoring the rest. The very last thing it does before exiting is running actor 4 to 10 once.

Here is the program listing:

import scala.actors.Actor
import scala.actors.Actor._

object Apall {
  val ranges = List(
          ("vlan3","79.98.195.",2,58),
          ("vlan11","79.98.193.",2,126),
          ("vlan12","79.98.193.",130,254),
          ("vlan13","79.98.194.",2,126),
          ("vlan14","79.98.194.",130,254),
          ("vlan15","79.98.197.",1,126)
  )

  case class ScanMessage(vlan: String,ip: String)
  case class GetOneIP(who: Actor)

  var count=10;
  val ipsToScan = actor {
    var ips = for((vlan,ipRange,firstOctet,lastOctet) <- ranges; octet <- firstOctet to lastOctet) yield ScanMessage(vlan,ipRange+octet)
    while(true) {
      receive {
        case GetOneIP(who) =>
          if (ips.isEmpty) {
            count -= 1
            if (count==0) System.exit(0)
          } else {
            who ! ips.head
            ips = ips.tail
          }
      }
    }
  }

  val count2 = count
  for(i <- 1 to count2) {
    println("Creating actor #"+i)
    val thisActor = new Actor {
    val me = i;
    def act() = {
      while(true) {
        receive {
          case ScanMessage(vlan,ip) =>
            println("Scanning("+me+") "+vlan+": "+ip)
            val output = Sh("arping -w 1 -D -I "+vlan+" "+ip+" |").foldLeft(""){ (a,b) => a+"\n"+b }
            for(mac <- "\\[([0-9A-F]{1,2}:){5}[0-9A-F]{1,2}\\]".r.findFirstIn(output)) {
              println(vlan+" "+ip+" has MAC "+mac)
            }
            ipsToScan ! GetOneIP(this)
        }
      }
    }}
    thisActor.start
    ipsToScan ! GetOneIP(thisActor)
  }

  def main(args: Array[String]) {
  }
}

Thanks,

Baldur
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Actor not creating enough threads

Baldur Norddahl-5
I figured the answer to this myself. I had to do System.setProperty("actors.corePoolSize","20").

However the documentation claims the framework will start as many threads as needed. Instead it starves my actors forever. Worse, it starts twice the number of cores threads. Which means it might be working just fine on a my development machine that could be a nice quad core, and fail horrible on the target machine that could be a single core.

Baldur

2010/2/26 Baldur Norddahl <[hidden email]>
Hi,

I am trying to create 10 parallel threads to do some work. But for some reason I only get 3 threads. What am I doing wrong? Is there a way to control how many threads the Actor library will use?

The following program will give output like this:

Creating actor #1
Creating actor #2
Creating actor #3
Creating actor #4
Creating actor #5
Creating actor #6
Creating actor #7
Creating actor #8
Creating actor #9
Creating actor #10
Scanning(3) vlan3: 79.98.195.4
Scanning(1) vlan3: 79.98.195.2
Scanning(2) vlan3: 79.98.195.3
vlan3 79.98.195.2 has MAC [00:23:8B:EA:5B:D2]
Scanning(1) vlan3: 79.98.195.12
Scanning(3) vlan3: 79.98.195.13
Scanning(2) vlan3: 79.98.195.14
vlan3 79.98.195.13 has MAC [00:18:39:BF:C3:E5]
Scanning(3) vlan3: 79.98.195.15
Scanning(1) vlan3: 79.98.195.16
Scanning(2) vlan3: 79.98.195.17
Scanning(3) vlan3: 79.98.195.18
vlan3 79.98.195.18 has MAC [00:21:9B:08:B7:9E]
Scanning(3) vlan3: 79.98.195.19
Scanning(1) vlan3: 79.98.195.20
...

As you can see, it is doing all the work in actor 1 to 3 and ignoring the rest. The very last thing it does before exiting is running actor 4 to 10 once.

Here is the program listing:

import scala.actors.Actor
import scala.actors.Actor._

object Apall {
  val ranges = List(
          ("vlan3","79.98.195.",2,58),
          ("vlan11","79.98.193.",2,126),
          ("vlan12","79.98.193.",130,254),
          ("vlan13","79.98.194.",2,126),
          ("vlan14","79.98.194.",130,254),
          ("vlan15","79.98.197.",1,126)
  )

  case class ScanMessage(vlan: String,ip: String)
  case class GetOneIP(who: Actor)

  var count=10;
  val ipsToScan = actor {
    var ips = for((vlan,ipRange,firstOctet,lastOctet) <- ranges; octet <- firstOctet to lastOctet) yield ScanMessage(vlan,ipRange+octet)
    while(true) {
      receive {
        case GetOneIP(who) =>
          if (ips.isEmpty) {
            count -= 1
            if (count==0) System.exit(0)
          } else {
            who ! ips.head
            ips = ips.tail
          }
      }
    }
  }

  val count2 = count
  for(i <- 1 to count2) {
    println("Creating actor #"+i)
    val thisActor = new Actor {
    val me = i;
    def act() = {
      while(true) {
        receive {
          case ScanMessage(vlan,ip) =>
            println("Scanning("+me+") "+vlan+": "+ip)
            val output = Sh("arping -w 1 -D -I "+vlan+" "+ip+" |").foldLeft(""){ (a,b) => a+"\n"+b }
            for(mac <- "\\[([0-9A-F]{1,2}:){5}[0-9A-F]{1,2}\\]".r.findFirstIn(output)) {
              println(vlan+" "+ip+" has MAC "+mac)
            }
            ipsToScan ! GetOneIP(this)
        }
      }
    }}
    thisActor.start
    ipsToScan ! GetOneIP(thisActor)
  }

  def main(args: Array[String]) {
  }
}

Thanks,

Baldur

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Re: Actor not creating enough threads

Niko Matsakis
This could be because the Actors library is non-preemptive.  Perhaps you are performing blocking operations in your actors, or looping indefinitely without returning control to the runtime?  


regards,
Niko

On Feb 27, 2010, at 1:49 PM, Baldur Norddahl wrote:

I figured the answer to this myself. I had to do System.setProperty("actors.corePoolSize","20").

However the documentation claims the framework will start as many threads as needed. Instead it starves my actors forever. Worse, it starts twice the number of cores threads. Which means it might be working just fine on a my development machine that could be a nice quad core, and fail horrible on the target machine that could be a single core.

Baldur

2010/2/26 Baldur Norddahl <[hidden email]>
Hi,

I am trying to create 10 parallel threads to do some work. But for some reason I only get 3 threads. What am I doing wrong? Is there a way to control how many threads the Actor library will use?

The following program will give output like this:

Creating actor #1
Creating actor #2
Creating actor #3
Creating actor #4
Creating actor #5
Creating actor #6
Creating actor #7
Creating actor #8
Creating actor #9
Creating actor #10
Scanning(3) vlan3: 79.98.195.4
Scanning(1) vlan3: 79.98.195.2
Scanning(2) vlan3: 79.98.195.3
vlan3 79.98.195.2 has MAC [00:23:8B:EA:5B:D2]
Scanning(1) vlan3: 79.98.195.12
Scanning(3) vlan3: 79.98.195.13
Scanning(2) vlan3: 79.98.195.14
vlan3 79.98.195.13 has MAC [00:18:39:BF:C3:E5]
Scanning(3) vlan3: 79.98.195.15
Scanning(1) vlan3: 79.98.195.16
Scanning(2) vlan3: 79.98.195.17
Scanning(3) vlan3: 79.98.195.18
vlan3 79.98.195.18 has MAC [00:21:9B:08:B7:9E]
Scanning(3) vlan3: 79.98.195.19
Scanning(1) vlan3: 79.98.195.20
...

As you can see, it is doing all the work in actor 1 to 3 and ignoring the rest. The very last thing it does before exiting is running actor 4 to 10 once.

Here is the program listing:

import scala.actors.Actor
import scala.actors.Actor._

object Apall {
  val ranges = List(
          ("vlan3","79.98.195.",2,58),
          ("vlan11","79.98.193.",2,126),
          ("vlan12","79.98.193.",130,254),
          ("vlan13","79.98.194.",2,126),
          ("vlan14","79.98.194.",130,254),
          ("vlan15","79.98.197.",1,126)
  )

  case class ScanMessage(vlan: String,ip: String)
  case class GetOneIP(who: Actor)

  var count=10;
  val ipsToScan = actor {
    var ips = for((vlan,ipRange,firstOctet,lastOctet) <- ranges; octet <- firstOctet to lastOctet) yield ScanMessage(vlan,ipRange+octet)
    while(true) {
      receive {
        case GetOneIP(who) =>
          if (ips.isEmpty) {
            count -= 1
            if (count==0) System.exit(0)
          } else {
            who ! ips.head
            ips = ips.tail
          }
      }
    }
  }

  val count2 = count
  for(i <- 1 to count2) {
    println("Creating actor #"+i)
    val thisActor = new Actor {
    val me = i;
    def act() = {
      while(true) {
        receive {
          case ScanMessage(vlan,ip) =>
            println("Scanning("+me+") "+vlan+": "+ip)
            val output = Sh("arping -w 1 -D -I "+vlan+" "+ip+" |").foldLeft(""){ (a,b) => a+"\n"+b }
            for(mac <- "<a href="smb://[">\\[([0-9A-F]{1,2}:){5}[0-9A-F]{1,2}\\]".r.findFirstIn(output)) {
              println(vlan+" "+ip+" has MAC "+mac)
            }
            ipsToScan ! GetOneIP(this)
        }
      }
    }}
    thisActor.start
    ipsToScan ! GetOneIP(thisActor)
  }

  def main(args: Array[String]) {
  }
}

Thanks,

Baldur


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Re: Actor not creating enough threads

Niko Matsakis
> This could be because the Actors library is non-preemptive.  Perhaps you are performing blocking operations in your actors, or looping indefinitely without returning control to the runtime?  

To reply to myself, I see that you enclosed a sample program which is not using blocking operations.  Sorry, I missed that the first time reading your message.  Nonetheless, I suspect the issue you are discussing is related.  Basically, I would guess the actors scheduler is not fair, and so each of the first three "consumer" actors greedily continue running so long as they have more messages.  The other consumers are starved until the total pool of produced items is exhausted, in which case they finally run.  This situation shouldn't cause a deadlock, but could result in some items waiting indefinitely to be processed if the pool of produced items is inexhaustible.  

Anyway, I haven't looked at the implementation of the actors runtime in detail, so this is all speculation.


regards,
Niko

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Actor not creating enough threads

Josh Suereth
In reply to this post by Baldur Norddahl-5
Try using "react" instead of "receive".   Receive blocks the current thread.


- Josh

On Fri, Feb 26, 2010 at 8:58 AM, Baldur Norddahl <[hidden email]> wrote:
Hi,

I am trying to create 10 parallel threads to do some work. But for some reason I only get 3 threads. What am I doing wrong? Is there a way to control how many threads the Actor library will use?

The following program will give output like this:

Creating actor #1
Creating actor #2
Creating actor #3
Creating actor #4
Creating actor #5
Creating actor #6
Creating actor #7
Creating actor #8
Creating actor #9
Creating actor #10
Scanning(3) vlan3: 79.98.195.4
Scanning(1) vlan3: 79.98.195.2
Scanning(2) vlan3: 79.98.195.3
vlan3 79.98.195.2 has MAC [00:23:8B:EA:5B:D2]
Scanning(1) vlan3: 79.98.195.12
Scanning(3) vlan3: 79.98.195.13
Scanning(2) vlan3: 79.98.195.14
vlan3 79.98.195.13 has MAC [00:18:39:BF:C3:E5]
Scanning(3) vlan3: 79.98.195.15
Scanning(1) vlan3: 79.98.195.16
Scanning(2) vlan3: 79.98.195.17
Scanning(3) vlan3: 79.98.195.18
vlan3 79.98.195.18 has MAC [00:21:9B:08:B7:9E]
Scanning(3) vlan3: 79.98.195.19
Scanning(1) vlan3: 79.98.195.20
...

As you can see, it is doing all the work in actor 1 to 3 and ignoring the rest. The very last thing it does before exiting is running actor 4 to 10 once.

Here is the program listing:

import scala.actors.Actor
import scala.actors.Actor._

object Apall {
  val ranges = List(
          ("vlan3","79.98.195.",2,58),
          ("vlan11","79.98.193.",2,126),
          ("vlan12","79.98.193.",130,254),
          ("vlan13","79.98.194.",2,126),
          ("vlan14","79.98.194.",130,254),
          ("vlan15","79.98.197.",1,126)
  )

  case class ScanMessage(vlan: String,ip: String)
  case class GetOneIP(who: Actor)

  var count=10;
  val ipsToScan = actor {
    var ips = for((vlan,ipRange,firstOctet,lastOctet) <- ranges; octet <- firstOctet to lastOctet) yield ScanMessage(vlan,ipRange+octet)
    while(true) {
      receive {
        case GetOneIP(who) =>
          if (ips.isEmpty) {
            count -= 1
            if (count==0) System.exit(0)
          } else {
            who ! ips.head
            ips = ips.tail
          }
      }
    }
  }

  val count2 = count
  for(i <- 1 to count2) {
    println("Creating actor #"+i)
    val thisActor = new Actor {
    val me = i;
    def act() = {
      while(true) {
        receive {
          case ScanMessage(vlan,ip) =>
            println("Scanning("+me+") "+vlan+": "+ip)
            val output = Sh("arping -w 1 -D -I "+vlan+" "+ip+" |").foldLeft(""){ (a,b) => a+"\n"+b }
            for(mac <- "\\[([0-9A-F]{1,2}:){5}[0-9A-F]{1,2}\\]".r.findFirstIn(output)) {
              println(vlan+" "+ip+" has MAC "+mac)
            }
            ipsToScan ! GetOneIP(this)
        }
      }
    }}
    thisActor.start
    ipsToScan ! GetOneIP(thisActor)
  }

  def main(args: Array[String]) {
  }
}

Thanks,

Baldur

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Actor not creating enough threads

Erik Engbrecht
Still, the scheduler is supposed to detect when all its threads are blocked and spawn more up to the limit.

On Sat, Feb 27, 2010 at 10:40 AM, Josh Suereth <[hidden email]> wrote:
Try using "react" instead of "receive".   Receive blocks the current thread.


- Josh


On Fri, Feb 26, 2010 at 8:58 AM, Baldur Norddahl <[hidden email]> wrote:
Hi,

I am trying to create 10 parallel threads to do some work. But for some reason I only get 3 threads. What am I doing wrong? Is there a way to control how many threads the Actor library will use?

The following program will give output like this:

Creating actor #1
Creating actor #2
Creating actor #3
Creating actor #4
Creating actor #5
Creating actor #6
Creating actor #7
Creating actor #8
Creating actor #9
Creating actor #10
Scanning(3) vlan3: 79.98.195.4
Scanning(1) vlan3: 79.98.195.2
Scanning(2) vlan3: 79.98.195.3
vlan3 79.98.195.2 has MAC [00:23:8B:EA:5B:D2]
Scanning(1) vlan3: 79.98.195.12
Scanning(3) vlan3: 79.98.195.13
Scanning(2) vlan3: 79.98.195.14
vlan3 79.98.195.13 has MAC [00:18:39:BF:C3:E5]
Scanning(3) vlan3: 79.98.195.15
Scanning(1) vlan3: 79.98.195.16
Scanning(2) vlan3: 79.98.195.17
Scanning(3) vlan3: 79.98.195.18
vlan3 79.98.195.18 has MAC [00:21:9B:08:B7:9E]
Scanning(3) vlan3: 79.98.195.19
Scanning(1) vlan3: 79.98.195.20
...

As you can see, it is doing all the work in actor 1 to 3 and ignoring the rest. The very last thing it does before exiting is running actor 4 to 10 once.

Here is the program listing:

import scala.actors.Actor
import scala.actors.Actor._

object Apall {
  val ranges = List(
          ("vlan3","79.98.195.",2,58),
          ("vlan11","79.98.193.",2,126),
          ("vlan12","79.98.193.",130,254),
          ("vlan13","79.98.194.",2,126),
          ("vlan14","79.98.194.",130,254),
          ("vlan15","79.98.197.",1,126)
  )

  case class ScanMessage(vlan: String,ip: String)
  case class GetOneIP(who: Actor)

  var count=10;
  val ipsToScan = actor {
    var ips = for((vlan,ipRange,firstOctet,lastOctet) <- ranges; octet <- firstOctet to lastOctet) yield ScanMessage(vlan,ipRange+octet)
    while(true) {
      receive {
        case GetOneIP(who) =>
          if (ips.isEmpty) {
            count -= 1
            if (count==0) System.exit(0)
          } else {
            who ! ips.head
            ips = ips.tail
          }
      }
    }
  }

  val count2 = count
  for(i <- 1 to count2) {
    println("Creating actor #"+i)
    val thisActor = new Actor {
    val me = i;
    def act() = {
      while(true) {
        receive {
          case ScanMessage(vlan,ip) =>
            println("Scanning("+me+") "+vlan+": "+ip)
            val output = Sh("arping -w 1 -D -I "+vlan+" "+ip+" |").foldLeft(""){ (a,b) => a+"\n"+b }
            for(mac <- "\\[([0-9A-F]{1,2}:){5}[0-9A-F]{1,2}\\]".r.findFirstIn(output)) {
              println(vlan+" "+ip+" has MAC "+mac)
            }
            ipsToScan ! GetOneIP(this)
        }
      }
    }}
    thisActor.start
    ipsToScan ! GetOneIP(thisActor)
  }

  def main(args: Array[String]) {
  }
}

Thanks,

Baldur




--
http://erikengbrecht.blogspot.com/
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Re: Actor not creating enough threads

Erik Engbrecht
In reply to this post by Baldur Norddahl-5
Which version of Scala are you using and on which JVM?

On Sat, Feb 27, 2010 at 7:49 AM, Baldur Norddahl <[hidden email]> wrote:
I figured the answer to this myself. I had to do System.setProperty("actors.corePoolSize","20").

However the documentation claims the framework will start as many threads as needed. Instead it starves my actors forever. Worse, it starts twice the number of cores threads. Which means it might be working just fine on a my development machine that could be a nice quad core, and fail horrible on the target machine that could be a single core.

Baldur

2010/2/26 Baldur Norddahl <[hidden email]>

Hi,

I am trying to create 10 parallel threads to do some work. But for some reason I only get 3 threads. What am I doing wrong? Is there a way to control how many threads the Actor library will use?

The following program will give output like this:

Creating actor #1
Creating actor #2
Creating actor #3
Creating actor #4
Creating actor #5
Creating actor #6
Creating actor #7
Creating actor #8
Creating actor #9
Creating actor #10
Scanning(3) vlan3: 79.98.195.4
Scanning(1) vlan3: 79.98.195.2
Scanning(2) vlan3: 79.98.195.3
vlan3 79.98.195.2 has MAC [00:23:8B:EA:5B:D2]
Scanning(1) vlan3: 79.98.195.12
Scanning(3) vlan3: 79.98.195.13
Scanning(2) vlan3: 79.98.195.14
vlan3 79.98.195.13 has MAC [00:18:39:BF:C3:E5]
Scanning(3) vlan3: 79.98.195.15
Scanning(1) vlan3: 79.98.195.16
Scanning(2) vlan3: 79.98.195.17
Scanning(3) vlan3: 79.98.195.18
vlan3 79.98.195.18 has MAC [00:21:9B:08:B7:9E]
Scanning(3) vlan3: 79.98.195.19
Scanning(1) vlan3: 79.98.195.20
...

As you can see, it is doing all the work in actor 1 to 3 and ignoring the rest. The very last thing it does before exiting is running actor 4 to 10 once.

Here is the program listing:

import scala.actors.Actor
import scala.actors.Actor._

object Apall {
  val ranges = List(
          ("vlan3","79.98.195.",2,58),
          ("vlan11","79.98.193.",2,126),
          ("vlan12","79.98.193.",130,254),
          ("vlan13","79.98.194.",2,126),
          ("vlan14","79.98.194.",130,254),
          ("vlan15","79.98.197.",1,126)
  )

  case class ScanMessage(vlan: String,ip: String)
  case class GetOneIP(who: Actor)

  var count=10;
  val ipsToScan = actor {
    var ips = for((vlan,ipRange,firstOctet,lastOctet) <- ranges; octet <- firstOctet to lastOctet) yield ScanMessage(vlan,ipRange+octet)
    while(true) {
      receive {
        case GetOneIP(who) =>
          if (ips.isEmpty) {
            count -= 1
            if (count==0) System.exit(0)
          } else {
            who ! ips.head
            ips = ips.tail
          }
      }
    }
  }

  val count2 = count
  for(i <- 1 to count2) {
    println("Creating actor #"+i)
    val thisActor = new Actor {
    val me = i;
    def act() = {
      while(true) {
        receive {
          case ScanMessage(vlan,ip) =>
            println("Scanning("+me+") "+vlan+": "+ip)
            val output = Sh("arping -w 1 -D -I "+vlan+" "+ip+" |").foldLeft(""){ (a,b) => a+"\n"+b }
            for(mac <- "\\[([0-9A-F]{1,2}:){5}[0-9A-F]{1,2}\\]".r.findFirstIn(output)) {
              println(vlan+" "+ip+" has MAC "+mac)
            }
            ipsToScan ! GetOneIP(this)
        }
      }
    }}
    thisActor.start
    ipsToScan ! GetOneIP(thisActor)
  }

  def main(args: Array[String]) {
  }
}

Thanks,

Baldur




--
http://erikengbrecht.blogspot.com/
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Re: Actor not creating enough threads

Baldur Norddahl-5
fm@fm:~$ scala -version
Scala code runner version 2.7.5final -- (c) 2002-2008 LAMP/EPFL
fm@fm:~$ java -version
java version "1.6.0_15"
Java(TM) SE Runtime Environment (build 1.6.0_15-b03)
Java HotSpot(TM) 64-Bit Server VM (build 14.1-b02, mixed mode)


2010/3/1 Erik Engbrecht <[hidden email]>
Which version of Scala are you using and on which JVM?


On Sat, Feb 27, 2010 at 7:49 AM, Baldur Norddahl <[hidden email]> wrote:
I figured the answer to this myself. I had to do System.setProperty("actors.corePoolSize","20").

However the documentation claims the framework will start as many threads as needed. Instead it starves my actors forever. Worse, it starts twice the number of cores threads. Which means it might be working just fine on a my development machine that could be a nice quad core, and fail horrible on the target machine that could be a single core.

Baldur

2010/2/26 Baldur Norddahl <[hidden email]>

Hi,

I am trying to create 10 parallel threads to do some work. But for some reason I only get 3 threads. What am I doing wrong? Is there a way to control how many threads the Actor library will use?

The following program will give output like this:

Creating actor #1
Creating actor #2
Creating actor #3
Creating actor #4
Creating actor #5
Creating actor #6
Creating actor #7
Creating actor #8
Creating actor #9
Creating actor #10
Scanning(3) vlan3: 79.98.195.4
Scanning(1) vlan3: 79.98.195.2
Scanning(2) vlan3: 79.98.195.3
vlan3 79.98.195.2 has MAC [00:23:8B:EA:5B:D2]
Scanning(1) vlan3: 79.98.195.12
Scanning(3) vlan3: 79.98.195.13
Scanning(2) vlan3: 79.98.195.14
vlan3 79.98.195.13 has MAC [00:18:39:BF:C3:E5]
Scanning(3) vlan3: 79.98.195.15
Scanning(1) vlan3: 79.98.195.16
Scanning(2) vlan3: 79.98.195.17
Scanning(3) vlan3: 79.98.195.18
vlan3 79.98.195.18 has MAC [00:21:9B:08:B7:9E]
Scanning(3) vlan3: 79.98.195.19
Scanning(1) vlan3: 79.98.195.20
...

As you can see, it is doing all the work in actor 1 to 3 and ignoring the rest. The very last thing it does before exiting is running actor 4 to 10 once.

Here is the program listing:

import scala.actors.Actor
import scala.actors.Actor._

object Apall {
  val ranges = List(
          ("vlan3","79.98.195.",2,58),
          ("vlan11","79.98.193.",2,126),
          ("vlan12","79.98.193.",130,254),
          ("vlan13","79.98.194.",2,126),
          ("vlan14","79.98.194.",130,254),
          ("vlan15","79.98.197.",1,126)
  )

  case class ScanMessage(vlan: String,ip: String)
  case class GetOneIP(who: Actor)

  var count=10;
  val ipsToScan = actor {
    var ips = for((vlan,ipRange,firstOctet,lastOctet) <- ranges; octet <- firstOctet to lastOctet) yield ScanMessage(vlan,ipRange+octet)
    while(true) {
      receive {
        case GetOneIP(who) =>
          if (ips.isEmpty) {
            count -= 1
            if (count==0) System.exit(0)
          } else {
            who ! ips.head
            ips = ips.tail
          }
      }
    }
  }

  val count2 = count
  for(i <- 1 to count2) {
    println("Creating actor #"+i)
    val thisActor = new Actor {
    val me = i;
    def act() = {
      while(true) {
        receive {
          case ScanMessage(vlan,ip) =>
            println("Scanning("+me+") "+vlan+": "+ip)
            val output = Sh("arping -w 1 -D -I "+vlan+" "+ip+" |").foldLeft(""){ (a,b) => a+"\n"+b }
            for(mac <- "\\[([0-9A-F]{1,2}:){5}[0-9A-F]{1,2}\\]".r.findFirstIn(output)) {
              println(vlan+" "+ip+" has MAC "+mac)
            }
            ipsToScan ! GetOneIP(this)
        }
      }
    }}
    thisActor.start
    ipsToScan ! GetOneIP(thisActor)
  }

  def main(args: Array[String]) {
  }
}

Thanks,

Baldur




--
http://erikengbrecht.blogspot.com/

Loading...