Browse Source

HPCC-13608 Return warning message if too many files

In some environment with many logical files, the "Jbuf: out of
memory" occurs when sorting the files on ESP for "Browse Logical
Files". As a short term fix, instead of returning all files, dali
will return to client (ESP) N files and a flag which indicates
that the N files are a subset of all matches. (The N value may be
specified by a client). ESP forwards the N files (with paging) to
its client with a warning message about the subset of files.

A long term fix will be done in HPCC-13425 later.

Signed-off-by: wangkx <kevin.wang@lexisnexis.com>
wangkx 10 years ago
parent
commit
545d54ba5d

+ 4 - 2
common/workunit/workunit.cpp

@@ -2465,6 +2465,7 @@ IConstQuerySetQueryIterator* CWorkUnitFactory::getQuerySetQueriesSorted( WUQuery
             sortElements(iter, sortOrder.get(), NULL, NULL, unknownAttributes, elements);
             return conn.getClear();
         }
+        virtual bool allMatchingElementsReceived() { return true; } //For now, dali always returns all of matched Queries.
     };
     StringAttr querySet;
     StringBuffer xPath;
@@ -2517,7 +2518,7 @@ IConstQuerySetQueryIterator* CWorkUnitFactory::getQuerySetQueriesSorted( WUQuery
     }
     IArrayOf<IPropertyTree> results;
     Owned<IElementsPager> elementsPager = new CQuerySetQueriesPager(querySet.get(), xPath.str(), so.length()?so.str():NULL, postFilters, unknownAttributes, _subset);
-    Owned<IRemoteConnection> conn=getElementsPaged(elementsPager,startoffset,maxnum,NULL,"",cachehint,results,total);
+    Owned<IRemoteConnection> conn=getElementsPaged(elementsPager,startoffset,maxnum,NULL,"",cachehint,results,total,NULL);
     return new CConstQuerySetQueryIterator(results);
 }
 
@@ -2711,6 +2712,7 @@ public:
                 sortElements(iter, sortOrder.get(), nameFilterLo.get(), nameFilterHi.get(), unknownAttributes, elements);
                 return conn.getClear();
             }
+            virtual bool allMatchingElementsReceived() { return true; }//For now, dali always returns all of matched WUs.
         };
         class CScopeChecker : public CSimpleInterface, implements ISortedElementsTreeFilter
         {
@@ -2795,7 +2797,7 @@ public:
         }
         IArrayOf<IPropertyTree> results;
         Owned<IElementsPager> elementsPager = new CWorkUnitsPager(query.str(), so.length()?so.str():NULL, namefilterlo.get(), namefilterhi.get(), unknownAttributes);
-        Owned<IRemoteConnection> conn=getElementsPaged(elementsPager,startoffset,maxnum,secmgr?sc:NULL,"",cachehint,results,total);
+        Owned<IRemoteConnection> conn=getElementsPaged(elementsPager,startoffset,maxnum,secmgr?sc:NULL,"",cachehint,results,total,NULL);
         return new CConstWUArrayIterator(results);
     }
 

+ 51 - 16
dali/base/dadfs.cpp

@@ -1004,7 +1004,7 @@ public:
     IDistributedFileIterator *getIterator(const char *wildname, bool includesuper,IUserDescriptor *user);
     IDFAttributesIterator *getDFAttributesIterator(const char *wildname, IUserDescriptor *user, bool recursive, bool includesuper,INode *foreigndali,unsigned foreigndalitimeout);
     IPropertyTreeIterator *getDFAttributesTreeIterator(const char *filters, DFUQResultField* localFilters, const char *localFilterBuf,
-        IUserDescriptor *user, INode *foreigndali,unsigned foreigndalitimeout);
+        IUserDescriptor *user, bool& allMatchingFilesReceived, INode *foreigndali,unsigned foreigndalitimeout);
     IDFAttributesIterator *getForeignDFAttributesIterator(const char *wildname, IUserDescriptor *user, bool recursive=true, bool includesuper=false, const char *foreigndali="", unsigned foreigndalitimeout=FOREIGN_DALI_TIMEOUT)
     {
         Owned<INode> foreign;
@@ -1076,7 +1076,7 @@ public:
     bool getProtectedInfo(const CDfsLogicalFileName &logicalname, StringArray &names, UnsignedArray &counts);
     IDFProtectedIterator *lookupProtectedFiles(const char *owner=NULL,bool notsuper=false,bool superonly=false);
     IDFAttributesIterator* getLogicalFilesSorted(IUserDescriptor* udesc, DFUQResultField *sortOrder, const void *filterBuf, DFUQResultField *specialFilters,
-            const void *specialFilterBuf, unsigned startOffset, unsigned maxNum, __int64 *cacheHint, unsigned *total);
+            const void *specialFilterBuf, unsigned startOffset, unsigned maxNum, __int64 *cacheHint, unsigned *total, bool *allMatchingFilesReceived);
 
     void setFileProtect(CDfsLogicalFileName &dlfn,IUserDescriptor *user, const char *owner, bool set, const INode *foreigndali=NULL,unsigned foreigndalitimeout=FOREIGN_DALI_TIMEOUT);
 
@@ -8525,6 +8525,7 @@ class CIterateFileFilterContainer : public CInterface
 {
     StringAttr filterBuf; //Hold original filter string just in case
     StringAttr wildNameFilter;
+    unsigned maxFilesFilter;
     DFUQFileTypeFilter fileTypeFilter;
     CIArrayOf<CDFUSFFilter> filters;
     //The 'filters' contains the file scan filters other than wildNameFilter and fileTypeFilter. Those filters are used for
@@ -8608,7 +8609,7 @@ class CIterateFileFilterContainer : public CInterface
             return;
         if (!isdigit(*attr))
         {
-            PROGLOG("Unsupported Speical Filter: %s", attr);
+            PROGLOG("Unsupported Special Filter: %s", attr);
             return;
         }
         DFUQSpecialFilter filterName = (DFUQSpecialFilter) atoi(attr);
@@ -8621,10 +8622,16 @@ class CIterateFileFilterContainer : public CInterface
             if (isdigit(*value))
                 fileTypeFilter = (DFUQFileTypeFilter) atoi(value);
             else
-                PROGLOG("Unsupported Speical Filter: %s, value %s", attr, value);
+                PROGLOG("Unsupported Special Filter: %s, value %s", attr, value);
+            break;
+        case DFUQSFMaxFiles:
+            if (isdigit(*value))
+                maxFilesFilter = atoi(value);
+            else
+                PROGLOG("Unsupported Special Filter: %s, value %s", attr, value);
             break;
         default:
-            PROGLOG("Unsupported Speical Filter: %d", filterName);
+            PROGLOG("Unsupported Special Filter: %d", filterName);
             break;
         }
     }
@@ -8640,6 +8647,7 @@ class CIterateFileFilterContainer : public CInterface
 public:
     CIterateFileFilterContainer()
     {
+        maxFilesFilter = ITERATE_FILTEREDFILES_LIMIT;
         fileTypeFilter = DFUQFFTall;
         wildNameFilter.set("*");
         filterBuf.clear();
@@ -8716,6 +8724,7 @@ public:
     }
 
     DFUQFileTypeFilter getFileTypeFilter() { return fileTypeFilter; }
+    unsigned getMaxFilesFilter() { return maxFilesFilter; }
     void setFileTypeFilter(DFUQFileTypeFilter _fileType)
     {
         fileTypeFilter = _fileType;
@@ -8899,7 +8908,8 @@ public:
         currentScope = NULL;
         processScopes(*sroot->queryPropTree(querySdsFilesRoot()),name);
     }
-    void _getResults(bool auth, IUserDescriptor *user, CScope &scope, CFileMatchArray &matchingFiles, StringArray &authScopes, unsigned &count)
+    void _getResults(bool auth, IUserDescriptor *user, CScope &scope, CFileMatchArray &matchingFiles, StringArray &authScopes,
+        unsigned &count, bool checkFileCount)
     {
         if (auth)
         {
@@ -8911,6 +8921,10 @@ public:
         CFileMatchArray &files = scope.queryFiles();
         ForEachItemIn(f, files)
         {
+            if (checkFileCount && (count == iterateFileFilterContainer->getMaxFilesFilter()))
+                throw MakeStringException(DFSERR_PassIterateFilesLimit, "CFileScanner::_getResults() found >%d files.",
+                    iterateFileFilterContainer->getMaxFilesFilter());
+
             CFileMatch *match = &files.item(f);
             matchingFiles.append(*LINK(match));
             ++count;
@@ -8919,13 +8933,12 @@ public:
         ForEachItemIn(s, subScopes)
         {
             CScope &subScope = subScopes.item(s);
-            _getResults(auth, user, subScope, matchingFiles, authScopes, count);
+            _getResults(auth, user, subScope, matchingFiles, authScopes, count, checkFileCount);
         }
     }
-    unsigned getResults(bool auth, IUserDescriptor *user, CFileMatchArray &matchingFiles, StringArray &authScopes)
+    unsigned getResults(bool auth, IUserDescriptor *user, CFileMatchArray &matchingFiles, StringArray &authScopes, unsigned &count, bool checkFileCount)
     {
-        unsigned count = 0;
-        _getResults(auth, user, *topLevelScope, matchingFiles, authScopes, count);
+        _getResults(auth, user, *topLevelScope, matchingFiles, authScopes, count, checkFileCount);
         return count;
     }
 };
@@ -9612,7 +9625,7 @@ public:
         StringArray authScopes;
         CIArrayOf<CFileMatch> matchingFiles;
         start = msTick();
-        count = scanner.getResults(auth, udesc, matchingFiles, authScopes);
+        scanner.getResults(auth, udesc, matchingFiles, authScopes, count, false);
         tookMs = msTick()-start;
         if (tookMs>100)
             PROGLOG("TIMING(LDAP): %s: took %dms, %d lookups, file matches = %d", trc.str(), tookMs, authScopes.ordinality(), count);
@@ -9669,7 +9682,20 @@ public:
         StringArray authScopes;
         CIArrayOf<CFileMatch> matchingFiles;
         start = msTick();
-        count = scanner.getResults(auth, udesc, matchingFiles, authScopes);
+        bool returnAllMatchingFiles = true;
+        try
+        {
+            scanner.getResults(auth, udesc, matchingFiles, authScopes, count, true);
+        }
+        catch(IException *e)
+        {
+            if (DFSERR_PassIterateFilesLimit != e->errorCode())
+                throw;
+            e->Release();
+            returnAllMatchingFiles = false;
+        }
+        mb.append(returnAllMatchingFiles);
+
         tookMs = msTick()-start;
         if (tookMs>100)
             PROGLOG("TIMING(LDAP): %s: took %dms, %d lookups, file matches = %d", trc.str(), tookMs, authScopes.ordinality(), count);
@@ -11961,12 +11987,14 @@ IPropertyTreeIterator *deserializeFileAttrIterator(MemoryBuffer& mb, DFUQResultF
         IMPLEMENT_IINTERFACE;
         MemoryBuffer mb;
         unsigned numfiles;
+        bool allMatchingFilesReceived;
         StringArray nodeGroupFilter;
 
         bool first()
         {
             mb.reset();
             mb.read(numfiles);
+            mb.read(allMatchingFilesReceived);
 
             return next();
         }
@@ -12021,7 +12049,7 @@ IPropertyTreeIterator *deserializeFileAttrIterator(MemoryBuffer& mb, DFUQResultF
 }
 
 IPropertyTreeIterator *CDistributedFileDirectory::getDFAttributesTreeIterator(const char* filters, DFUQResultField* localFilters,
-    const char* localFilterBuf, IUserDescriptor* user, INode* foreigndali, unsigned foreigndalitimeout)
+    const char* localFilterBuf, IUserDescriptor* user, bool& allMatchingFilesReceived, INode* foreigndali, unsigned foreigndalitimeout)
 {
     CMessageBuffer mb;
     mb.append((int)MDFS_ITERATE_FILTEREDFILES).append(filters).append(true);
@@ -12034,6 +12062,9 @@ IPropertyTreeIterator *CDistributedFileDirectory::getDFAttributesTreeIterator(co
         queryCoven().sendRecv(mb,RANK_RANDOM,MPTAG_DFS_REQUEST);
     checkDfsReplyException(mb);
 
+    unsigned numfiles;
+    mb.read(numfiles);
+    mb.read(allMatchingFilesReceived);
     return deserializeFileAttrIterator(mb, localFilters, localFilterBuf);
 }
 
@@ -12046,7 +12077,8 @@ IDFAttributesIterator* CDistributedFileDirectory::getLogicalFilesSorted(
     unsigned startOffset,
     unsigned maxNum,
     __int64 *cacheHint,
-    unsigned *total)
+    unsigned *total,
+    bool *allMatchingFiles)
 {
     class CDFUPager : public CSimpleInterface, implements IElementsPager
     {
@@ -12056,6 +12088,7 @@ IDFAttributesIterator* CDistributedFileDirectory::getLogicalFilesSorted(
         DFUQResultField *localFilters;
         StringAttr localFilterBuf;
         StringAttr sortOrder;
+        bool allMatchingFilesReceived;
 
     public:
         IMPLEMENT_IINTERFACE_USING(CSimpleInterface);
@@ -12064,15 +12097,17 @@ IDFAttributesIterator* CDistributedFileDirectory::getLogicalFilesSorted(
             const char*_sortOrder) : udesc(_udesc), filters(_filters), localFilters(_localFilters), localFilterBuf(_localFilterBuf),
             sortOrder(_sortOrder)
         {
+            allMatchingFilesReceived = true;
         }
         virtual IRemoteConnection* getElements(IArrayOf<IPropertyTree> &elements)
         {
             Owned<IPropertyTreeIterator> fi = queryDistributedFileDirectory().getDFAttributesTreeIterator(filters.get(),
-                localFilters, localFilterBuf.get(), udesc);
+                localFilters, localFilterBuf.get(), udesc, allMatchingFilesReceived);
             StringArray unknownAttributes;
             sortElements(fi, sortOrder.get(), NULL, NULL, unknownAttributes, elements);
             return NULL;
         }
+        virtual bool allMatchingElementsReceived() { return allMatchingFilesReceived; }
     };
 
     StringBuffer so;
@@ -12095,7 +12130,7 @@ IDFAttributesIterator* CDistributedFileDirectory::getLogicalFilesSorted(
     IArrayOf<IPropertyTree> results;
     Owned<IElementsPager> elementsPager = new CDFUPager(udesc, (const char*) filters, localFilters, (const char*) localFilterBuf,
         so.length()?so.str():NULL );
-    getElementsPaged(elementsPager,startOffset,maxNum,NULL,"",cacheHint,results,total,false);
+    Owned<IRemoteConnection> conn = getElementsPaged(elementsPager,startOffset,maxNum,NULL,"",cacheHint,results,total,allMatchingFiles,false);
     return new CDFAttributeIterator(results);
 }
 #ifdef _USE_CPPUNIT

+ 7 - 5
dali/base/dadfs.hpp

@@ -48,7 +48,7 @@ interface IUserDescriptor;
 #define S_LINK_RELATIONSHIP_KIND "link"
 #define S_VIEW_RELATIONSHIP_KIND "view"
 
-
+#define ITERATE_FILTEREDFILES_LIMIT 100000
 
 interface IDistributedSuperFile;
 interface IDistributedFile;
@@ -192,7 +192,8 @@ enum DFUQSerializeFileAttrOption
 enum DFUQSpecialFilter
 {
     DFUQSFFileNameWithPrefix = 1,
-    DFUQSFFileType = 2
+    DFUQSFFileType = 2,
+    DFUQSFMaxFiles = 3
 };
 
 enum DFUQFileTypeFilter
@@ -560,7 +561,7 @@ interface IDistributedFileDirectory: extends IInterface
             // wildname is in form scope/name and may contain wild components for either
     virtual IDFAttributesIterator *getDFAttributesIterator(const char *wildname, IUserDescriptor *user, bool recursive=true, bool includesuper=false, INode *foreigndali=NULL, unsigned foreigndalitimeout=FOREIGN_DALI_TIMEOUT) = 0;
     virtual IPropertyTreeIterator *getDFAttributesTreeIterator(const char *filters, DFUQResultField* localFilters,
-        const char *localFilterBuf, IUserDescriptor *user, INode *foreigndali=NULL, unsigned foreigndalitimeout=FOREIGN_DALI_TIMEOUT) = 0;
+        const char *localFilterBuf, IUserDescriptor *user, bool& allMatchingFilesReceived, INode *foreigndali=NULL, unsigned foreigndalitimeout=FOREIGN_DALI_TIMEOUT) = 0;
     virtual IDFAttributesIterator *getForeignDFAttributesIterator(const char *wildname, IUserDescriptor *user, bool recursive=true, bool includesuper=false, const char *foreigndali="", unsigned foreigndalitimeout=FOREIGN_DALI_TIMEOUT) = 0;
 
     virtual IDFScopeIterator *getScopeIterator(IUserDescriptor *user, const char *subscope=NULL,bool recursive=true,bool includeempty=false)=0;
@@ -665,7 +666,7 @@ interface IDistributedFileDirectory: extends IInterface
 
     virtual IDFProtectedIterator *lookupProtectedFiles(const char *owner=NULL,bool notsuper=false,bool superonly=false)=0; // if owner = NULL then all
     virtual IDFAttributesIterator* getLogicalFilesSorted(IUserDescriptor* udesc, DFUQResultField *sortOrder, const void* filters, DFUQResultField *localFilters,
-            const void *specialFilterBuf, unsigned startOffset, unsigned maxNum, __int64 *cacheHint, unsigned *total) = 0;
+            const void *specialFilterBuf, unsigned startOffset, unsigned maxNum, __int64 *cacheHint, unsigned *total, bool *allMatchingFilesReceived) = 0;
 
     virtual unsigned setDefaultTimeout(unsigned timems) = 0;                                // sets default timeout for SDS connections and locking
                                                                                             // returns previous value
@@ -733,7 +734,8 @@ enum DistributedFileSystemError
     DFSERR_ClusterNotFound,
     DFSERR_ClusterAlreadyExists,
     DFSERR_LookupConnectionTimout,       // only raised if timeout specified on lookup etc.
-    DFSERR_FailedToDeleteFile
+    DFSERR_FailedToDeleteFile,
+    DFSERR_PassIterateFilesLimit
 };
 
 

+ 3 - 0
dali/base/dautils.cpp

@@ -1965,6 +1965,7 @@ IRemoteConnection *getElementsPaged( IElementsPager *elementsPager,
                                      __int64 *hint,
                                      IArrayOf<IPropertyTree> &results,
                                      unsigned *total,
+                                     bool *allMatchingElementsReceived,
                                      bool checkConn)
 {
     if ((pagesize==0) || !elementsPager)
@@ -2038,6 +2039,8 @@ IRemoteConnection *getElementsPaged( IElementsPager *elementsPager,
             results.append(item);
         }
     }
+    if (allMatchingElementsReceived)
+        *allMatchingElementsReceived = elementsPager->allMatchingElementsReceived();
     IRemoteConnection *ret = NULL;
     if (elem->conn)
         ret = elem->conn.getLink();

+ 2 - 0
dali/base/dautils.hpp

@@ -271,6 +271,7 @@ interface ISortedElementsTreeFilter : extends IInterface
 interface IElementsPager : extends IInterface
 {
     virtual IRemoteConnection *getElements(IArrayOf<IPropertyTree> &elements) = 0;
+    virtual bool allMatchingElementsReceived() = 0;
 };
 extern da_decl void sortElements( IPropertyTreeIterator* elementsIter,
                                      const char *sortorder, 
@@ -287,6 +288,7 @@ extern da_decl IRemoteConnection *getElementsPaged(IElementsPager *elementsPager
                                      __int64 *hint,                         // if non null points to in/out cache hint
                                      IArrayOf<IPropertyTree> &results,
                                      unsigned *total,
+                                     bool *allMatchingElementsReceived,
                                      bool checkConn = true); // total possible filtered matches, i.e. irrespective of startoffset and pagesize
 
 extern da_decl void clearPagedElementsCache();

+ 2 - 1
dali/dfu/dfuwu.cpp

@@ -3041,6 +3041,7 @@ public:
                 sortElements(iter, sortOrder.get(), nameFilterLo.get(), nameFilterHi.get(), unknownAttributes, elements);
                 return conn.getClear();
             }
+            virtual bool allMatchingElementsReceived() { return true; }//For now, dali always returns all of matched WUs.
         };
 
         StringBuffer query;
@@ -3095,7 +3096,7 @@ public:
         }
         IArrayOf<IPropertyTree> results;
         Owned<IElementsPager> elementsPager = new CDFUWorkUnitsPager(query.str(), so.length()?so.str():NULL, namefilterlo.get(), namefilterhi.get(), unknownAttributes);
-        Owned<IRemoteConnection> conn=getElementsPaged(elementsPager,startoffset,maxnum,NULL,queryowner,cachehint,results,total);
+        Owned<IRemoteConnection> conn=getElementsPaged(elementsPager,startoffset,maxnum,NULL,queryowner,cachehint,results,total, NULL);
         return new CConstDFUWUArrayIterator(this,conn,results);
     }
 

+ 3 - 0
esp/scm/ws_dfu.ecm

@@ -172,6 +172,7 @@ ESPrequest [nil_remove] DFUQueryRequest
 
     bool OneLevelDirFileReturn(false);
     [min_ver("1.24")] int64 CacheHint;
+    [min_ver("1.30")] int MaxNumberOfFiles;
     [min_ver("1.30")] bool IncludeSuperOwner;
 };
 
@@ -211,6 +212,8 @@ DFUQueryResponse
     string ParametersForPaging;
     string Filters;
     [min_ver("1.24")] int64 CacheHint;
+    [min_ver("1.30")] bool IsSubsetOfFiles;
+    [min_ver("1.30")] string Warning;
 };
 
 ESPrequest 

+ 24 - 3
esp/services/ws_dfu/ws_dfuService.cpp

@@ -3118,6 +3118,12 @@ void CWsDfuEx::setFileNameFilter(const char* fname, const char* prefix, StringBu
     filterBuf.append(DFUQFTspecial).append(DFUQFilterSeparator).append(DFUQSFFileNameWithPrefix).append(DFUQFilterSeparator).append(fileNameFilter.str()).append(DFUQFilterSeparator);
 }
 
+void CWsDfuEx::setFileIterateFilter(unsigned maxFiles, StringBuffer &filterBuf)
+{
+    filterBuf.append(DFUQFTspecial).append(DFUQFilterSeparator).append(DFUQSFMaxFiles).append(DFUQFilterSeparator)
+        .append(maxFiles).append(DFUQFilterSeparator);
+}
+
 void CWsDfuEx::setDFUQueryFilters(IEspDFUQueryRequest& req, StringBuffer& filterBuf)
 {
     setFileNameFilter(req.getLogicalName(), req.getPrefix(), filterBuf);
@@ -3485,13 +3491,22 @@ bool CWsDfuEx::doLogicalFileSearch(IEspContext &context, IUserDescriptor* udesc,
         pageSize = firstN;
     }
 
+    unsigned maxFiles = 0;
+    if(!req.getMaxNumberOfFiles_isNull())
+        maxFiles = req.getMaxNumberOfFiles();
+    if (maxFiles == 0)
+        maxFiles = ITERATE_FILTEREDFILES_LIMIT;
+    if (maxFiles != ITERATE_FILTEREDFILES_LIMIT)
+        setFileIterateFilter(maxFiles, filterBuf);
+
     __int64 cacheHint = 0;
     if (!req.getCacheHint_isNull())
         cacheHint = req.getCacheHint();
 
+    bool allMatchingFilesReceived = true;
     unsigned totalFiles = 0;
     Owned<IDFAttributesIterator> it = queryDistributedFileDirectory().getLogicalFilesSorted(udesc, sortOrder, filterBuf.str(),
-        localFilters, localFilterBuf.bufferBase(), pageStart, pageSize, &cacheHint, &totalFiles);
+        localFilters, localFilterBuf.bufferBase(), pageStart, pageSize, &cacheHint, &totalFiles, &allMatchingFilesReceived);
     if(!it)
         throw MakeStringException(ECLWATCH_CANNOT_GET_FILE_ITERATOR,"Cannot get information from file system.");
 
@@ -3499,8 +3514,14 @@ bool CWsDfuEx::doLogicalFileSearch(IEspContext &context, IUserDescriptor* udesc,
     ForEach(*it)
         addToLogicalFileList(it->query(), NULL, version, logicalFiles);
 
-    if (version >= 1.24)
-        resp.setCacheHint(cacheHint);
+    if (!allMatchingFilesReceived)
+    {
+        VStringBuffer warning("The returned results (%d files) represent a subset of the total number of matches. Using a correct filter may reduce the number of matches.",
+            maxFiles);
+        resp.setWarning(warning.str());
+        resp.setIsSubsetOfFiles(!allMatchingFilesReceived);
+    }
+    resp.setCacheHint(cacheHint);
     resp.setDFULogicalFiles(logicalFiles);
     setDFUQueryResponse(context, totalFiles, sortBy, descending, pageStart, pageSize, req, resp); //This call may be removed after 5.0
 

+ 1 - 0
esp/services/ws_dfu/ws_dfuService.hpp

@@ -78,6 +78,7 @@ private:
     bool addDFUQueryFilter(DFUQResultField *filters, unsigned short &count, MemoryBuffer &buff, const char* value, DFUQResultField name);
     void appendDFUQueryFilter(const char *name, DFUQFilterType type, const char *value, StringBuffer& filterBuf);
     void appendDFUQueryFilter(const char *name, DFUQFilterType type, const char *value, const char *valueHigh, StringBuffer& filterBuf);
+    void setFileIterateFilter(unsigned maxFiles, StringBuffer &filterBuf);
     void setFileTypeFilter(const char* fileType, StringBuffer& filterBuf);
     void setFileNameFilter(const char* fname, const char* prefix, StringBuffer &buff);
     void setDFUQueryFilters(IEspDFUQueryRequest& req, StringBuffer& filterBuf);