I have a method which takes a parameter which is Partition
enum. This method will be called by multiple background threads around same time period by passing different value of partition
. Here dataHoldersByPartition
is a map of Partition
and ConcurrentLinkedQueue<DataHolder>
.
private void validateAndSend(final Partition partition) {
ConcurrentLinkedQueue<DataHolder> dataHolders = dataHoldersByPartition.get(partition);
Map<byte[], byte[]> clientKeyBytesAndProcessBytesHolder = new HashMap<>();
int totalSize = 0;
DataHolder dataHolder;
while ((dataHolder = dataHolders.poll()) != null) {
byte[] clientKeyBytes = dataHolder.getClientKey().getBytes(StandardCharsets.UTF_8);
if (clientKeyBytes.length > 255)
continue;
byte[] processBytes = dataHolder.getProcessBytes();
int clientKeyLength = clientKeyBytes.length;
int processBytesLength = processBytes.length;
int additionalLength = clientKeyLength + processBytesLength;
if (totalSize + additionalLength > 50000) {
Message message = new Message(partition, clientKeyBytesAndProcessBytesHolder);
sendToDatabase(message.getAddress(), message.getLocation());
clientKeyBytesAndProcessBytesHolder.clear(); // watch out for gc
totalSize = 0;
}
clientKeyBytesAndProcessBytesHolder.put(clientKeyBytes, processBytes);
totalSize += additionalLength;
}
// calling again with remaining values only if clientKeyBytesAndProcessBytesHolder is not empty
if(!clientKeyBytesAndProcessBytesHolder.isEmpty()) {
Message message = new Message(partition, clientKeyBytesAndProcessBytesHolder);
sendToDatabase(message.getAddress(), message.getLocation());
}
}
In the method, I will iterate dataHolders
CLQ and I will extract clientKeyBytes
and processBytes
from it. Here is the validation that I am supposed to do:
- If the
clientKeyBytes
length is greater than 255 then I will skip it and continue iterating. - I will keep incrementing the
totalSize
variable which will be the sum ofclientKeyLength
andprocessBytesLength
, and thistotalSize
length should always be less than 50000 bytes. - As soon as it reaches the 50000 limit, I will send the
clientKeyBytesAndProcessBytesHolder
map to thesendToDatabase
method and clear out the map, resettotalSize
to 0 and start populating again. - If it doesn't reaches that limit and
dataHolders
got empty, then it will send whatever it has.
Basically, what I have to make sure is whenever the sendToDatabase
method is called, the clientKeyBytesAndProcessBytesHolder
map should have size less than 50000 (sum of all keys and values length). It should never be called with the size greater than 50000 (50k).
Question:
My code works fine, but as you can see, I am calling the sendToDatabase
method at two places: one is as soon as it is reaching the 50k
limit, and the other is it didn't reach because we ran out of elements.
Is there any way by which I can call the sendToDatabase
method just once and still fulfill both my conditions by rewriting it in a better way? I am working with Java 7.