diff --git a/src/main/java/org/filesys/server/filesys/FileInfo.java b/src/main/java/org/filesys/server/filesys/FileInfo.java index 44a6742..86f592d 100644 --- a/src/main/java/org/filesys/server/filesys/FileInfo.java +++ b/src/main/java/org/filesys/server/filesys/FileInfo.java @@ -639,6 +639,7 @@ public final FileType isFileType() { */ public final void resetInfo() { m_name = ""; + m_shortName = null; m_path = null; m_size = 0L; @@ -666,6 +667,7 @@ public final void resetInfo() { */ public final void copyFrom(FileInfo finfo) { m_name = finfo.getFileName(); + m_shortName = finfo.getShortName(); m_path = finfo.getPath(); m_size = finfo.getSize(); diff --git a/src/main/java/org/filesys/smb/server/disk/JavaNIOSearchContext.java b/src/main/java/org/filesys/smb/server/disk/JavaNIOSearchContext.java index 7b0bcd0..8c44c61 100644 --- a/src/main/java/org/filesys/smb/server/disk/JavaNIOSearchContext.java +++ b/src/main/java/org/filesys/smb/server/disk/JavaNIOSearchContext.java @@ -46,6 +46,10 @@ public class JavaNIOSearchContext extends SearchContext { private Iterator m_pathIter; private int m_idx; + // Help speed up a common restartAt(FileInfo info) call pattern + private FileInfo m_cachedFileInfo; + private boolean m_restartFromCache; + // File attributes private int m_attr; @@ -74,6 +78,11 @@ public int getResumeId() { return m_idx; } + private void resetIndex() { + m_idx = 0; + m_cachedFileInfo = null; + } + /** * Determine if there are more files to return for this search * @@ -87,7 +96,7 @@ public boolean hasMoreFiles() { else if (m_stream == null || m_pathIter == null) return false; else if ( m_pathIter != null) - return m_pathIter.hasNext(); + return m_pathIter.hasNext() || m_restartFromCache && m_cachedFileInfo != null; return true; } @@ -104,7 +113,7 @@ public final void initSinglePathSearch( Path singlePath) { // Indicate this is a single file/folder search setSingleFileSearch( true); - m_idx = 0; + resetIndex(); m_stream = null; m_pathIter = null; @@ -131,7 +140,7 @@ public final void initWildcardSearch( Path folderPath, int attr, WildCard wildCa // Indicate a multi-file search setSingleFileSearch( false); - m_idx = 0; + resetIndex(); // Start the folder search m_stream = Files.newDirectoryStream(m_root); @@ -223,6 +232,11 @@ public boolean nextFileInfo(FileInfo info) { infoValid = true; } } + else if (m_restartFromCache == true && m_cachedFileInfo != null) { + m_restartFromCache = false; + info.copyFrom(m_cachedFileInfo); + infoValid = true; + } else if (m_pathIter != null && m_pathIter.hasNext()) { // Find the next file/folder that matches the search attributes @@ -329,11 +343,14 @@ else if (fname.equalsIgnoreCase("Desktop.ini") || // Indicate that the file information is valid infoValid = true; + + m_cachedFileInfo = info; } } } catch ( IOException ex) { infoValid = false; + m_cachedFileInfo = null; } // Return the file information valid state @@ -355,6 +372,10 @@ public String nextFileName() { else return null; } + else if (m_restartFromCache == true && m_cachedFileInfo != null) { + m_restartFromCache = false; + return m_cachedFileInfo.getFileName(); + } else if ( m_pathIter != null && m_pathIter.hasNext()) { // Find the next matching file name @@ -390,6 +411,7 @@ public boolean restartAt(int resumeId) { // Restart the iteration and skip to the required position try { + m_stream.close(); m_stream = Files.newDirectoryStream(m_root); m_pathIter = m_stream.iterator(); } @@ -397,7 +419,7 @@ public boolean restartAt(int resumeId) { return false; } - m_idx = 0; + resetIndex(); while ( m_pathIter.hasNext() && m_idx != resumeId) { m_pathIter.next(); @@ -420,11 +442,18 @@ public boolean restartAt(FileInfo info) { boolean restartOK = false; if (m_stream != null) { + if (m_cachedFileInfo != null && m_cachedFileInfo == info) { + // Avoid expensively reiterating the whole directory if we're asked to merely go + // back to the immediately previously retrieved entry. + m_restartFromCache = true; + return true; + } // Restart the stream iterator and find the required restart path - m_idx = 0; + resetIndex(); try { + m_stream.close(); m_stream = Files.newDirectoryStream(m_root); m_pathIter = m_stream.iterator(); } @@ -438,7 +467,8 @@ public boolean restartAt(FileInfo info) { while ( curPath != null && restartOK == false) { if ( curPath.getFileName().toString().equalsIgnoreCase(info.getFileName())) { - restartOK = true; + // Rewind by one, so the next call to nextFileInfo will return the correct item + restartOK = restartAt(m_idx - 1); } else { curPath = m_pathIter.next(); @@ -485,4 +515,19 @@ public final void setRelativePath(String relPath) { if (m_relPath != null && m_relPath.endsWith(FileName.DOS_SEPERATOR_STR) == false) m_relPath = m_relPath + FileName.DOS_SEPERATOR_STR; } + + /** + * Close the search. + */ + public void closeSearch() { + if (m_stream != null) { + try { + m_stream.close(); + } + catch (IOException unused) { + } + } + super.closeSearch(); + } + }