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
clientKeyByteslength is greater than 255 then I will skip it and continue iterating. - I will keep incrementing the
totalSizevariable which will be the sum ofclientKeyLengthandprocessBytesLength, and thistotalSizelength should always be less than 50000 bytes. - As soon as it reaches the 50000 limit, I will send the
clientKeyBytesAndProcessBytesHoldermap to thesendToDatabasemethod and clear out the map, resettotalSizeto 0 and start populating again. - If it doesn't reaches that limit and
dataHoldersgot 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.