<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 的機(jī)制來實(shí)現(xiàn)同一文件夾的互斥訪問:當(dāng)有進(jìn)程訪問需要互斥訪問的文件夾時(shí),首先查看與之關(guān)聯(lián)的是否存在,若存在則拒絕訪問;若不存在,則先上,訪問之,最后解。不同的Lock子類,具體的實(shí)現(xiàn)方式并不一樣。

    1.Lock/LockFactory類系的層次圖



    2.
    部分代碼說明

    Lock

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

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

     

    Lock還提供了兩個(gè)靜態(tài)變量:long LOCK_POLL_INTERVAL(默認(rèn)值為1000ms)和final long LOCK_OBTAIN_WAIT_FOREVER(值為-1) ,前者為試圖獲取時(shí)的時(shí)間間隔值,后者為當(dāng)lockWaitTimeout設(shè)置為該值時(shí),obtain(long)將會(huì)無限期試圖獲取

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

     1    public boolean obtain(long lockWaitTimeout)
     2            throws LockObtainFailedException, IOException {
     3        failureReason = null;
     4        // locked試圖獲取“鎖文件”。obtain()的功能是及時(shí)返回是否能取得“鎖文件”
     5        boolean locked = obtain();
     6        // 給定參數(shù)值為負(fù)并且不等于-1,則拋出參數(shù)值設(shè)置異常
     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        // 設(shè)置最大睡眠次數(shù)
    12        long maxSleepCount = lockWaitTimeout / LOCK_POLL_INTERVAL;
    13        long sleepCount = 0;    // 睡眠次數(shù)累加器
    14        // 循環(huán)直到取得“鎖文件”;或者時(shí)間到,則拋出異常
    15        while (!locked) {
    16            if (lockWaitTimeout != LOCK_OBTAIN_WAIT_FOREVER
    17                    && sleepCount++ >= maxSleepCount) {        // 參數(shù)lockWaitTimeout不為-1且累計(jì)睡眠次數(shù)大于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(默認(rèn)1000ms)時(shí)間
    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類中,是通過給需要訪問的文件夾另外建立一個(gè)文件的方式來實(shí)現(xiàn)的;查看某文件夾是否被上鎖,你需要做的僅僅是查看下與其相關(guān)的鎖文件是否存在;解鎖時(shí)只需刪除鎖文件就萬事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        // 說明:建立成功,也就是說“鎖文件”不存在; 失敗,說明“鎖文件”已經(jīng)存在,也就是說該文件夾已被上鎖
    17        return lockFile.createNewFile();
    18    }

    NativeFSLock

    NativeFSLockSimpleFSLock有些不同,它的用的是鎖文件的鎖,說起來很是繞口,其實(shí)它只是給鎖文件上一把鎖:在查看某文件夾是否能被訪問時(shí),首先檢查與此文件夾關(guān)聯(lián)的鎖文件的鎖是否被占用,而不像SimpleFSLock僅僅查看與之相連的鎖文件是否存在。正因?yàn)槿绱耍鉀Q了如果JVM異常退出時(shí)遺留的鎖文件的問題:在SimpleFSLock中,只要鎖文件存在,就被人為該文件夾被鎖,而不能被任何其他進(jìn)程訪問。

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

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

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

      1    public synchronized boolean obtain() throws IOException {    // 該方法被設(shè)置為同步訪問
      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;    //標(biāo)記在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) {    // 設(shè)置LOCK_HELD的同步訪問
     29                if (LOCK_HELD.contains(canonicalPath)) {    // 如果標(biāo)準(zhǔn)路徑存在于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;    // 設(shè)置為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{    // 如果沒有取得鎖,需關(guān)閉通道并設(shè)置其為null
     74                            try {
     75                                channel.close();    //關(guān)閉通道
     76                            }
     finally {
     77                                channel = null;    //設(shè)置為null
     78                            }

     79                        }

     80                    }

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

     88                    }

     89                }

     90            }

     91
     92        }
     finally {
     93            // markedHeld為ture,但isLocked()為false,說明上鎖途中出現(xiàn)異常
     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        // 經(jīng)過以上過程,若成功上鎖則isLock()為true;反之,false
    104        return isLocked();
    105    }

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


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     

    導(dǎo)航

    統(tǒng)計(jì)

    留言簿(1)

    隨筆分類(12)

    隨筆檔案(19)

    積分與排名

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 又黄又大的激情视频在线观看免费视频社区在线 | 亚洲国产成人AV在线播放| 国产一区视频在线免费观看| 在线免费观看h片| 亚洲男人的天堂久久精品| 无码专区一va亚洲v专区在线| 免费国产成人午夜在线观看| 亚洲私人无码综合久久网| 亚洲永久无码3D动漫一区| 可以免费看黄视频的网站| 九九视频高清视频免费观看| 亚洲欧洲自拍拍偷综合| 亚洲黄片毛片在线观看| 男女超爽刺激视频免费播放| 成人免费777777被爆出| 亚洲熟妇无码八V在线播放| 亚洲AV永久青草无码精品| 日韩视频免费在线| 91久久精品国产免费一区| 一级a性色生活片久久无少妇一级婬片免费放 | 亚洲国产91精品无码专区| 免费人成在线观看69式小视频| 一个人看的免费视频www在线高清动漫| 亚洲在成人网在线看| 亚洲人成网77777色在线播放| 免费看无码自慰一区二区| 精品一区二区三区无码免费视频| 日本永久免费a∨在线视频| 亚洲午夜电影在线观看高清 | 久久久久免费精品国产小说| 污污视频免费观看网站| 亚洲人成图片网站| 97久久精品亚洲中文字幕无码| 久久精品国产精品亚洲精品| 4444www免费看| 日批视频网址免费观看| 色九月亚洲综合网| 日韩亚洲不卡在线视频中文字幕在线观看 | 亚洲精品视频免费在线观看| 亚洲免费观看视频| 亚洲综合另类小说色区色噜噜|