Ticket #3433: 3433_replay_cache_v1.2.patch

File 3433_replay_cache_v1.2.patch, 3.9 KB (added by Imarok, 8 years ago)

Some style fixes

  • source/ps/VisualReplay.cpp

     
    6262}
    6363
    6464/**
    65  * Load all replays found in the directory.
    66  *
    67  * Since files are spread across the harddisk,
    68  * loading hundreds of them can consume a lot of time.
     65 * Load the replay cache and check if there are new/deleted ones
     66 * If so, update their data.
    6967 */
    7068JS::Value VisualReplay::GetReplays(ScriptInterface& scriptInterface)
    7169{
     
    7270    TIMER(L"GetReplays");
    7371    JSContext* cx = scriptInterface.GetContext();
    7472    JSAutoRequest rq(cx);
     73   
     74    std::map<CStr, u32> fileList;
    7575
     76    const OsPath cacheFileName = GetDirectoryName() / L"replayCache.json";
     77    JS::RootedObject cachedReplaysObject(cx);
     78
     79    bool cacheFound = FileExists(cacheFileName);
     80    if (cacheFound)
     81    {
     82        // Open cache file
     83        std::istream* cacheStream = new std::ifstream(cacheFileName.string8().c_str());
     84
     85        // Read file into chacheStr
     86        CStr cacheStr((std::istreambuf_iterator<char>(*cacheStream)), std::istreambuf_iterator<char>());
     87
     88        // Create empty JS object and parse the context of the cache into it
     89        JS::RootedValue cachedReplays(cx);
     90        scriptInterface.ParseJSON(cacheStr, &cachedReplays);
     91        SAFE_DELETE(cacheStream);
     92
     93        JS::RootedObject temp(cx, &cachedReplays.toObject());
     94        cachedReplaysObject = temp;
     95
     96        // Create list of files included in the cache
     97        u32 cacheLength = 0;
     98        JS_GetArrayLength(cx, cachedReplaysObject, &cacheLength);
     99        for (u32 j = 0; j < cacheLength ; ++j)
     100        {
     101            JS::RootedValue replay(cx);
     102            JS_GetElement(cx, cachedReplaysObject, j, &replay);
     103
     104            JS::RootedObject replayObject(cx, &replay.toObject());
     105            JS::RootedValue file(cx);
     106            JS_GetProperty(cx, replayObject, "directory", &file);
     107
     108            CStr fileName;
     109            scriptInterface.FromJSVal(cx, file, fileName);
     110            fileList.emplace(fileName, j);
     111        }
     112    }
     113
     114    JS::RootedObject replays(cx, JS_NewArrayObject(cx, 0));
     115    bool newReplays = false;
     116    DirectoryNames directories;
    76117    u32 i = 0;
    77     DirectoryNames directories;
    78     JS::RootedObject replays(cx, JS_NewArrayObject(cx, 0));
    79 
    80118    if (GetDirectoryEntries(GetDirectoryName(), NULL, &directories) == INFO::OK)
     119    {
    81120        for (OsPath& directory : directories)
    82121        {
    83122            if (SDL_QuitRequested())
    84123                return JSVAL_NULL;
    85124
    86             JS::RootedValue replayData(cx, LoadReplayData(scriptInterface, directory));
    87             if (!replayData.isNull())
    88                 JS_SetElement(cx, replays, i++, replayData);
     125            std::map<CStr, u32>::iterator it = fileList.find(directory.string8());
     126           
     127            // directory is not element of fileList
     128            if (it == fileList.end())
     129            {
     130                JS::RootedValue replayData(cx, LoadReplayData(scriptInterface, directory));
     131                if (!replayData.isNull())
     132                {
     133                    JS_SetElement(cx, replays, i++, replayData);
     134                    newReplays = true;
     135                }
     136            }
     137            else
     138                fileList.erase(it);
    89139        }
     140
     141        // No replay was changed, so just return the cache
     142        if (!newReplays && fileList.empty())
     143            return JS::ObjectValue(*cachedReplaysObject);
     144        // Cache found, so copy the replays from the cache that are not deleted
     145        if (cacheFound)
     146        {
     147            std::vector<u32> deleteIndices;
     148            for (const std::pair<CStr, u32>& file : fileList)
     149                deleteIndices.push_back(file.second);
     150
     151            u32 cacheLength = 0;
     152            JS_GetArrayLength(cx, cachedReplaysObject, &cacheLength);
     153
     154            for (u32 j = 0; j < cacheLength; ++j)
     155                // a not in deleteIndices, so copy it into replays
     156                if (std::find(deleteIndices.begin(), deleteIndices.end(), j) == deleteIndices.end())
     157                {
     158                    JS::RootedValue replay(cx);
     159                    JS_GetElement(cx, cachedReplaysObject, j, &replay);
     160                    JS_SetElement(cx, replays, i++, replay);
     161                }
     162        }
     163
     164        JS::RootedValue replaysRooted(cx, JS::ObjectValue(*replays));
     165        std::ofstream stream(cacheFileName.string8().c_str(), std::ofstream::out | std::ofstream::trunc);
     166        stream << scriptInterface.StringifyJSON(&replaysRooted);
     167        stream.close();
     168    }
     169
    90170    return JS::ObjectValue(*replays);
    91171}
    92172