Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Waiting requests functionality issue within Volley library (PriorityBlockingQueue.java)

I have a problem with the waiting requests functionality in the volley library. The debugging led me to the AbstractQueue class in java.util where an element is being added (according to some values in the method that indicate a successful addition to the queue) and simultaneously - not being added(according to the 0 elements in the queue - that don't change their value). The adding method is synchronized. Bellow you can find a detailed description of the situation and my research so far. I will be really thankful if you have a look at them and share if you have any idea what is happening.

I try to automatically retry requests upon any kind of error ( for example - when there is no connection, or the server name is not correct ). The error handler of a request adds the request back to the static singleton RequestQueue of my app.

RetriableRequestWraper.java

m_request = new StringRequest(
            method,
            url,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    handleResponse(response);
                }
            },

            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError volleyError) {
                    handleError(volleyError);
                }
            });

public void handleError(VolleyError volleyError)
{
    Log.d("Request: ", m_request.toString());
    Log.d("handleError: ", volleyError.toString());
    if(retriesCount<3)
    {
        executeRequest();
        ++retriesCount;
    }
    else
    {
        retriesCount = 0;
    }
}

public void executeRequest()
{
    RequestsManager.getInstance().executeRequest(m_request);
}

public void executeRequest(Request request)
{
    Log.d("executeRequest ","m_requestQueue.add(request)");
    m_requestQueue.add(request);
}

RequestManager.java

public void executeRequest(Request request)
{
    Log.d("executeRequest ","m_requestQueue.add(request)");
    m_requestQueue.add(request);
}

This approach doesn't work and when debugging inside the volley library I come to the point where the request could not be added to the mCacheQueue of the RequestQueue class, because the cacheKey of the reuqest is present in the mWaitingRequests Map. So the request is added in the queue in mWaitingRequests map, corresponding to its key. When the previous request is finished - the new one is not added to the queue although these lines are being executed in the RequestQueue class:

synchronized(this.mWaitingRequests) {
            String cacheKey1 = request.getCacheKey();
            Queue waitingRequests1 = (Queue)this.mWaitingRequests.remove(cacheKey1);
            if(waitingRequests1 != null) {
                if(VolleyLog.DEBUG) {
                    VolleyLog.v("Releasing %d waiting requests for cacheKey=%s.", new Object[]{Integer.valueOf(waitingRequests1.size()), cacheKey1});
                }

                this.mCacheQueue.addAll(waitingRequests1);
            }
        }

When debugging further this line

this.mCacheQueue.addAll(waitingRequests1);

In the AbstractQueue.java (class in java.util ) the element is being added to the queue, the "modified" value is true, but throughout the hole time the "this" parameter continues to contain 0 elements.

    public boolean addAll(Collection<? extends E> c) {
    if (c == null)
        throw new NullPointerException("c == null");
    if (c == this)
        throw new IllegalArgumentException("c == this");
    boolean modified = false;
    for (E e : c)
        if (add(e))
            modified = true;
    return modified;
}

Inside the offer(E e) method of PriorityBlockingQueue.java the execution of the program stops at line 453.

l452 siftUpUsingComparator(n, e, array, cmp);
l453 size = n+1;

Obviously the returned value is true, but the element is not added. My debugger could not get into the method that adds the element - siftUpUsingComparator(n, e, array, cmp);

I am going to add a timer before retrying my request, and will construct a new one. So I am not really interested in a workaround, I want to understand what and how is happening in this situation. Do you have any idea as to what could be the reason behind this?

like image 792
Radostina Poulain Radost Avatar asked Nov 08 '22 23:11

Radostina Poulain Radost


1 Answers

The issue is that you try to add the same Request instance once again to the queue it has been added to. This messes up with the queue and the Request itself as it has states. For example if you simply enable markers you'll have a crash. The solution is to either just use the default retry policy or clone the requests.

like image 175
kalin Avatar answered Nov 14 '22 21:11

kalin