Skip to content

Commit 6e3b670

Browse files
committed
Updated qury path for better rate limiting.
Added post-request check for prepared statement in queries to enable calls to rate limiters if none were set previously. Also updated QueryRequest.doesWrites() to check for SELECT vs other query types.
1 parent 7826c06 commit 6e3b670

File tree

4 files changed

+75
-14
lines changed

4 files changed

+75
-14
lines changed

driver/src/main/java/oracle/nosql/driver/http/Client.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,13 @@ public Result execute(Request kvRequest) {
536536
updateRateLimiters(((TableResult)res).getTableName(), tl);
537537
}
538538

539+
if (rateLimiterMap != null && readLimiter == null) {
540+
readLimiter = getQueryRateLimiter(kvRequest, true);
541+
}
542+
if (rateLimiterMap != null && writeLimiter == null) {
543+
writeLimiter = getQueryRateLimiter(kvRequest, false);
544+
}
545+
539546
/* consume rate limiter units based on actual usage */
540547
rateDelayedMs += consumeLimiterUnits(readLimiter,
541548
res.getReadUnitsInternal(),
@@ -697,6 +704,40 @@ public Result execute(Request kvRequest) {
697704
kvRequest.getRetryStats(), exception);
698705
}
699706

707+
/**
708+
* Returns a rate limiter for a query operation, if the query op has
709+
* a prepared statement and a limiter exists in the rate limiter map
710+
* for the query table.
711+
*/
712+
private RateLimiter getQueryRateLimiter(Request request, boolean read) {
713+
if (rateLimiterMap == null || !(request instanceof QueryRequest)) {
714+
return null;
715+
}
716+
717+
/*
718+
* If we're asked for a write limiter, and the request doesn't
719+
* do writes, return null
720+
*/
721+
if (read == false && ((QueryRequest)request).doesWrites() == false) {
722+
return null;
723+
}
724+
725+
/*
726+
* We sometimes may only get a prepared statement after the
727+
* first query response is returned. In this case, we can get
728+
* the tablename from the request and apply rate limiting.
729+
*/
730+
String tableName = ((QueryRequest)request).getTableName();
731+
if (tableName == null || tableName == "") {
732+
return null;
733+
}
734+
735+
if (read) {
736+
return rateLimiterMap.getReadLimiter(tableName);
737+
}
738+
return rateLimiterMap.getWriteLimiter(tableName);
739+
}
740+
700741

701742
/**
702743
* Comsume rate limiter units after successful operation.

driver/src/main/java/oracle/nosql/driver/ops/PreparedStatement.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,22 @@ public class PreparedStatement {
8585
/*
8686
* The namespace returned from a prepared query result, if any.
8787
*/
88-
private String namespace;
88+
private final String namespace;
8989

9090

9191
/*
9292
* The table name returned from a prepared query result, if any.
9393
*/
94-
private String tableName;
94+
private final String tableName;
9595

96+
/*
97+
* the operation code for the query.
98+
*/
99+
private final byte operation;
100+
101+
/* The one operation code we care about */
102+
/* "5" == PrepareCallback.QueryOperation.SELECT */
103+
private final byte OPCODE_SELECT = 5;
96104

97105
/**
98106
* @hidden
@@ -111,6 +119,7 @@ public class PreparedStatement {
111119
* @param externalVars external variables for the query
112120
* @param namespace namespace, if any, from deserialization
113121
* @param tableName table name, if any, from deserialization
122+
* @param operation operation code for the query
114123
*/
115124
public PreparedStatement(
116125
String sqlText,
@@ -122,7 +131,8 @@ public PreparedStatement(
122131
int numRegisters,
123132
Map<String, Integer> externalVars,
124133
String namespace,
125-
String tableName) {
134+
String tableName,
135+
byte operation) {
126136

127137
/* 10 is arbitrary. TODO: put magic number in it for validation? */
128138
if (proxyStatement == null || proxyStatement.length < 10) {
@@ -140,6 +150,7 @@ public PreparedStatement(
140150
this.variables = externalVars;
141151
this.namespace = namespace;
142152
this.tableName = tableName;
153+
this.operation = operation;
143154
}
144155

145156
/**
@@ -160,7 +171,8 @@ public PreparedStatement copyStatement() {
160171
numRegisters,
161172
variables,
162173
namespace,
163-
tableName);
174+
tableName,
175+
operation);
164176
}
165177

166178
/**
@@ -378,4 +390,13 @@ public String getNamespace() {
378390
public String getTableName() {
379391
return tableName;
380392
}
393+
394+
/**
395+
* @hidden
396+
* @return true if the query does writes
397+
*/
398+
public boolean doesWrites() {
399+
/* if it's not SELECT, it does writes */
400+
return operation != OPCODE_SELECT;
401+
}
381402
}

driver/src/main/java/oracle/nosql/driver/ops/QueryRequest.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,7 @@ public boolean isQueryRequest() {
212212
@Override
213213
public boolean doesReads() {
214214
/*
215-
* Currently there is no easy/dependable mechanism to tell if
216-
* a query will do reads or writes. So we assume the most likely
217-
* case. TODO: update this when we have better info
215+
* Just about every permutation of query does reads
218216
*/
219217
return true;
220218
}
@@ -224,12 +222,10 @@ public boolean doesReads() {
224222
*/
225223
@Override
226224
public boolean doesWrites() {
227-
/*
228-
* Currently there is no easy/dependable mechanism to tell if
229-
* a query will do reads or writes. So we assume the most likely
230-
* case. TODO: update this when we have better info
231-
*/
232-
return false;
225+
if (preparedStatement == null) {
226+
return false;
227+
}
228+
return preparedStatement.doesWrites();
233229
}
234230

235231
/**

driver/src/main/java/oracle/nosql/driver/ops/serde/PrepareRequestSerializer.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,13 @@ static PreparedStatement deserializeInternal(
8080
* byte (number of tables)
8181
* namespace (string)
8282
* tablename (string)
83+
* operation (1 byte)
8384
*/
8485
int savedOffset = in.getOffset();
8586
in.skip(37); // 4 + 32 + 1
8687
String namespace = readString(in);
8788
String tableName = readString(in);
89+
byte operation = in.readByte();
8890
in.setOffset(savedOffset);
8991

9092
byte[] proxyStatement = readByteArrayWithInt(in);
@@ -129,6 +131,7 @@ static PreparedStatement deserializeInternal(
129131
numRegisters,
130132
externalVars,
131133
namespace,
132-
tableName);
134+
tableName,
135+
operation);
133136
}
134137
}

0 commit comments

Comments
 (0)