improve locking

git-svn-id: file:///root/webif/svn/pkg/webif/trunk@2845 2a923420-c742-0410-a762-8d5b09965624
This commit is contained in:
hummypkg 2016-04-10 13:24:16 +00:00
parent 7bbfa758c1
commit 9ce18af5cf
3 changed files with 106 additions and 79 deletions

View File

@ -1,7 +1,7 @@
Package: webif Package: webif
Priority: optional Priority: optional
Section: web Section: web
Version: 1.2.8-15 Version: 1.2.8-16
Architecture: mipsel Architecture: mipsel
Maintainer: af123@hpkg.tv Maintainer: af123@hpkg.tv
Depends: tcpfix,webif-channelicons(>=1.1.20),lighttpd(>=1.4.39-1),jim(>=0.76-1),jim-oo,jim-sqlite3(>=0.76),jim-cgi(>=0.7-1),jim-binary(>=0.76),service-control(>=2.1),busybox(>=1.20.2-1),lsof(>=4.87),epg(>=1.2.1-1),hmt(>=2.0.9),ssmtp,cron-daemon(>=1.18.3-3),at(>=3.1.18),anacron,trm(>=1.1),openssl-command,nicesplice,id3v2,file,rsvsync(>=1.0.2),webif-charts(>=1.2-1),stripts(>=1.2.5-3),tmenu(>=1.08),ffmpeg,id3v2,multienv(>=1.6),tcpping(>=1.1),e2fsprogs,wireless-tools(>=29-1),dbupdate,recmon(>=2.0.7) Depends: tcpfix,webif-channelicons(>=1.1.20),lighttpd(>=1.4.39-1),jim(>=0.76-1),jim-oo,jim-sqlite3(>=0.76),jim-cgi(>=0.7-1),jim-binary(>=0.76),service-control(>=2.1),busybox(>=1.20.2-1),lsof(>=4.87),epg(>=1.2.1-1),hmt(>=2.0.9),ssmtp,cron-daemon(>=1.18.3-3),at(>=3.1.18),anacron,trm(>=1.1),openssl-command,nicesplice,id3v2,file,rsvsync(>=1.0.2),webif-charts(>=1.2-1),stripts(>=1.2.5-3),tmenu(>=1.08),ffmpeg,id3v2,multienv(>=1.6),tcpping(>=1.1),e2fsprogs,wireless-tools(>=29-1),dbupdate,recmon(>=2.0.7)

View File

@ -56,67 +56,97 @@ proc {file touch} {target {ref ""}} {
} }
proc {file tdelete} {target} { proc {file tdelete} {target} {
if {[file isdirectory $target]} { try {
foreach f [readdir -nocomplain $target] { if {[file isdirectory $target]} {
file tdelete "$target/$f" foreach f [readdir -nocomplain $target] {
file tdelete "$target/$f"
}
exec /mod/bin/busybox/rm -rf $target
} else {
exec /mod/bin/trm $target
} }
exec /mod/bin/busybox/rm -rf $target } on error {msg opts} {
} else { incr opts(-level)
exec /mod/bin/trm $target return {*}$opts $msg
} }
} }
proc {file read} {target {bytes 0}} { proc {file read} {target {bytes 0}} {
if {[file readable $target]} { try {
set fd [open $target] if {[file readable $target]} {
if {$bytes} { set fd [open $target]
set ret [$fd read $bytes] if {$bytes} {
} else { set ret [$fd read $bytes]
set ret [$fd read] } else {
set ret [$fd read]
}
$fd close
return $ret
} }
$fd close error "Cannot read $target"
return $ret } on error {msg opts} {
incr opts(-level)
return {*}$opts $msg
} }
error "Cannot read $target"
} }
proc {file write} {target content} { proc {file write} {target content} {
if {[catch {set fd [open $target w]} msg]} { try {
error "Open failed, $msg" if {[catch {set fd [open $target w]} msg]} {
} else { error "Open failed, $msg"
$fd puts -nonewline $content } else {
$fd close $fd puts -nonewline $content
$fd close
}
} on error {msg opts} {
incr opts(-level)
return {*}$opts $msg
} }
} }
set ::fileops::locks {} set ::fileops::locks {}
proc {file lock} {target} { proc {file lock} {{create {}} target} {
if {[dict exists $::fileops::locks $target]} { try {
return 0 if {$create ni {{} -create}} {
} error "bad option \"$create\": should be -create"
if {[catch {set fd [open $target w]} msg]} {
error "open '$target' failed, $msg"
} else {
set ret [$fd lock]
if {$ret == 1} {
set ::fileops::locks($target) $fd
} else {
$fd close
} }
return $ret if {[dict exists $::fileops::locks $target]} {
return 0
}
if {$create eq "" && ![file exists $target]} {
error "'$target' does not exist"
} elseif {[catch {set fd [open $target w]} msg]} {
error "open '$target' failed, $msg"
} else {
set ret [$fd lock]
if {$ret == 1} {
set ::fileops::locks($target) $fd
} else {
$fd close
}
return $ret
}
} on error {msg opts} {
incr opts(-level)
return {*}$opts $msg
} }
} }
proc {file unlock} {target} { proc {file unlock} {target} {
if {[dict exists $::fileops::locks $target]} { try {
set fd $::fileops::locks($target) if {[dict exists $::fileops::locks $target]} {
dict unset ::fileops::locks $target set fd $::fileops::locks($target)
set ret [$fd unlock] dict unset ::fileops::locks $target
$fd close set ret [$fd unlock]
return $ret $fd close
return $ret
}
error "$target was not locked."
} on error {msg opts} {
incr opts(-level)
return {*}$opts $msg
} }
error "$target was not locked."
} }
local proc file {cmd args} { local proc file {cmd args} {

View File

@ -1,50 +1,47 @@
#!/mod/bin/jimsh #!/mod/bin/jimsh
set ::_lock::locks {} set ::lock::locks {}
# For testing, 'ababab' collides with 'b'
proc ::_lock::hash {id} {{hashes {}}} {
set len [string length $id]
set hash $len
for {set i 0} {$i < $len} {incr i} {
scan [string index $id $i] "%c" asc
set hash [expr (($hash<<5)^($hash>>27))^$asc];
}
set hash [expr (65535 - ($hash % 101))]
while {[dict exists $hashes $hash] && $hashes($hash) ne $id} {
#puts "Hash collision."
if {[incr hash] > 65535} { set hash 32768 }
}
set hashes($hash) $id
return $hash
}
proc acquire_lock {id {timeout 0} {interval 0.2}} { proc acquire_lock {id {timeout 0} {interval 0.2}} {
set port [::_lock::hash $id] try {
incr timeout [clock seconds] if {[dict exists $::lock::locks $id]} {
#error "Lock already held"
set lock $::lock::locks($id)
} else {
set file "/var/lock/.webiflock_[system filename $id]"
set fh [open $file w]
set lock [list file $file fh $fh]
set ::lock::locks($id) $lock
}
while {[catch {set socket [\ incr timeout [clock seconds]
socket stream.server "127.0.0.1:$port"]} msg]} {
if {[clock seconds] > $timeout} { return 0 } while {[$lock(fh) lock] != 1} {
sleep $interval if {[clock seconds] > $timeout} { return 0 }
sleep $interval
}
return 1
} on error {msg opts} {
incr opts(-level)
return {*}$opts $msg
} }
set ::_lock::locks($id) $socket
return 1
} }
proc release_lock {id} { proc release_lock {id} {
if {![dict exists $::_lock::locks $id]} { return 0 } try {
if {[catch {close $::_lock::locks($id)} msg]} { if {![dict exists $::lock::locks $id]} {
#puts "Error releasing lock: $msg" error "Lock not held."
return 0 }
set lock $::lock::locks($id)
set ret [$lock(fh) unlock]
$lock(fh) close
dict unset ::lock::locks $id
return $ret
} on error {msg opts} {
incr opts(-level)
return {*}$opts $msg
} }
unset ::_lock::locks($id)
return 1
} }