制定计划
October 26th, 2005 by 1e0n现在制定计划如下:
1.简化程序,主要去掉或修改一些无用的测试注释。
2.使程序输入信息清晰易懂,而不是乱七八糟的,这个很重要哦:)
3.优化一些代码。
主要是完成1,2先,然后Release出v0.4 test2版本。
之后应该就是Candidate1了……
完成后Release出v0.5.
现在制定计划如下:
1.简化程序,主要去掉或修改一些无用的测试注释。
2.使程序输入信息清晰易懂,而不是乱七八糟的,这个很重要哦:)
3.优化一些代码。
主要是完成1,2先,然后Release出v0.4 test2版本。
之后应该就是Candidate1了……
完成后Release出v0.5.
稍微整理了下代码,去掉了一些无用测试语句的注释,保持代码的清晰度是很重要的。
#!/usr/bin/perl -w
#use strict;
# file:prime_main
# main program of prime_project.
# by:leon 05/10/26 v0.3.10
use Socket;
use IO::Handle;
use read_write_db qw(read_db write_db);
use cal_prime qw(cal_prime_by_step);
# Bidirectional communication using socketpair
socketpair(CHILD, PARENT, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "socketpair: $!";
CHILD->autoflush(1);
PARENT->autoflush(1);
unless ($pid = fork) {
# This is Child,for calculate prime
die "cannot fork: $!" unless defined $pid;
close CHILD;
# Child ignore "ctrl+c"
$SIG{INT} = ‘IGNORE’;
# Read date from database for prepare calculate
local (@prime_n_array,$prime_step_id,@new_prime_id_array,@new_prime_n_array);
read_db(*prime_n_array,*prime_step_id);
while (1) {
$|=1;
print PARENT "go_on?\n";
chomp($line = <PARENT>);
if ($line eq "go_on") {
# Parent didn’t catch "ctrl+c" so we go on next step calculate
# print "\b";
print "In step:$prime_step_id\n";
cal_prime_by_step(*prime_n_array,*prime_step_id,*new_prime_id_array,*new_prime_n_array);
# When finish a step save data to database
write_db(*new_prime_id_array,*new_prime_n_array,*prime_step_id);
} elsif ($line eq "exit") {
# Parent catch "ctrl+c" so we stop
print "Child: Saving step data before exit\n";
write_db(*new_prime_id_array,*new_prime_n_array,*prime_step_id);
print "Child: Saved!\n";
print PARENT "child_finish\n";
last;
} else {
# For Extensions
print "Child: I don’t understand What Parent say.\n";
exit;
}
}
print "Child: Exiting\n";
close PARENT;
exit;
} else {
# This is Parent,for control Child
close PARENT;
# Catch ctrl+c,but don’t exit directly.Parent send a msg
# to Child then exit after Child finish ending work
$SIG{INT} = sub {$int_count++};
# When Child finish a step and ask Parent if go on or do something else
# Parent responses a answer
while (chomp($line = <CHILD>)) {
# Parent catch "ctrl+c" and ask Child to exit.
if ($int_count) {
# Now we should ignore ctrl+c!
$SIG{INT} = ‘IGNORE’;
# Do some ending job
print "Parent: Calling Child to finish job\n";
print CHILD "exit\n";
chomp($line = <CHILD>);
if ($line eq "child_finish") {
print "Parent: All job finish\n";
print "Parent: Exiting\n";
last;
} else {
print "Parent: I don’t understand What Child say.\n";
}
}
# Havn’t catch ctrl+c,so let Child go on next step
if ($line eq "go_on?") {
print CHILD "go_on\n";
} else {
# For Extensions
print "Parent: I don’t understand What Child say.\n";
}
}
close CHILD;
waitpid($pid,0);
}
由于prime_main的体积过于庞大,都超过100行了,我在考虑是否要将子进程和父进程的对话交互部分分离出一个模块来专门处理。
这是个很好的想法,不过在这之前还是处理好其他事情先把。
让输入信息更加简洁易懂了:
# ./prime_main
step:115
step:116
step:117
step:118
step:119
step:120
step:121
step:122
step:123
step:124
step:125
Parent: Calling Child to finish job
Child: Saving step data before exit
Child: Saved!
Parent: All job finish
Parent: Exiting
Child: Exiting
以下是程序:
#!/usr/bin/perl -w
#use strict;
# file:prime_main
# main program of prime_project.
# by:leon 05/10/26 v0.3.9
use Socket;
use IO::Handle;
use read_write_db qw(read_db write_db);
use cal_prime qw(cal_prime_by_step);
# Bidirectional communication using socketpair
socketpair(CHILD, PARENT, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "socketpair: $!";
CHILD->autoflush(1);
PARENT->autoflush(1);
unless ($pid = fork) {
# This is Child,for calculate prime
die "cannot fork: $!" unless defined $pid;
close CHILD;
# Child ignore "ctrl+c"
$SIG{INT} = ‘IGNORE’;
# Read date from database for prepare calculate
local (@prime_n_array,$prime_step_id,@new_prime_id_array,@new_prime_n_array);
read_db(*prime_n_array,*prime_step_id);
while (1) {
print PARENT "go_on?\n";
chomp($line = <PARENT>);
if ($line eq "go_on") {
# Parent didn’t catch "ctrl+c" so we go on next step calculate
#$i = 0;
#while (++$i<150) {
# Go into a calculate prime step
print "step:$prime_step_id\n";
cal_prime_by_step(*prime_n_array,*prime_step_id,*new_prime_id_array,*new_prime_n_array);
#print "new_id: @new_prime_id_array\n";
#print "new_n: @new_prime_n_array\n";
write_db(*new_prime_id_array,*new_prime_n_array,*prime_step_id);
#}
#last;
} elsif ($line eq "exit") {
# Parent catch "ctrl+c" so we stop
print "Child: Saving step data before exit\n";
write_db(*new_prime_id_array,*new_prime_n_array,*prime_step_id);
print "Child: Saved!\n";
print PARENT "child_finish\n";
last;
} else {
# For Extensions
print "Child: I don’t understand What Parent say.\n";
exit;
}
}
print "Child: Exiting\n";
close PARENT;
exit;
} else {
# This is Parent,for control Child
close PARENT;
# Catch ctrl+c,but don’t exit directly.Parent send a msg
# to Child then exit after Child finish ending work
$SIG{INT} = sub {$int_count++};
# When Child finish a step and ask Parent if go on or do something else
# Parent responses a answer
while (chomp($line = <CHILD>)) {
# Parent catch "ctrl+c" and ask Child to exit.
if ($int_count) {
# Now we should ignore ctrl+c!
$SIG{INT} = ‘IGNORE’;
# Do some ending job
print "Parent: Calling Child to finish job\n";
print CHILD "exit\n";
chomp($line = <CHILD>);
if ($line eq "child_finish") {
print "Parent: All job finish\n";
print "Parent: Exiting\n";
last;
} else {
print "Parent: I don’t understand What Child say.\n";
}
}
if ($line eq "go_on?") {
print CHILD "go_on\n";
} else {
# For Extensions
print "Parent: I don’t understand What Child say.\n";
}
}
close CHILD;
waitpid($pid,0);
}
我把prime-0.4.0.test1.tar.gz的第一个测试版放在这里:
prime-0.4.0.test1.tar.gz
现在的整个project都可以工作了。
下一步是修正bug和提升性能的过程。
BUG:
1.发现现在ctrl+c没用,子进程和父进程都没反应,首先修改这个bug吧。
#!/usr/bin/perl
# file:read_write_db.pm
# read mysql database into hashref or write back hashref to database.
# by:1e0n 05/10/26 v0.3.5
package read_write_db;
require Exporter;
@ISA = qw(Exporter);
@EXPORT_OK = qw(read_db write_db);
use DBI();
use read_conf qw($user $pwd);
sub read_db {
# Use Typeglob to make a efficient prarmeter passing
local (*cp_prime_n_array,*cp_prime_step_id) = @_;
my $n;
# Connect to the database.
my $dbh = DBI->connect("DBI:mysql:database=prime_db;host=localhost",
$user,$pwd,
{’RaiseError’ => 1});
# pick out all prime to ref && sqrt_of_prime_id to ref
my $prime_n_ref = $dbh->selectall_arrayref("SELECT prime_n FROM prime_table");
my $prime_step_id_ref = $dbh->selectrow_arrayref("SELECT MAX(prime_step_id) FROM prime_table");
# copy prime to array "copy_prime",$cp_prime_n_array[0] is no use but we let it equal 1.
# we start from $cp_prime_n_array[1] = 2 which mean the first prime is 2.
@cp_prime_n_array = (1);
foreach (@$prime_n_ref) {
$cp_prime_n_array[++$n]=$_->[0];
}
$cp_prime_step_id = $prime_step_id_ref->[0];
#print "列数: $#{$ref}+1 行数?: $#{$ref->[0]}+1\n";
#print "@$ref[0]->[1]\n";
# after reading data disconnect mysql
$dbh -> disconnect();
}
sub write_db {
local (*cp_new_prime_id_array,*cp_new_prime_n_array,*cp_prime_step_id)=@_;
# Connect to the database.
my $dbh = DBI->connect("DBI:mysql:database=prime_db;host=localhost",
$user,$pwd,
{’RaiseError’ => 1});
$insert = $dbh->prepare("INSERT INTO prime_table (id,prime_n,prime_step_id) VALUES (?,?,?)");
my $i=0;
for (@cp_new_prime_id_array) {
$insert->execute($_,@cp_new_prime_n_array[$i],$cp_prime_step_id) or die ($dbh->errstr);
$i++;
}
# after reading data disconnect mysql
$dbh -> disconnect();
}
1;
write_db也写好了,现在整个程序ok了!
prime_main加了个参数给write_db。
#!/usr/bin/perl -w
#use strict;
# file:prime_main
# main program of prime_project.
# by:leon 05/10/26 v0.3.9
use Socket;
use IO::Handle;
use read_write_db qw(read_db write_db);
use cal_prime qw(cal_prime_by_step);
# Bidirectional communication using socketpair
socketpair(CHILD, PARENT, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "socketpair: $!";
CHILD->autoflush(1);
PARENT->autoflush(1);
unless ($pid = fork) {
# This is Child,for calculate prime
die "cannot fork: $!" unless defined $pid;
close CHILD;
print "CHILD PID:$$\n";
# Child ignore "ctrl+c"
$SIG{INT} = ‘IGNORE’;
# Read date from database for prepare calculate
local (@prime_n_array,$prime_step_id,@new_prime_id_array,@new_prime_n_array);
read_db(*prime_n_array,*prime_step_id);
#print "@prime_n_array,$prime_step_id\n";
while (1) {
print PARENT "go_on?\n";
chomp($line = <PARENT>);
if ($line eq "go_on") {
# Parent didn’t catch "ctrl+c" so we go on next step calculate
$i = 0;
while (++$i<150) {
# Go into a calculate prime step
print "step:$prime_step_id\n";
cal_prime_by_step(*prime_n_array,*prime_step_id,*new_prime_id_array,*new_prime_n_array);
print "new_id: @new_prime_id_array\n";
print "new_n: @new_prime_n_array\n";
write_db(*new_prime_id_array,*new_prime_n_array,*prime_step_id);
}
last;
} elsif ($line eq "exit") {
# Parent catch "ctrl+c" so we stop
print "Child do something before exit\n";
write_db(*new_prime_id_array,*new_prime_n_array);
exit;
} else {
# For Extensions
print "Child:I don’t understand What Parent say.\n";
exit;
}
}
print "CHILD end\n";
close PARENT;
exit;
} else {
# This is Parent,for control Child
close PARENT;
# Catch ctrl+c,but don’t exit directly.Parent send a msg
# to Child then exit after Child finish ending work
$SIG{INT} = sub {$int_count++};
while (chomp($line = <CHILD>)) {
if ($int_count) {
print CHILD "exit\n";
last; #jump out of "while"
}
if ($line eq "go_on?") {
print CHILD "go_on\n";
} else {
# For Extensions
print "Parent:I don’t understand What Child say.\n";
}
}
print "Parent going to exit.\n";
close CHILD;
waitpid($pid,0);
}
跟着prime_main改的,返回两个新prime的数组变量保存新算出来的prime给主程序,主程序再提供给write_db()。
#!/usr/bin/perl
# file:cal_prime.pm
# calculate prime.
# by:1e0n 05/10/26 v0.3.5
package cal_prime;
require Exporter;
@ISA = qw(Exporter);
@EXPORT_OK = qw(cal_prime_by_step);
sub cal_prime_by_step {
# Use Typeglob to make a efficient prarmeter passing
local (*cp_prime_n_array,*cp_prime_step_id,*cp_new_prime_id_array,*cp_new_prime_n_array) = @_;
@cp_new_prime_id_array = ();
@cp_new_prime_n_array = ();
$prime_n_last = $cp_prime_n_array[-1];
my $prime_id_count = @cp_prime_n_array-1;
#print "prime_n_array: @cp_prime_n_array\n";
#print "last prime: $prime_n_last\n";
#print "count: $prime_id_count\n";
#print "sqrt_of_prime_id: $cp_prime_step_id\n";
#print "sqrt_of_prime_n: $cp_prime_n_array[$cp_prime_step_id]\n";
# Use Typeglob to change name
local *prime = *cp_prime_n_array;
local *last_num_to_cal = *prime_n_last;
# We can use "do{something;}while();" function in the follow code
# but it’s unclear
$last_num_to_cal += 2;
$cp_prime_step_id++;
# Go into a calculate prime step
while ($last_num_to_cal < $prime[$cp_prime_step_id]**2) {
$if_prime = 1;
#print "checking $last_num_to_cal with step $cp_prime_step_id\n";
for (1..$cp_prime_step_id) {
if ($last_num_to_cal % $prime[$_] == 0) {
$if_prime = 0;
last;
}
}
if ($if_prime) {
$prime[++$prime_id_count] = $last_num_to_cal;
push @cp_new_prime_id_array,$prime_id_count;
push @cp_new_prime_n_array,$last_num_to_cal;
#print "$prime_id_count prime is $last_num_to_cal\n";
#print $last_num_to_cal." ";
}
$last_num_to_cal += 2;
}
}
1;
加入了两个变量给write_db提供新prime数据的参数,其实现在这个方法并不高性能而且多消耗了内存。
不过为了简单起见先用这个方法处理好write_db。
下面write_db可以动工了。
#!/usr/bin/perl -w
#use strict;
# file:prime_main
# main program of prime_project.
# by:leon 05/10/26 v0.3.8
use Socket;
use IO::Handle;
use read_write_db qw(read_db write_db);
use cal_prime qw(cal_prime_by_step);
# Bidirectional communication using socketpair
socketpair(CHILD, PARENT, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "socketpair: $!";
CHILD->autoflush(1);
PARENT->autoflush(1);
unless ($pid = fork) {
# This is Child,for calculate prime
die "cannot fork: $!" unless defined $pid;
close CHILD;
print "CHILD PID:$$\n";
# Child ignore "ctrl+c"
$SIG{INT} = ‘IGNORE’;
# Read date from database for prepare calculate
local (@prime_n_array,$prime_step_id,@new_prime_id_array,@new_prime_n_array);
read_db(*prime_n_array,*prime_step_id);
#print "@prime_n_array,$prime_step_id\n";
while (1) {
print PARENT "go_on?\n";
chomp($line = <PARENT>);
if ($line eq "go_on") {
# Parent didn’t catch "ctrl+c" so we go on next step calculate
$i = 0;
while (++$i<3) {
# Go into a calculate prime step
print "step:$prime_step_id\n";
cal_prime_by_step(*prime_n_array,*prime_step_id,*new_prime_id_array,*new_prime_n_array);
print "new_id: @new_prime_id_array\n";
print "new_n: @new_prime_n_array\n";
write_db();
}
last;
} elsif ($line eq "exit") {
# Parent catch "ctrl+c" so we stop
print "Child do something before exit\n";
write_db();
exit;
} else {
# For Extensions
print "Child:I don’t understand What Parent say.\n";
exit;
}
}
print "CHILD end\n";
close PARENT;
exit;
} else {
# This is Parent,for control Child
close PARENT;
# Catch ctrl+c,but don’t exit directly.Parent send a msg
# to Child then exit after Child finish ending work
$SIG{INT} = sub {$int_count++};
while (chomp($line = <CHILD>)) {
if ($int_count) {
print CHILD "exit\n";
last; #jump out of "while"
}
if ($line eq "go_on?") {
print CHILD "go_on\n";
} else {
# For Extensions
print "Parent:I don’t understand What Child say.\n";
}
}
print "Parent going to exit.\n";
close CHILD;
waitpid($pid,0);
}