6969import oracle .nosql .driver .util .ByteOutputStream ;
7070import oracle .nosql .driver .util .RateLimiterMap ;
7171import oracle .nosql .driver .util .SerializationUtil ;
72- import oracle .nosql .driver .util .SimpleRateLimiter ;
7372
7473import io .netty .buffer .ByteBuf ;
7574import io .netty .channel .Channel ;
@@ -379,6 +378,11 @@ public Result execute(Request kvRequest) {
379378 long thisTime = System .currentTimeMillis ();
380379 int thisIterationTimeoutMs = timeoutMs - (int )(thisTime - startTime );
381380
381+ /*
382+ * Check rate limiters before executing the request.
383+ * Wait for read and/or write limiters to be below their limits
384+ * before continuing. Be aware of the timeout given.
385+ */
382386 if (readLimiter != null && checkReadUnits == true ) {
383387 try {
384388 /*
@@ -524,10 +528,10 @@ public Result execute(Request kvRequest) {
524528 /* consume rate limiter units based on actual usage */
525529 rateDelayedMs += consumeLimiterUnits (readLimiter ,
526530 res .getReadUnitsInternal (),
527- kvRequest , thisIterationTimeoutMs );
531+ thisIterationTimeoutMs );
528532 rateDelayedMs += consumeLimiterUnits (writeLimiter ,
529533 res .getWriteUnitsInternal (),
530- kvRequest , thisIterationTimeoutMs );
534+ thisIterationTimeoutMs );
531535 res .setRateLimitDelayedMs (rateDelayedMs );
532536
533537 /* copy retry stats to Result on successful operation */
@@ -716,21 +720,20 @@ private RateLimiter getQueryRateLimiter(Request request, boolean read) {
716720 return rateLimiterMap .getWriteLimiter (tableName );
717721 }
718722
719-
720723 /**
721724 * Comsume rate limiter units after successful operation.
722725 * @return the number of milliseconds delayed due to rate limiting
723726 */
724- private int consumeLimiterUnits (RateLimiter rl , long units ,
725- Request request , int timeoutMs ) {
727+ private int consumeLimiterUnits (RateLimiter rl ,
728+ long units , int timeoutMs ) {
726729
727730 if (rl == null || units <= 0 ) {
728731 return 0 ;
729732 }
730733
731734 /*
732735 * The logic consumes units (and potentially delays) _after_ a
733- * successful operation for a few reasons:
736+ * successful operation for a couple reasons:
734737 * 1) We don't know the actual number of units an op uses unitl
735738 * after the operation successfully finishes
736739 * 2) Delaying after the op keeps the application from immediately
@@ -740,32 +743,12 @@ private int consumeLimiterUnits(RateLimiter rl, long units,
740743 * after a successful op, client threads will get staggered
741744 * better to avoid spikes in throughput and oscillation that
742745 * can result from it.
743- * 3) For operations that use less than 100% of the limits (i.e.
744- * they set a usePercent to less than 100), this is the only place
745- * where the delay time may be longer, because the pre-operation
746- * "wait for below the limit" limiter checks do not take usePercent
747- * into account.
748746 */
749747
750- double usePercent = request .getRateLimiterPercentage ();
751- if (usePercent == 0.0 ) {
752- usePercent = config .getDefaultRateLimitingPercentage ();
753- }
754748 try {
755- if (rl instanceof SimpleRateLimiter && usePercent > 0.0 ) {
756- /* "true" == "consume units, even on timeout" */
757- return ((SimpleRateLimiter )rl ).consumeUnitsWithTimeout (
758- units , timeoutMs ,
759- true , usePercent );
760- } else {
761- /* "true" == "consume units, even on timeout" */
762- return rl .consumeUnitsWithTimeout (units , timeoutMs , true );
763- }
749+ return rl .consumeUnitsWithTimeout (units , timeoutMs , false );
764750 } catch (TimeoutException e ) {
765- /*
766- * Do not throw: the operation succeeded.
767- * We just delayed a while.
768- */
751+ /* Don't throw - operation succeeded. Just return timeoutMs. */
769752 return timeoutMs ;
770753 }
771754 }
@@ -807,14 +790,19 @@ public boolean updateRateLimiters(String tableName, TableLimits limits) {
807790 int durationSeconds = Integer .getInteger ("test.rldurationsecs" , 30 )
808791 .intValue ();
809792
810- rateLimiterMap .update (tableName ,
811- (double )limits .getReadUnits (),
812- (double )limits .getWriteUnits (),
813- durationSeconds );
793+ double RUs = (double )limits .getReadUnits ();
794+ double WUs = (double )limits .getWriteUnits ();
795+
796+ /* if there's a specified rate limiter percentage, use that */
797+ double rlPercent = config .getDefaultRateLimitingPercentage ();
798+ if (rlPercent > 0.0 ) {
799+ RUs = (RUs * rlPercent ) / 100.0 ;
800+ WUs = (WUs * rlPercent ) / 100.0 ;
801+ }
814802
803+ rateLimiterMap .update (tableName , RUs , WUs , durationSeconds );
815804 final String msg = String .format ("Updated table '%s' to have " +
816- "RUs=%d and WUs=%d per second" ,
817- tableName , limits .getReadUnits (), limits .getWriteUnits ());
805+ "RUs=%.1f and WUs=%.1f per second" , tableName , RUs , WUs );
818806 logInfo (logger , msg );
819807
820808 return true ;
@@ -1146,7 +1134,8 @@ public void resetRateLimiters(String tableName) {
11461134 * executed by one thread when no other operations are
11471135 * in progress.
11481136 */
1149- public void enableRateLimiting (boolean enable ) {
1137+ public void enableRateLimiting (boolean enable , double usePercent ) {
1138+ config .setDefaultRateLimitingPercentage (usePercent );
11501139 if (enable == true && rateLimiterMap == null ) {
11511140 rateLimiterMap = new RateLimiterMap ();
11521141 tableLimitUpdateMap = new ConcurrentHashMap <String , AtomicLong >();
0 commit comments