Wednesday, May 8, 2013

Moodle - Initial try for bug fixing of MDL-36020

As a prerequisite, fixing existing Moodle bugs is crucial to the GSoC application for Moodle projects. Among the list of bugs suggested by Tim, it is hard to justify their difficulty for a beginner.

Anyway, browsing through the list and finally decide to try this one:

From the description, it is some bug related to the re-grading function. The first step would thus to locate where these actions are processed. 

Directly diving into the codes makes me even confusing and cannot find even a start. Have to do the other way, i.e. trying the system. 

Creating a dummy course, registering a bunch of dummy users and design a set of questions to form a quiz. Using different accounts to attempt the quiz and finally the regrading button shows up.

The regrading lies in the Results section of Quiz module. In the source code it doesn't have a separate page but a set of functions. 

The codes are under the path moodle/mod/quiz/
Especially in the file moodle/mod/quiz/overview/report.php

Following are the functions responsible for the regrading:

process_actions($quiz, $cm, $currentgroup, $groupstudents, $allowed, $redirecturl)
Based on the action received, calling corresponding functions. Actions include "regrade", "regradeall", "regradealldry", "regradealldrydo".

regrade_attempt($attempt, $dryrun = false, $slots = null)
Regrade a particular quiz attempt. This is where the actual regrading happens. It is called by other methods.

regrade_attempts($quiz, $dryrun = false,
            $groupstudents = array(), $attemptids = array())
Regrade a set of attempts for this quiz. The set of attempts are specified by the input parameters. For each attempt, the regrading is done by the above regrade_attempt() function.

regrade_attempts_needing_it($quiz, $groupstudents)
Regrade all the attempts of the specified quiz that are marked as needing regrading.

count_question_attempts_needing_regrade($quiz, $groupstudents)
Count the number of attempts that needs regrading for the specified quiz.

has_regraded_questions($from, $where, $params)
Check whether there are any pending regrades to show.

clear_regrade_table($quiz, $groupstudents)
Remove all information about pending/complete regrades from database.

Update the final grades for all attempts in the quiz.

These are probably the place to resolving the bug and a general problem for all the regrading action, we may need to fix it in the process_actions() function. 

Next, how to fix the problem. From the description, the problem is due to the long processing time of the regrading which leads to the user session time out. 

Personally, I don't like the questions such as how good are you at xxx? how familiar are you with xxx? I have no idea what standards could be used to evaluated such as goodness or familiarity. No matter what standard you took, the answer will always be subjective and most of time  helpless.

Regarding Tim's question "what the session is". As I have never studies PHP in a systematical way, I only knows it keeps track of a user's information during his/her visiting of the website. And the only thing I have touched session in PHP is during last summer's GSoC. 
a) After a user logs in, the session_start() is called;
b) $_SESSION['variable']=value is used when I need to pass over some variables between different pages;
c) session_destroy() is called when the user logs out.
That's all I know about sessions in PHP.

Regarding the second question "why it might normally lock?", I have no idea. But with the help of Google, I learned following aspects:

a) From, the session locks due to multiple requests to access the same session file and could be solved by closing the session with session_write_close() before starting the long running process. This function only close the write session capability, the session variables are still readable. 

It seems a solution but how can we guarantee that there will be no session write requests after this?



    Putting the long run script to background by:


    This could put the script running in background. However, Other PHP files may not be opened until this scripts finish.

    session_write_close(); may solve the problem but what if we want to change the session variables after it?

  2. Currently, my thought to solve the problem is to add following lines to the code somewhere before the regrading happens:





  3. By the way, adding session_start() after the script execution should be fine, too.