点击下载 (刚修订了一些bug,甚至连逻辑也改了,所以下面的内容也就没什么意义,要源代码的可电邮我gyn_tadao@yahoo.com.cn,要运行下载代码请先安装TCL解析器http://www.activestate.com/activetcl/downloads/)因为对
bugd
中的
item
状态需要定时地进行判断,以确定其是否过期。也就是说,对于
due
中的值小于当前日期但
status
却未
fixed
的,可以认为该
item
就是过期的了,需要将
status
更新为
outdated
。这种事情对于
sqlserver
之类的数据库,一般只需要做一个简单的
schedule
就可以了,但是在
bugd
中我采用的是
sqlite
作为服务器端的数据库,所以这个
schedule
不得不自己编了。
之前,我使用
perl
来写了一个,之后思索着索性写一个
sqlite
的
schedule
工具吧,最好还是带
GUI
的。这并不难,
bugd
中的组件正好可以利用。说干就干,两天的功夫就完成了。跟
bugd
很像,算是一个派生物了吧,但是复杂度小了很多,一则实现的功能比较单一,不需要复杂的界面配套;二来,不是
CS
的结构,考虑的问题都集中在本地。真正的难点是怎么维护一个对各个事件需要发生的时间的判断,同时又可以方便地增加和删除
schedule
事件。在这里,我维护了
一个名为
rl
的队列,意思是
runing-list
,将需要进入
schedule
的事件名称放入到该队列中,要停止的时候再将其从该队列中移除,由专门的函数循环处理该队列。
该函数叫
runSchedule
,形式如下。其中的
yet
用于判断是否已经在当天检查了时间队列
rl
。
proc runSchedule {} {
global rl loop_interval yet
update idletask
if [at 00:00:00] {
if $yet {
schedule $rl
set yet 0
}
}
after [expr $loop_interval * 1000] runSchedule
}
在原来的函数中,我是使用
after idle
来进行循环的,由于使用了
update idletasks
,该程序界面运行第很流畅,但是在资源管理器中
cpu
的使用率达到了
100%
,没办法是能改为一个秒级的
interval
。
每个新的一天到来的时候,真正的队列处理在
schedule
被处理。该函数如下:
proc schedule {rl} {
global cmd scdl dbl
set sep1 @
set sep2 |
foreach n $rl {
set m [dict get $cmd $n]
set s [dict get $scdl $n]
set d [dict get $dbl $n]
foreach {ery dy tm} [split $s $sep1] {}
switch $ery {
month { set d [clock format [clock seconds] -format "%d"]}
week {set d [clock format [clock seconds] -format "%a"]}
default {}
}
if [info exists d] {
foreach e [split $dy $sep2] {
if {$e eq $d} {
runCommand $tm $d $m
}
}
} else {
runCommand $tm $m
}
}
}
在
schedule
中,根据
rl
中的事件名称,将通过
cmd
、
scdl
和
dbl
三个
dict
,调出对应的命令,运行时间和所在的数据库。之后通过
runCommand
来根据具体时间来运行
SQL
命令。
proc runCommand {tm db cmd} {
global loop_interval
if ![at $tm] {
update idletask
after [expr $loop_interval * 1000] [list runCommand $tm $cmd]
} else {
sqlite3 d $db
if [catch {d eval $cmd} err] {
updateStatusInfo [join $err _]
}
d close
}
}
最后需要说明的是
at
函数,它是用来判断是否过了所给定的时间的,也就是说只要当前时间大于输入参数,它就返回为真,不然为否。所以真正意义上应该叫做
after
,但是
after
已经是
tcl
默认函数了,所以改成了
at
。
proc at {tm} {
global yet
if {[clock scan $tm] >= [clock seconds]} {set yet 1; return 1}
return 0
}