procs
2 TopicsWhat are good or bad uses of irule Procs
I want to provide global debugging control over irules I have deployed so that I can target the logging of debug information for specific events, hosts, uri, vs, pool, etc, across these irules. I plan to use a proc that will log a message to the LTM log if the current set of debug targets are met. The targets will be set as static variables. This proc will be called multiple times in a variety of irules I have written to log debug information. I am concerned that using a Proc will introduce a performance issue. Please advise287Views0likes1CommentNested Procs in an iRule
Since iRules don't support the expr ceil(args) function, I'm trying to implement a TCL version that I found at https://searchcode.com/codesearch/view/16742115/ This implement uses multiple reusable procs. When I format my iRule with these procs, the recusion doesn't seem to process correctly and I'm wondering if there are any restrictions here? The below code results in this error on my system (11.4.1 HF3) 01070151:3: Rule [/Common/math] error: /Common/math:37: error: [undefined procedure: isFloat][isFloat $x] /Common/math:37: error: [undefined procedure: isInt][isInt $x] /Common/math:59: error: [undefined procedure: checkFloat][checkFloat $x] /Common/math:71: error: [undefined procedure: checkNumber][checkNumber $a] /Common/math:72: error: [undefined procedure: iszero][iszero $a] /Common/math:109: error: [undefined procedure: bits][bits $delta] /Common/math:131: error: [undefined procedure: normalize][normalize $number] /Common/math:145: error: [undefined procedure: opp][opp $try] These have been copied from https://searchcode.com/codesearch/view/16742115/ returns 1 if x is a BigFloat, 0 elsewhere proc isFloat {x} { a BigFloat is a list of : "F" mantissa exponent delta if {[llength $x]!=4} { return 0 } the marker is the letter "F" if {[string equal [lindex $x 0] F]} { return 1 } return 0 } checks that n is a BigInt (a number create by math::bignum::fromstr) proc isInt {n} { if {[llength $n]>1} { return 0 } if {[string is digit $n]} { return 1 } return 1 } checks if each number is either a BigFloat or a BigInt arguments : each argument is the name of a variable to be checked proc checkNumber {x} { if {![isFloat $x] && ![isInt $x]} { error "input is not an integer, nor a BigFloat" } } checks each variable to be a BigFloat arguments : each argument is the name of a variable to be checked proc checkFloat {number} { if {![isFloat $number]} { error "BigFloat expected" } } returns 1 if x is null, 0 otherwise proc iszero {x} { if {[isInt $x]} { return [expr {$x==0}] } checkFloat $x now we do some interval rounding : if a number's interval englobs 0, it is considered to be equal to zero foreach {dummy integer exp delta} $x {break} if {$delta>=abs($integer)} {return 1} return 0 } returns -A (the opposite) proc opp {a} { checkNumber $a if {[iszero $a]} { return $a } if {[isInt $a]} { return [expr {-$a}] } recursive call lset a 1 [expr {-[lindex $a 1]}] return $a } bits : computes the number of bits of an integer, approx. proc bits {int} { set l [string length [set int [expr {abs($int)}]]] int<10**l -> log_2(int)=l*log_2(10) set l [expr {int($l*log(10)/log(2))+1}] if {$int>>$l!=0} { error "bad result: $l bits" } while {($int>>($l-1))==0} { incr l -1 } return $l } normalizes a number : Delta (accuracy of the BigFloat) has to be limited, because the memory use increase quickly when we do some computations, as the Mantissa and Delta increase together The solution : limit the size of Delta to 16 bits proc normalize {number} { checkFloat $number foreach {dummy integer exp delta} $number {break} set l [bits $delta] if {$l>16} { incr l -16 $l holds the supplementary size (in bits) now we can shift right by $l bits always round upper the Delta set delta [expr {$delta>>$l}] incr delta set integer [expr {$integer>>$l}] incr exp $l } return [list F $integer $exp $delta] } returns the integer part of a BigFloat, as a BigInt the result is the same one you would have if you had called [expr {ceil($x)}] Case C1631422 proc ceil {number} { checkFloat $number set number [normalize $number] if {[iszero $number]} { return 0 } foreach {dummy integer exp delta} $number {break} if {$exp>=0} { error "not enough precision to perform rounding (ceil)" } saving the sign ... set sign [expr {$integer<0}] set integer [expr {abs($integer)}] integer part set try [expr {$integer>>(-$exp)}] if {$sign} { return [opp $try] } fractional part if {($try<<(-$exp))!=$integer} { return [incr try] } return $try } These have been copied from https://searchcode.com/codesearch/view/16742115/ returns 1 if x is a BigFloat, 0 elsewhere proc isFloat {x} { a BigFloat is a list of : "F" mantissa exponent delta if {[llength $x]!=4} { return 0 } the marker is the letter "F" if {[string equal [lindex $x 0] F]} { return 1 } return 0 } checks that n is a BigInt (a number create by math::bignum::fromstr) proc isInt {n} { if {[llength $n]>1} { return 0 } if {[string is digit $n]} { return 1 } return 1 } checks if each number is either a BigFloat or a BigInt arguments : each argument is the name of a variable to be checked proc checkNumber {x} { if {![isFloat $x] && ![isInt $x]} { error "input is not an integer, nor a BigFloat" } } checks each variable to be a BigFloat arguments : each argument is the name of a variable to be checked proc checkFloat {number} { if {![isFloat $number]} { error "BigFloat expected" } } returns 1 if x is null, 0 otherwise proc iszero {x} { if {[isInt $x]} { return [expr {$x==0}] } checkFloat $x now we do some interval rounding : if a number's interval englobs 0, it is considered to be equal to zero foreach {dummy integer exp delta} $x {break} if {$delta>=abs($integer)} {return 1} return 0 } returns -A (the opposite) proc opp {a} { checkNumber $a if {[iszero $a]} { return $a } if {[isInt $a]} { return [expr {-$a}] } recursive call lset a 1 [expr {-[lindex $a 1]}] return $a } bits : computes the number of bits of an integer, approx. proc bits {int} { set l [string length [set int [expr {abs($int)}]]] int<10**l -> log_2(int)=l*log_2(10) set l [expr {int($l*log(10)/log(2))+1}] if {$int>>$l!=0} { error "bad result: $l bits" } while {($int>>($l-1))==0} { incr l -1 } return $l } normalizes a number : Delta (accuracy of the BigFloat) has to be limited, because the memory use increase quickly when we do some computations, as the Mantissa and Delta increase together The solution : limit the size of Delta to 16 bits proc normalize {number} { checkFloat $number foreach {dummy integer exp delta} $number {break} set l [bits $delta] if {$l>16} { incr l -16 $l holds the supplementary size (in bits) now we can shift right by $l bits always round upper the Delta set delta [expr {$delta>>$l}] incr delta set integer [expr {$integer>>$l}] incr exp $l } return [list F $integer $exp $delta] } returns the integer part of a BigFloat, as a BigInt the result is the same one you would have if you had called [expr {ceil($x)}] Case C1631422 proc ceil {number} { checkFloat $number set number [normalize $number] if {[iszero $number]} { return 0 } foreach {dummy integer exp delta} $number {break} if {$exp>=0} { error "not enough precision to perform rounding (ceil)" } saving the sign ... set sign [expr {$integer<0}] set integer [expr {abs($integer)}] integer part set try [expr {$integer>>(-$exp)}] if {$sign} { return [opp $try] } fractional part if {($try<<(-$exp))!=$integer} { return [incr try] } return $try }264Views0likes1Comment