Changeset 16071 for lang/perl/Data-Valve
- Timestamp:
- 07/22/08 09:38:42 (5 years ago)
- Location:
- lang/perl/Data-Valve/trunk
- Files:
-
- 9 modified
-
Valve.xs (modified) (2 diffs)
-
dv_bucket.c (modified) (7 diffs)
-
dv_bucket.h (modified) (4 diffs)
-
lib/Data/Valve.pm (modified) (4 diffs)
-
lib/Data/Valve/Bucket.pm (modified) (1 diff)
-
lib/Data/Valve/BucketStore.pm (modified) (1 diff)
-
lib/Data/Valve/BucketStore/Memory.pm (modified) (3 diffs)
-
lib/Data/Valve/BucketStore/Object.pm (modified) (1 diff)
-
t/01_basic.t (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
lang/perl/Data-Valve/trunk/Valve.xs
r15617 r16071 8 8 9 9 dv_bucket * 10 dv_bucket_create(double interval, unsigned long max )10 dv_bucket_create(double interval, unsigned long max, int strict_interval = 0) 11 11 12 12 void … … 44 44 45 45 dv_bucket * 46 dv_bucket__deserialize(SV *buf, double interval, long max )46 dv_bucket__deserialize(SV *buf, double interval, long max, int strict_interval = 0) 47 47 PREINIT: 48 48 STRLEN len; 49 49 char *c_buf = (char *)SvPV(ST(0), len); 50 50 CODE: 51 RETVAL = dv_bucket_deserialize(c_buf, len, interval, max );51 RETVAL = dv_bucket_deserialize(c_buf, len, interval, max, strict_interval); 52 52 OUTPUT: 53 53 RETVAL -
lang/perl/Data-Valve/trunk/dv_bucket.c
r15625 r16071 33 33 34 34 dv_bucket* 35 dv_bucket_create(double interval, unsigned long max )35 dv_bucket_create(double interval, unsigned long max, int strict_interval) 36 36 { 37 37 dv_bucket *bucket; … … 41 41 bucket->interval = interval * DV_1E6; 42 42 bucket->count = 0; 43 bucket->strict_interval = strict_interval; 43 44 bucket->head = NULL; 44 45 bucket->tail = NULL; … … 106 107 */ 107 108 size_t expired = 0; 109 double dtime = dv_bucket_timeval2double(tp); 108 110 109 111 while ( 110 112 bucket->head != NULL && 111 bucket->interval < d v_bucket_timeval2double(tp)- bucket->head->time113 bucket->interval < dtime - bucket->head->time 112 114 ) { 113 115 dv_bucket_item *tmp = bucket->head; … … 125 127 126 128 int 127 dv_bucket_is_full(dv_bucket *bucket) 128 { 129 dv_bucket_is_full(dv_bucket *bucket, double dtime) 130 { 131 if (bucket->count == 0 || bucket->head == NULL) { 132 /* safety net */ 133 return 0; 134 } 135 136 /* if we're in strict_interval mode, then we check for the last entry 137 * in the list, and make sure that current time is more than 138 * last entry + interval 139 */ 140 if (bucket->strict_interval) { 141 return bucket->head->time + bucket->interval > dtime; 142 } 143 144 /* Otherwise, we care about how many items are in the list */ 129 145 return bucket->max <= bucket->count; 130 146 } … … 149 165 { 150 166 struct timeval t; 167 double dtime; 151 168 152 169 gettimeofday(&t, &tzp_not_used); … … 154 171 dv_bucket_expire( bucket, &t ); 155 172 173 dtime = dv_bucket_timeval2double(&t); 174 156 175 if ( dv_bucket_count( bucket ) == 0 ) { 157 dv_bucket_push( bucket, d v_bucket_timeval2double(&t));176 dv_bucket_push( bucket, dtime ); 158 177 return 1; 159 178 } 160 179 161 if ( dv_bucket_is_full(bucket ) ) {180 if ( dv_bucket_is_full(bucket, dtime) ) { 162 181 return 0; 163 182 } 164 183 165 dv_bucket_push( bucket, d v_bucket_timeval2double(&t));184 dv_bucket_push( bucket, dtime ); 166 185 return 1; 167 186 } … … 183 202 184 203 dv_bucket * 185 dv_bucket_deserialize(char *buf, size_t len, double interval, unsigned long max )186 { 187 dv_bucket *bucket = dv_bucket_create(interval, max );204 dv_bucket_deserialize(char *buf, size_t len, double interval, unsigned long max, int strict_interval) 205 { 206 dv_bucket *bucket = dv_bucket_create(interval, max, strict_interval); 188 207 char *end = buf + len; 189 208 -
lang/perl/Data-Valve/trunk/dv_bucket.h
r15617 r16071 18 18 unsigned long max; 19 19 double interval; 20 int strict_interval; 20 21 unsigned long count; 21 22 dv_bucket_item *head; … … 29 30 /* Creates a new bucket */ 30 31 dv_bucket * 31 dv_bucket_create(double interval, unsigned long max );32 dv_bucket_create(double interval, unsigned long max, int strict_interval); 32 33 33 34 /* Frees a bucket */ … … 57 58 /* Returns true if count >= max */ 58 59 int 59 dv_bucket_is_full(dv_bucket *bucket );60 dv_bucket_is_full(dv_bucket *bucket, double dtime); 60 61 61 62 /* Pushes a new item on to the bucket */ … … 73 74 /* Deserialize a bucket from a string */ 74 75 dv_bucket * 75 dv_bucket_deserialize(char *buf, size_t len, double interval, unsigned long max );76 dv_bucket_deserialize(char *buf, size_t len, double interval, unsigned long max, int strict_interval); 76 77 77 78 /* returns the first bucket item */ -
lang/perl/Data-Valve/trunk/lib/Data/Valve.pm
r15826 r16071 23 23 ); 24 24 25 has 'strict_interval' => ( 26 is => 'rw', 27 isa => 'Bool', 28 required => 1, 29 default => 0 30 ); 31 25 32 has '__bucket_store' => ( 26 33 accessor => 'bucket_store', 27 34 is => 'rw', 28 35 does => 'Data::Valve::BucketStore', 36 required => 1, 29 37 ); 30 38 … … 33 41 no Moose; 34 42 35 sub BUILD {36 my ($self, $args) = @_;43 sub BUILDARGS { 44 my ($self, %args) = @_; 37 45 38 my $store = delete $args ->{bucket_store} || { module => 'Memory' };46 my $store = delete $args{bucket_store} || { module => 'Memory' }; 39 47 if (! blessed $store) { 40 48 my $module = $store->{module}; … … 44 52 Class::MOP::load_class($module); 45 53 46 $store = $module->new( %{ $store->{args} } , context => $self);54 $store = $module->new( %{ $store->{args} } ); 47 55 } 48 $self->bucket_store($store); 56 57 if ($args{strict_interval}) { 58 # in strict_interval mode, max_items doesn't mean anything 59 $args{max_items} = 0; 60 } 61 62 return { %args, __bucket_store => $store }; 63 } 64 65 sub BUILD { 66 my $self = shift; 67 $self->bucket_store->context($self); 49 68 } 50 69 … … 90 109 mechanism is much simpler than Data::Throttler, and so is faster. 91 110 92 It also comes with Memcached support for a distributed throttling. 111 It also comes with Memcached support for a distributed throttling via 112 memcached + keyedmutexd. This means that you can have multiple hosts throttling 113 on the same "key". For example, multiple crawler instances can throttle 114 requests against a single host safely. To enable distributed throttling, 115 you simply need to specify a Data::Valve::BucketStore instance that supports 116 distribution (i.e. Data::Valve::BucketStore::Memcached) or create your own 117 instance, and pass it to the constructor: 118 119 Data::Valve->new( 120 ..., 121 bucket_store => { 122 module => "Memcached", # to use Data::Valve::BucketStore::Memcached 123 args => { 124 servers => [ '127.0.0.1:11211' ] 125 } 126 } 127 ); 128 129 Please note that for distributed throttling to work, you must specify the 130 correct values in max_items, interval, and so forth, for each Data::Valve 131 instance. Data::Valve will not try to automatically adjust this for you. 132 You must coordinate it in the client side (i.e., whatever that's using 133 Data::Valve) 134 135 Since version 0.00006, Data::Valve supports "strict_interval" mode, where 136 instead of counting the number of items over a range of time, it simply 137 calculates the amount of time elapsed since the last logged request. 138 139 To enable, specify it in the constrctor: 140 141 # This specifies that at least 5 seconds should have passed before 142 # the next item can go 143 Data::Valve->new( 144 interval => 5, 145 strict_interval => 1, 146 ); 93 147 94 148 =head1 METHODS 149 150 =head2 new(%args) 151 152 =over 4 153 154 =item max_items 155 156 In strict interval mode, does not mean anything. If NOT in strict interval 157 mode, specifies the max number of items that can go through this throttler 158 in the given interval. 159 160 =item interval 161 162 In strict interval mode, this specifies the number of seconds to wait between 163 each request. If NOT in strict interval mode, specifies the number of seconds 164 to span the requests, up to the value specified in max_items 165 166 C<interval> may be a fractional number, denoting fractional seconds. 167 168 =item strict_interval 169 170 Boolean. Enable/Disable strict interval mode. Default is off. 171 172 =cut 95 173 96 174 =head2 try_push([key => $key_name]) -
lang/perl/Data-Valve/trunk/lib/Data/Valve/Bucket.pm
r15629 r16071 6 6 sub new { 7 7 my ($class, %args) = @_; 8 my $self = bless create($args{interval}, $args{max_items}), $class; 8 $args{strict_interval} ||= 0; 9 my $self = bless create($args{interval}, $args{max_items}, $args{strict_interval}), $class; 9 10 10 11 return $self; -
lang/perl/Data-Valve/trunk/lib/Data/Valve/BucketStore.pm
r15824 r16071 9 9 is => 'rw', 10 10 isa => 'Data::Valve', 11 handles => [ qw(max_items interval ) ],11 handles => [ qw(max_items interval strict_interval) ], 12 12 ); 13 13 -
lang/perl/Data-Valve/trunk/lib/Data/Valve/BucketStore/Memory.pm
r15824 r16071 9 9 is => 'rw', 10 10 isa => 'HashRef', 11 required => 1, 12 default => sub { +{} } 11 13 ); 12 14 … … 15 17 no Moose; 16 18 17 sub BUILD {18 my $self = shift;19 $self->store( {20 __default => $self->create_bucket()21 } );22 }23 24 19 sub create_bucket 25 20 { … … 27 22 return Data::Valve::Bucket->new( 28 23 max_items => $self->max_items, 29 interval => $self->interval 24 interval => $self->interval, 25 strict_interval => $self->strict_interval, 30 26 ); 31 27 } -
lang/perl/Data-Valve/trunk/lib/Data/Valve/BucketStore/Object.pm
r15790 r16071 40 40 my $bucket; 41 41 if ($bucket_source) { 42 $bucket = Data::Valve::Bucket->deserialize($bucket_source, $self->interval, $self->max_items );42 $bucket = Data::Valve::Bucket->deserialize($bucket_source, $self->interval, $self->max_items, $self->strict_interval); 43 43 } else { 44 44 $bucket = Data::Valve::Bucket->new( 45 interval => $self->interval, 46 max_items => $self->max_items, 45 interval => $self->interval, 46 max_items => $self->max_items, 47 strict_interval => $self->strict_interval 47 48 ); 48 49 } -
lang/perl/Data-Valve/trunk/t/01_basic.t
r15595 r16071 1 1 use strict; 2 use Test::More (tests => 16);2 use Test::More (tests => 20); 3 3 4 4 BEGIN … … 45 45 ok( $valve->try_push(key => "foo"), "try after 3 seconds should work"); 46 46 } 47 48 { 49 my $valve = Data::Valve->new( 50 max_items => 5, 51 interval => 3, 52 strict_interval => 1, 53 ); 54 55 ok( $valve->try_push(key => "foo"), "try 1 should succeed" ); 56 ok(! $valve->try_push(key => "foo"), "try 2 should fail" ); 57 diag("sleeping for 3 seconds..."); 58 sleep 3; 59 ok( $valve->try_push(key => "foo"), "try 3 should succeed" ); 60 ok(! $valve->try_push(key => "foo"), "try 4 should fail" ); 61 }
![(please configure the [header_logo] section in trac.ini)](/share/chrome/site/your_project_logo.png)