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

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

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

    LetsCoding.cn

    天地之間有桿秤,拿秤砣砸老百姓。

    Lucene源碼分析筆記之[org.apache.lucene.store](一)

     Lock/LockFactory類系

    綜述:Lucene 的機制來實現同一文件夾的互斥訪問:當有進程訪問需要互斥訪問的文件夾時,首先查看與之關聯的是否存在,若存在則拒絕訪問;若不存在,則先上,訪問之,最后解。不同的Lock子類,具體的實現方式并不一樣。

    1.Lock/LockFactory類系的層次圖



    2.
    部分代碼說明

    Lock

    Lock本身是一個抽象類,它提供了4個方法,但它僅實現了obtain(long)這一個方法,其他三個留給了它的子類去完成。4個方法的聲明羅列如下:

    public abstract Boolean obtain() throws IOException;
    public boolean obtain(long lockWaitTimeout) throws LockObtainFailedException;;
    public abstract void release() throws IOException;
    public abstract Boolean isLocked();

     

    Lock還提供了兩個靜態變量:long LOCK_POLL_INTERVAL(默認值為1000ms)和final long LOCK_OBTAIN_WAIT_FOREVER(值為-1) ,前者為試圖獲取時的時間間隔值,后者為當lockWaitTimeout設置為該值時,obtain(long)將會無限期試圖獲取。

    obtain(long)的功能為在給定的lockWaitTimeout時間內試圖獲取,一旦獲取到,則返回;超過時間則會拋出異常。其代碼及注釋如下:

     1    public boolean obtain(long lockWaitTimeout)
     2            throws LockObtainFailedException, IOException {
     3        failureReason = null;
     4        // locked試圖獲取“鎖文件”。obtain()的功能是及時返回是否能取得“鎖文件”
     5        boolean locked = obtain();
     6        // 給定參數值為負并且不等于-1,則拋出參數值設置異常
     7        if (lockWaitTimeout < 0 && lockWaitTimeout != LOCK_OBTAIN_WAIT_FOREVER)
     8            throw new IllegalArgumentException(
     9                    "lockWaitTimeout should be LOCK_OBTAIN_WAIT_FOREVER or a non-negative number (got "
    10                            + lockWaitTimeout + ")");
    11        // 設置最大睡眠次數
    12        long maxSleepCount = lockWaitTimeout / LOCK_POLL_INTERVAL;
    13        long sleepCount = 0;    // 睡眠次數累加器
    14        // 循環直到取得“鎖文件”;或者時間到,則拋出異常
    15        while (!locked) {
    16            if (lockWaitTimeout != LOCK_OBTAIN_WAIT_FOREVER
    17                    && sleepCount++ >= maxSleepCount) {        // 參數lockWaitTimeout不為-1且累計睡眠次數大于maxSleepCount,拋出異常
    18                String reason = "Lock obtain timed out: " + this.toString();
    19                if (failureReason != null{
    20                    reason += "" + failureReason;
    21                }

    22                LockObtainFailedException e = new LockObtainFailedException(
    23                        reason);
    24                if (failureReason != null{
    25                    e.initCause(failureReason);
    26                }

    27                throw e;
    28            }

    29            try {
    30                // 睡眠LOCK_POLL_INTERVAL(默認1000ms)時間
    31                Thread.sleep(LOCK_POLL_INTERVAL);
    32            }
     catch (InterruptedException e) {
    33                throw new IOException(e.toString());
    34            }

    35            // 再次試圖獲取“鎖文件”
    36            locked = obtain();
    37        }

    38        // 正常退出,
    39        return locked;
    40    }

     

    SimpleFSLock

    SimpleFSLock類中,是通過給需要訪問的文件夾另外建立一個文件的方式來實現的;查看某文件夾是否被上鎖,你需要做的僅僅是查看下與其相關的鎖文件是否存在;解鎖時只需刪除鎖文件就萬事OK了。下面是obtain()方法的代碼及注釋:

     1    public boolean obtain() throws IOException {
     2
     3        // Ensure that lockDir exists and is a directory:
     4        // 確保lockDir存在并且是文件夾類型
     5        if (!lockDir.exists()) {
     6            if (!lockDir.mkdirs())    // 如果lockDir不存在,則試圖為其建立新文件夾,建立失敗則拋出異常
     7                throw new IOException("Cannot create directory: "
     8                        + lockDir.getAbsolutePath());
     9        }
     else if (!lockDir.isDirectory()) {
    10            // 如果lockDir存在,但不是文件夾,拋出異常
    11            throw new IOException(
    12                    "Found regular file where directory expected: "
    13                            + lockDir.getAbsolutePath());
    14        }

    15        // createNewFile成功,返回true; 失敗,false;
    16        // 說明:建立成功,也就是說“鎖文件”不存在; 失敗,說明“鎖文件”已經存在,也就是說該文件夾已被上鎖
    17        return lockFile.createNewFile();
    18    }

    NativeFSLock

    NativeFSLockSimpleFSLock有些不同,它的用的是鎖文件的鎖,說起來很是繞口,其實它只是給鎖文件上一把鎖:在查看某文件夾是否能被訪問時,首先檢查與此文件夾關聯的鎖文件的鎖是否被占用,而不像SimpleFSLock僅僅查看與之相連的鎖文件是否存在。正因為如此,它解決了如果JVM異常退出時遺留的鎖文件的問題:在SimpleFSLock中,只要鎖文件存在,就被人為該文件夾被鎖,而不能被任何其他進程訪問。

    NativeFSLock額外定義了一個私有靜態變量:private static HashSet LOCK_HELD。它用來記錄鎖文件的標準路徑名(canonical path),當某文件夾的鎖文件標準路徑名存在于LOCK_HELD中,且沒有被上鎖,就說明該文件夾可被訪問;否則拒絕訪問。在解鎖時,需要從LOCK_HELD中刪除鎖文件的標準路徑名,刪除鎖文件。

    NativeFSLock的代碼中包含了很多對于異常的處理,使得程序看起來很是費解。

    obtain()的主要代碼及注釋如下:

      1    public synchronized boolean obtain() throws IOException {    // 該方法被設置為同步訪問
      2        //    isLocked()為true說明“鎖文件”已被上鎖,正在被使用中
      3        if (isLocked()) {
      4            // Our instance is already locked:
      5            return false;
      6        }

      7
      8        // Ensure that lockDir exists and is a directory.
      9        if (!lockDir.exists()) {
     10            if (!lockDir.mkdirs())
     11                throw new IOException("Cannot create directory: "
     12                        + lockDir.getAbsolutePath());
     13        }
     else if (!lockDir.isDirectory()) {
     14            throw new IOException(
     15                    "Found regular file where directory expected: "
     16                            + lockDir.getAbsolutePath());
     17        }

     18
     19        String canonicalPath = path.getCanonicalPath();
     20
     21        boolean markedHeld = false;    //標記在LOCK_HELD中是否存在某“鎖文件”的路徑名
     22
     23        try {
     24
     25            // Make sure nobody else in-process has this lock held
     26            // already, and, mark it held if not:
     27
     28            synchronized (LOCK_HELD) {    // 設置LOCK_HELD的同步訪問
     29                if (LOCK_HELD.contains(canonicalPath)) {    // 如果標準路徑存在于LOCK_HELD中,說明該文件被上鎖或正在被上鎖,返回false
     30                    // Someone else in this JVM already has the lock:
     31                    return false;
     32                }
     else {
     33                    // This "reserves" the fact that we are the one
     34                    // thread trying to obtain this lock, so we own
     35                    // the only instance of a channel against this
     36                    // file:
     37                    LOCK_HELD.add(canonicalPath);    // 添加路徑名到LOCK_HELD中
     38                    markedHeld = true;    // 設置為true
     39                }

     40            }

     41
     42            try {
     43                //  建立“鎖文件”
     44                f = new RandomAccessFile(path, "rw");
     45            }
     catch (IOException e) {
     46                // On Windows, we can get intermittant "Access
     47                // Denied" here.  So, we treat this as failure to
     48                // acquire the lock, but, store the reason in case
     49                // there is in fact a real error case.
     50                failureReason = e;
     51                f = null;    // 建立失敗,則f= null
     52            }

     53
     54            if (f != null{
     55                try {
     56                    // 獲取“鎖文件”的通道
     57                    channel = f.getChannel();
     58                    try {
     59                        // 給“鎖文件”上鎖
     60                        lock = channel.tryLock();
     61                    }
     catch (IOException e) {
     62                        // At least on OS X, we will sometimes get an
     63                        // intermittant "Permission Denied" IOException,
     64                        // which seems to simply mean "you failed to get
     65                        // the lock".  But other IOExceptions could be
     66                        // "permanent" (eg, locking is not supported via
     67                        // the filesystem).  So, we record the failure
     68                        // reason here; the timeout obtain (usually the
     69                        // one calling us) will use this as "root cause"
     70                        // if it fails to get the lock.
     71                        failureReason = e;
     72                    }
     finally {        
     73                        if (lock == null{    // 如果沒有取得鎖,需關閉通道并設置其為null
     74                            try {
     75                                channel.close();    //關閉通道
     76                            }
     finally {
     77                                channel = null;    //設置為null
     78                            }

     79                        }

     80                    }

     81                }
     finally {
     82                    if (channel == null{ // 如果通道獲取失敗或者上鎖異常,關閉“鎖文件”
     83                        try {
     84                            f.close();    // 關閉“鎖文件”
     85                        }
     finally {
     86                            f = null;
     87                        }

     88                    }

     89                }

     90            }

     91
     92        }
     finally {
     93            // markedHeld為ture,但isLocked()為false,說明上鎖途中出現異常
     94            // 需刪除“鎖文件”的路徑名 
     95            if (markedHeld && !isLocked()) {
     96                synchronized (LOCK_HELD) {    // 注意同步訪問LOCK_HELD
     97                    if (LOCK_HELD.contains(canonicalPath)) {
     98                        LOCK_HELD.remove(canonicalPath);
     99                    }

    100                }

    101            }

    102        }

    103        // 經過以上過程,若成功上鎖則isLock()為true;反之,false
    104        return isLocked();
    105    }

    posted on 2008-11-10 16:26 Rolandz 閱讀(2950) 評論(0)  編輯  收藏


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     

    導航

    統計

    留言簿(1)

    隨筆分類(12)

    隨筆檔案(19)

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲国产av美女网站| 亚洲精品无AMM毛片| 亚洲综合小说久久另类区| 7777久久亚洲中文字幕| 免费观看四虎精品成人| 人妻丰满熟妇无码区免费| 成人永久免费高清| 亚洲电影免费在线观看| 色天使色婷婷在线影院亚洲| 国产亚洲精品免费视频播放| 黄网址在线永久免费观看 | 亚洲AV色欲色欲WWW| 久久久精品午夜免费不卡| 日韩伦理片电影在线免费观看| 亚洲欧美日韩中文高清www777| 99久久免费国产精品热| 国产高清免费在线| 亚洲视频中文字幕| 中文字幕免费在线播放| 亚洲AV无码专区国产乱码4SE| 免费看黄网站在线看| 中国亚洲女人69内射少妇| 亚洲成av人片天堂网无码】| 在线观看亚洲免费| 岛国岛国免费V片在线观看| 亚洲激情在线视频| 成年午夜视频免费观看视频| 亚洲国产日韩在线成人蜜芽| 大地资源二在线观看免费高清| 亚洲精品免费在线| 成人免费看片又大又黄| 一级毛片一级毛片免费毛片| 国产91在线免费| 福利片免费一区二区三区| 全免费a级毛片免费**视频| 人妻免费久久久久久久了| 免费爱爱的视频太爽了| 一个人看的在线免费视频| 亚洲熟妇无码爱v在线观看| 国产免费小视频在线观看| 久草视频在线免费看|