changeset 250:a654d43731f0

implement multi-thread Ikariam::Scanner
author "Rex Tsai <chihchun@kalug.linux.org.tw>"
date Mon, 17 Nov 2008 00:26:44 +0800
parents c30080146c05
children 5527133b7c7e
files Ikariam.pm scan.pl
diffstat 2 files changed, 61 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/Ikariam.pm	Mon Nov 17 00:25:56 2008 +0800
+++ b/Ikariam.pm	Mon Nov 17 00:26:44 2008 +0800
@@ -118,16 +118,23 @@
         debug => undef,
     };
 
-
     # if debug
     LWP::Debug::level('+trace');
 
-    $self->{mech}->cookie_jar(HTTP::Cookies->new(file => "/tmp/ikariam-cookies.txt", autosave => 1));
+    $self->{mech}->cookie_jar(HTTP::Cookies->new(file => "/tmp/ikariam-$server-cookies.txt", autosave => 1, ignore_discard => 1));
     $self->{mech}->default_headers->push_header('Accept-Encoding', 'deflate');
  
     return bless $self, $class;
 }
 
+sub clone
+{
+    my $self = shift;
+    my $copy = bless { %$self }, ref $self;  # copy most fields
+
+    $copy;
+}
+
 sub viewAlly
 {
     my $self = shift;
--- a/scan.pl	Mon Nov 17 00:25:56 2008 +0800
+++ b/scan.pl	Mon Nov 17 00:26:44 2008 +0800
@@ -3,12 +3,30 @@
 use Data::Dumper;
 use Carp;
 use Ikariam;
+use Parallel::ForkManager;
 
 package main;
 
+package Ikariam::Scanner;
+use strict;
+use Carp;
+use Ikariam;
+use Data::Dumper;
+use Parallel::ForkManager;
+
+sub new {
+    my($class, $i) = @_;
+    warn("new scanner");
+    my $self = {
+        ikariam => $i,
+    };
+
+    return bless $self, $class;
+}
+
 sub saveCities
 {
-    my ($island, @cities) = @_;
+    my ($self, $island, @cities) = @_;
 
     if ($#cities == -1) {
         warn ("empty cities list.\n");
@@ -16,7 +34,8 @@
     }
 
     foreach my $h_city (@cities) {
-# Carp::carp(sprintf("checking %s\n", $h_city->{'cityname'}));
+        # Carp::carp(sprintf("checking %s\n", $h_city->{'cityname'}));
+        print(STDERR sprintf("checking cityname %s\n", $h_city->{'cityname'}));
         $h_city->{island} = $island;
         $h_city->{'time'} = time;
         my $c = Ikariam::Cities->retrieve($h_city->{cityId});
@@ -32,43 +51,47 @@
         my $user = Ikariam::User->retrieve($h_city->{'user'});
         next if (defined($user) && defined($user->time) && $user->time gt (time - 30*60));
 
-        saveUser($h_city->{owner});
+        $self->saveUser($h_city->{owner});
     }
 }
 
 sub saveUser
 {
+    my $self = shift;
     my $userName = shift;
     my $users;
 
     foreach my $x (qw/score army_score_main trader_score_secondary/) {
-        $users = $::i->viewScore($x, $userName, 0);
+        my $i = $self->{ikariam}->clone();
+        $users = $i->viewScore($x, $userName, 0);
 
         foreach my $h_user (values(%{$users})) {
-# Carp::carp(sprintf("Saving user %s\n", $h_user->{'name'}));
+            # Carp::carp(sprintf("Saving user %s\n", $h_user->{'name'}));
             $h_user->{'time'} = time;
-
             my $user = Ikariam::User->retrieve($h_user->{'id'});
             if(defined($user)) {
+                # check if the arm score is down
                 foreach (keys(%$h_user)) { $user->set($_ => $h_user->{$_}); }
             } else {
                 $user = Ikariam::User->insert($h_user);
             }
             $user->update();
-            saveAlly($h_user->{allyId});
+            $self->saveAlly($h_user->{allyId});
         }
     }
 }
 
 sub saveAlly
 {
+    my $self = shift;
     my $allyId = shift;
     return unless (defined($allyId) && $allyId ne '0');
 
     # Save for member of ally 
     my $ally = Ikariam::Ally->retrieve($allyId);
     if(!defined($ally) || $ally->time le (time - 30*60*1)) {
-        my $h_ally = $::i->viewAlly($allyId);
+        my $i = $self->{ikariam}->clone();
+        my $h_ally = $i->viewAlly($allyId);
         $h_ally->{'time'} = time;
         if(defined($ally)) {
             foreach (keys(%$h_ally)) { $ally->set($_ => $h_ally->{$_}); }
@@ -79,12 +102,15 @@
 }
 
 sub saveIslands {
-    my @islands = @_;
+    my ($self, @islands) = @_;
+
+    my $pm = new Parallel::ForkManager(10);
 
     foreach my $h_island (@islands)
     {
-        # printf("checking island %d\n", $h_island->{id});
-
+        my $pid = $pm->start and next;
+        
+        printf("checking island %d\n", $h_island->{id});
         my $island;
         if($island = Ikariam::Island->retrieve($h_island->{id})) {
             foreach my $i (keys(%$h_island)) {
@@ -98,16 +124,22 @@
         # 10 minutes cache.
         if($island->time le (time - 60*10))
         {
-            my @cities = $::i->viewIsland($h_island->{id});
-            saveCities($h_island->{id}, @cities);
+            my $i = $self->{ikariam}->clone();
+            my @cities = 
+                $i->viewIsland($h_island->{id});
+            $self->saveCities($h_island->{id}, @cities);
 
             $island->set('time', time);
         }
         $island->update();
-
+        $pm->finish;
     }
+    $pm->wait_all_children;
 }
 
+1;
+
+package main;
 
 # local $SIG{ALRM} = sub { die "timeout\n" };
 # alarm 3;
@@ -116,24 +148,23 @@
 if($#ARGV == 1) {
     $i->login;
     my @islands = $i->viewWorldMap($ARGV[0], $ARGV[1]);
-    saveIslands(@islands);
-    $i->logout;
+    # my $s = new Ikariam::Scanner($i);
+    # $s->saveIslands(@islands);
+    new Ikariam::Scanner($i)->saveIslands(@islands);
 } elsif($#ARGV == 0) {
     $i->login;
     my $island = $ARGV[0];
     my @cities = $i->viewIsland($island);
-    saveCities($island, @cities);
-    $i->logout;
+    new Ikariam::Scanner($i)->saveCities($island, @cities);
 } elsif($#ARGV == -1) {
     $i->login;
     my $cities = $i->check;
     # random
     foreach my $cityId (keys(%$cities)) {
-# Carp::carp(sprintf("Checking island location [%s:%s]\n", $cities->{$cityId}->{island}->{x},  $cities->{$cityId}->{island}->{y}));
         my @islands = $i->viewWorldMap( $cities->{$cityId}->{island}->{x},  $cities->{$cityId}->{island}->{y});
-        saveIslands(@islands);
+        new Ikariam::Scanner($i)->saveIslands(@islands);
     }
-    $i->logout;
 } else {
     die("Usage: $0\nUsage: $0 x y\n");
 }
+$i->logout;