<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Live a simple life

    沉默(zhu_xing@live.cn)
    隨筆 - 48, 文章 - 0, 評論 - 132, 引用 - 0
    數(shù)據(jù)加載中……

    【Eclipse插件開發(fā)】資源不同步問題分析

            資源不同步的問題對于插件開發(fā)的哥們應(yīng)該都不是很陌生,記得剛到兩年前剛接觸插件開發(fā)的時候,由于產(chǎn)品中代碼中很多都是用java.io.File操作文件資源,導(dǎo)致經(jīng)常有這種問題發(fā)生,例如刪除不掉、內(nèi)容更新失敗等。下班之前,以資源刪除失敗為例子,寫篇小隨筆,把這個資源不同步的問題多少說道說道。^_^

            首先看個可能不陌生的錯誤(錯誤本質(zhì)上都是不同步引起,但是可能包裝形式很多):
            
            
        下面是引起錯誤的代碼:

     1 public void run(IAction action) {
     2         try {
     3             //獲取一個存在的文件
     4             IFile eclipseFile = ResourcesPlugin.getWorkspace().getRoot().getProject("project").getFile(new Path("folder/file.txt"));
     5             
     6             //用java IO更新底層資源
     7             eclipseFile.getLocation().toFile().setLastModified(eclipseFile.getLocalTimeStamp() + 100);
     8             
     9             //刪除文件
    10             eclipseFile.delete(falsenull);
    11         } catch (CoreException e) {
    12             Activator.getDefault().getLog().log(new Status(IStatus.ERROR, "aaa"99"刪除資源失敗", e));
    13         }
    14     }

            
            【猜測】是不是我們用Java IO修改了文件,而Eclipse工作區(qū)不知道,這可能就是不同步?

            【兩種狀態(tài):ResourceInfo VS IFileInfo】
               一個文件資源的狀態(tài)描述,我們可以從兩個層面來看:一個Eclipse工作區(qū)層面的資源狀態(tài);二是文件系統(tǒng)層面的資源狀態(tài)。對于這兩者,Eclipse資源管理模塊中都有對應(yīng)的類型支持。

            ResourceInfo :封裝了工作區(qū)對一個文件資源的描述,也就是我們常說的工作區(qū)資源樹上的一個數(shù)據(jù)節(jié)點,Eclipse資源管理中的IResource系列接口本身也是ResourceInfo的代理,ResourceInfo主要操作如下:
                    
                    
                    

                    ResourceInfo的主要常規(guī)獲取方式,Workspace.getResourceInfo:

     1 public ResourceInfo getResourceInfo(IPath path, boolean phantom, boolean mutable) {
     2         try {
     3             if (path.segmentCount() == 0) {
     4                 ResourceInfo info = (ResourceInfo) tree.getTreeData();
     5                 Assert.isNotNull(info, "Tree root info must never be null"); //$NON-NLS-1$
     6                 return info;
     7             }
     8             ResourceInfo result = null;
     9             if (!tree.includes(path))
    10                 return null;
    11             if (mutable)
    12                 result = (ResourceInfo) tree.openElementData(path);
    13             else
    14                 result = (ResourceInfo) tree.getElementData(path);
    15             if (result != null && (!phantom && result.isSet(M_PHANTOM)))
    16                 return null;
    17             return result;
    18         } catch (IllegalArgumentException e) {
    19             return null;
    20         }
    21     }

                資源樹的影子出來了,我們獲取resource info的過程其實就是在資源樹上面定位對應(yīng)數(shù)據(jù)節(jié)點的過程。那可以自然的猜測(有興趣的Tx可以接著撒兩眼資源樹是如何實現(xiàn)的),ResourceInfo的獲取過程并不是每次都會產(chǎn)生一個新的ResourceInfo實例,因為直覺告訴我們這可能是性能敏感的。
                    
            IFileInfo:一個資源在特定時間點上的狀態(tài)快照(snapshot),可以理解為一個底層文件系統(tǒng)資源對應(yīng)的靜態(tài)只讀信息的集合。我們看一下它的獲取方式,IFileStore.fetchInfo()實現(xiàn)(有關(guān)IFleStore這里就省略了^_^):

     1 public IFileInfo fetchInfo(int options, IProgressMonitor monitor) {
     2         if (LocalFileNatives.usingNatives()) {
     3             FileInfo info = LocalFileNatives.fetchFileInfo(filePath);
     4             //natives don't set the file name on all platforms
     5             if (info.getName().length() == 0)
     6                 info.setName(file.getName());
     7             return info;
     8         }
     9         //in-lined non-native implementation
    10         FileInfo info = new FileInfo(file.getName());
    11         final long lastModified = file.lastModified();
    12         if (lastModified <= 0) {
    13             //if the file doesn't exist, all other attributes should be default values
    14             info.setExists(false);
    15             return info;
    16         }
    17         info.setLastModified(lastModified);
    18         info.setExists(true);
    19         info.setLength(file.length());
    20         info.setDirectory(file.isDirectory());
    21         info.setAttribute(EFS.ATTRIBUTE_READ_ONLY, file.exists() && !file.canWrite());
    22         info.setAttribute(EFS.ATTRIBUTE_HIDDEN, file.isHidden());
    23         return info;
    24     }

            可以看出來,每次獲取IFileInfo的過程是每次都產(chǎn)生新的實例,這個新的實例來描述該時間點上的文件狀態(tài)。        
            
            到這里我們知道了,ResourceInfo其實是內(nèi)存中Eclipse維護的一個東東,IFileInfo是實時獲取的,那么在特定的時間點上面,前者有可能和后者不統(tǒng)一。這是不是就是不同步問題的根源呢?

            【資源不同步檢查】
            為了驗證上面的猜測,我們追蹤調(diào)試一下文章開頭提到的測試代碼:
            
            
            找到了檢查文件資源是否同步的代碼,FileSystemResourceManager.isSynchronized(IResource target, int depth),資源樹在檢查一個資源是否同步時候(IResourceTree.isisSynchronized(IResource target, int depth)),也是委托給了FileSystemResourceManager: 

     1 public boolean isSynchronized(IResource target, int depth) {
     2         switch (target.getType()) {
     3             case IResource.ROOT :
     4                 if (depth == IResource.DEPTH_ZERO)
     5                     return true;
     6                 //check sync on child projects.
     7                 depth = depth == IResource.DEPTH_ONE ? IResource.DEPTH_ZERO : depth;
     8                 IProject[] projects = ((IWorkspaceRoot) target).getProjects();
     9                 for (int i = 0; i < projects.length; i++) {
    10                     if (!isSynchronized(projects[i], depth))
    11                         return false;
    12                 }
    13                 return true;
    14             case IResource.PROJECT :
    15                 if (!target.isAccessible())
    16                     return true;
    17                 break;
    18             case IResource.FILE :
    19                 if (fastIsSynchronized((File) target))
    20                     return true;
    21                 break;
    22         }
    23         IsSynchronizedVisitor visitor = new IsSynchronizedVisitor(Policy.monitorFor(null));
    24         UnifiedTree tree = new UnifiedTree(target);
    25         try {
    26             tree.accept(visitor, depth);
    27         } catch (CoreException e) {
    28             Policy.log(e);
    29             return false;
    30         } catch (IsSynchronizedVisitor.ResourceChangedException e) {
    31             //visitor throws an exception if out of sync
    32             return false;
    33         }
    34         return true;
    35     }

            
                我們接著看一下上面負責(zé)File級別同步檢查的FileSystemResourceManager.fastIsSynchronized方法:

    1 public boolean fastIsSynchronized(File target) {
    2         ResourceInfo info = target.getResourceInfo(falsefalse);
    3         if (target.exists(target.getFlags(info), true)) {
    4             IFileInfo fileInfo = getStore(target).fetchInfo();
    5             if (!fileInfo.isDirectory() && info.getLocalSyncInfo() == fileInfo.getLastModified())
    6                 return true;
    7         }
    8         return false;
    9     }
            上面的紅線部分告訴我們:對于一個文件級別的資源,判斷是否同步就是檢查Eclipse維護的時間戳和底層文件系統(tǒng)的時間戳是否一致?。?!

            如果用Eclipse IResource API來修改文件資源,Eclipse自己會知道;如果用java IO或者java NIO來修改文件資源,Eclipse就一無所知,狀態(tài)維護就會出問題。不知道就出事情了,不同步只是后果之一,變化跟蹤也將失效,resource change event也將無從產(chǎn)生了^_^

            【后記】
           1、對于非File級別的資源,為什么同步檢查不是很嚴格呢?
               因為在不同操作系統(tǒng)不同類型分區(qū)上面,一個文件夾下面的文件資源被修改了,文件夾的時間戳并不保證會及時更新。這是很底層的東西了,就不接著講了。  如果你想修正這個問題,你可以對目錄時間戳做自己的維護(這是可行的,我們產(chǎn)品里面就是這么干的)。

                2、ResourceInfo和IFileInfo好像不怎么使用?
                確實,Ecipse也不想讓開發(fā)者去直接使用它。例如:getResourceInfo是在Resource中提供的,而不是在IResource接口中定義的。

               3、那如何同步呢?
                    IResource.refreshLocal(int depth, IProgressMonitor monitor)     


    本博客中的所有文章、隨筆除了標題中含有引用或者轉(zhuǎn)載字樣的,其他均為原創(chuàng)。轉(zhuǎn)載請注明出處,謝謝!

    posted on 2008-09-02 17:56 zhuxing 閱讀(2851) 評論(2)  編輯  收藏 所屬分類: Eclipse Plug-in & OSGI

    評論

    # re: 【Eclipse插件開發(fā)】資源不同步問題分析  回復(fù)  更多評論   

    2008-09-02 20:18 | 試客網(wǎng)

    # re: 【Eclipse插件開發(fā)】資源不同步問題分析[未登錄]  回復(fù)  更多評論   

    "如果用Eclipse IResource API來修改文件資源,Eclipse自己會知道;如果用java IO或者java NIO來修改文件資源,Eclipse就一無所知,狀態(tài)維護就會出問題。" 用java IO修改后再調(diào)用刷新接口,應(yīng)該可以解決
    2014-03-11 15:21 | simon
    主站蜘蛛池模板: 8x成人永久免费视频| 在线看片免费人成视频福利| 成人免费一级毛片在线播放视频| 亚洲人成无码网站| 国产免费黄色无码视频| 亚洲欧洲久久久精品| eeuss影院www天堂免费| 国产亚洲情侣一区二区无| 99久久免费精品视频| 国产小视频免费观看| 亚洲国产精品成人精品无码区在线| 国产精品偷伦视频免费观看了| 亚洲VA综合VA国产产VA中| 一区二区在线视频免费观看| 国产亚洲成归v人片在线观看| 巨胸喷奶水www永久免费 | 国产乱子伦精品免费无码专区| 亚洲女子高潮不断爆白浆| 国产免费av一区二区三区| 一级全免费视频播放| 国产成人亚洲综合无码精品 | 18禁免费无码无遮挡不卡网站| 亚洲免费在线视频观看| 成人免费无码视频在线网站| 国产精品久久久亚洲| 最近免费中文字幕mv在线电影| 国产精品亚洲午夜一区二区三区 | MM131亚洲国产美女久久| 亚洲色欲啪啪久久WWW综合网| 国产免费网站看v片在线| 亚洲人成电影福利在线播放| 一级特黄录像视频免费| 久久亚洲国产中v天仙www| 亚洲精品免费在线视频| 色婷婷亚洲一区二区三区| 成人A级毛片免费观看AV网站| 立即播放免费毛片一级| 亚洲AV无码一区二区三区系列| 野花高清在线观看免费3中文 | 成人毛片18岁女人毛片免费看| 亚洲国产精品白丝在线观看|