<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](三)

    Directory類系

    綜述:Directory類系可以被理解成是一個(gè)文件夾,它提供些對(duì)文件夾內(nèi)容及本身的一些操作。比如:

    1.建立/讀取/刪除/重命名文件;
    2.復(fù)制文件夾;
    3.查尋是否存在某文件;
    4.設(shè)置/獲取某文件最后訪問時(shí)間;
    5.查尋文件夾大小;
    6.查看文件列表

    1Directory類系層次圖

    2. 部分代碼說明

    Directory

    Directory是所有文件夾類的父類。它規(guī)定了所有子類必須提供的操作,但它本身只實(shí)現(xiàn)了部分,其中比較重要的就是文件夾間的拷貝操作copy()方法。

     1    public static void copy(Directory src, Directory dest, boolean closeDirSrc)
     2            throws IOException {    // 文件夾之間的的復(fù)制
     3        final String[] files = src.list();    // 獲取源文件夾文件列表
     4
     5        if (files == null)
     6            throw new IOException("cannot read directory " + src
     7                    + ": list() returned null");
     8
     9        byte[] buf = new byte[BufferedIndexOutput.BUFFER_SIZE];    // 建立緩沖buf
    10        for (int i = 0; i < files.length; i++{    // 對(duì)每個(gè)文件進(jìn)行復(fù)制操作
    11            IndexOutput os = null;    // 寫通道
    12            IndexInput is = null;    // 讀通道
    13            try {
    14                // create file in dest directory
    15                os = dest.createOutput(files[i]);    // 創(chuàng)建對(duì)file[i]的寫通道
    16                // read current file
    17                is = src.openInput(files[i]);    // 讀通道
    18                // and copy to dest directory
    19                long len = is.length();    // 文件總長(zhǎng)度
    20                long readCount = 0;    // 已讀取長(zhǎng)度
    21                while (readCount < len) {    // 循環(huán)讀取文件數(shù)據(jù)
    22                    int toRead = readCount + BufferedIndexOutput.BUFFER_SIZE > len ? (int) (len - readCount)
    23                            : BufferedIndexOutput.BUFFER_SIZE;    // 實(shí)際一次讀取長(zhǎng)度 
    24                    is.readBytes(buf, 0, toRead);    // 讀取
    25                    os.writeBytes(buf, toRead);    // 寫入
    26                    readCount += toRead;    // 記錄已寫入數(shù)量
    27                }

    28            }
     finally {    // 關(guān)閉操作
    29                // graceful cleanup
    30                try {
    31                    if (os != null)
    32                        os.close();
    33                }
     finally {
    34                    if (is != null)
    35                        is.close();
    36                }

    37            }

    38        }

    39        if (closeDirSrc)
    40            src.close();
    41    }


    FSDirectory

    FSDirectory是基于硬盤的Directory

    FSDirectory中最重要的實(shí)例生成方法就是getFSDirectory(File, LockFactory)了。

     1    public static FSDirectory getDirectory(File file, LockFactory lockFactory)
     2            throws IOException {
     3        file = new File(file.getCanonicalPath());    // 獲得file
     4
     5        if (file.exists() && !file.isDirectory())    // file存在但不是文件夾
     6            throw new IOException(file + " not a directory");
     7
     8        if (!file.exists())    // file不存在
     9            if (!file.mkdirs())    // 試圖創(chuàng)建file文件夾,失敗則拋出異常
    10                throw new IOException("Cannot create directory: " + file);
    11
    12        FSDirectory dir;
    13        synchronized (DIRECTORIES) {    // 同步訪問DIRECTORIES
    14            dir = (FSDirectory) DIRECTORIES.get(file);    // 試圖從DIRECTORIES中獲取
    15            if (dir == null{    // 獲取失敗
    16                try {
    17                    dir = (FSDirectory) IMPL.newInstance();    // 創(chuàng)建一個(gè)新實(shí)例
    18                }
     catch (Exception e) {
    19                    throw new RuntimeException(
    20                            "cannot load FSDirectory class: " + e.toString(), e);
    21                }

    22                dir.init(file, lockFactory);    // 初始化dir
    23                DIRECTORIES.put(file, dir);    // 把dir放入DIRECTORIES
    24            }
     else {
    25                // Catch the case where a Directory is pulled from the cache,
    26                // but has a
    27                // different LockFactory instance.
    28                if (lockFactory != null && lockFactory != dir.getLockFactory()) {
    29                    throw new IOException(
    30                            "Directory was previously created with a different LockFactory instance; please pass null as the lockFactory instance and use setLockFactory to change it");
    31                }

    32            }

    33        }

    34        synchronized (dir) {
    35            dir.refCount++;    // refCount++
    36        }

    37        return dir;
    38    }


    init(File, LockFactory)為初始化FSDirectory實(shí)例的方法,只能內(nèi)部調(diào)用。

     1    private void init(File path, LockFactory lockFactory) throws IOException {
     2
     3        // Set up lockFactory with cascaded defaults: if an instance was passed
     4        // in,
     5        // use that; else if locks are disabled, use NoLockFactory; else if the
     6        // system property org.apache.lucene.store.FSDirectoryLockFactoryClass
     7        // is set,
     8        // instantiate that; else, use SimpleFSLockFactory:
     9
    10        directory = path;
    11
    12        boolean doClearLockID = false;
    13
    14        if (lockFactory == null{
    15
    16            if (disableLocks) {
    17                // Locks are disabled:
    18                lockFactory = NoLockFactory.getNoLockFactory();
    19            }
     else {
    20                String lockClassName = System
    21                        .getProperty("org.apache.lucene.store.FSDirectoryLockFactoryClass");
    22
    23                if (lockClassName != null && !lockClassName.equals("")) {    // 系統(tǒng)設(shè)置了默認(rèn)lockFactory
    24                    Class c;
    25
    26                    try {
    27                        c = Class.forName(lockClassName);
    28                    }
     catch (ClassNotFoundException e) {
    29                        throw new IOException("unable to find LockClass "
    30                                + lockClassName);
    31                    }

    32
    33                    try {
    34                        lockFactory = (LockFactory) c.newInstance();    // 實(shí)例化系統(tǒng)默認(rèn)的lockFactory
    35                    }
     catch (IllegalAccessException e) {
    36                        throw new IOException(
    37                                "IllegalAccessException when instantiating LockClass "
    38                                        + lockClassName);
    39                    }
     catch (InstantiationException e) {
    40                        throw new IOException(
    41                                "InstantiationException when instantiating LockClass "
    42                                        + lockClassName);
    43                    }
     catch (ClassCastException e) {
    44                        throw new IOException("unable to cast LockClass "
    45                                + lockClassName + " instance to a LockFactory");
    46                    }

    47
    48                    if (lockFactory instanceof NativeFSLockFactory) {    // 根據(jù)lockFactory的類型各自調(diào)用setLockDir()
    49                        ((NativeFSLockFactory) lockFactory).setLockDir(path);
    50                    }
     else if (lockFactory instanceof SimpleFSLockFactory) {
    51                        ((SimpleFSLockFactory) lockFactory).setLockDir(path);
    52                    }

    53                }
     else {    // 使用lucene默認(rèn)的lockFactory: SimpleFSLockFactory
    54                    // Our default lock is SimpleFSLockFactory;
    55                    // default lockDir is our index directory:
    56                    lockFactory = new SimpleFSLockFactory(path);
    57                    doClearLockID = true;    // 設(shè)置為true,    不懂!!!!!!
    58                }

    59            }

    60        }

    61
    62        setLockFactory(lockFactory);    // 設(shè)置lockFactory
    63
    64        if (doClearLockID) {
    65            // Clear the prefix because write.lock will be
    66            // stored in our directory:
    67            lockFactory.setLockPrefix(null);
    68        }

    69    }


    MMapDirectory

    MMapDirectoryFSDirectory的子類,它重寫了FSDirectoryopenInput()方法。他們的區(qū)別是,在讀取文件時(shí),FSDirectory在底層用BufferedIndexInput(把文件部分讀入內(nèi)存),而MMapDirectory則用MMapDirectory/MultiMMapDirectory(把文件一次性全部讀入內(nèi)存)。

     

    openInput(String)功能為打開某文件的讀取通道。

     

     1    public IndexInput openInput(String name) throws IOException {
     2        File f = new File(getFile(), name);    
     3        RandomAccessFile raf = new RandomAccessFile(f, "r");
     4        try {    // 根據(jù)文件的大小選擇適當(dāng)?shù)腎ndexInput
     5            return (raf.length() <= MAX_BBUF) ? (IndexInput) new MMapIndexInput(
     6                    raf)
     7                    : (IndexInput) new MultiMMapIndexInput(raf, MAX_BBUF);
     8        }
     finally {
     9            raf.close();
    10        }

    11    }

     

    RAMDirectory

    RAMDirectoryFSDirectory不同,它是基于內(nèi)存的。它在內(nèi)存中劃出一個(gè)區(qū)域,用來存放文件,在性能上肯定要比FSDirectory快的多。當(dāng)然它也有它的局限性,比如,文件過大,內(nèi)存小放不下,呵呵。

     

    RAMDirectory里定義了變量:HashMap fileMap = new HashMap()用來存放文件名及與之對(duì)應(yīng)得文件在內(nèi)存中的指針。還有一個(gè)變量long sizeInBytes:文件夾總字節(jié)數(shù)。

     

    當(dāng)通過Directory來創(chuàng)建RAMDirectory時(shí),RAMDirectory需要把Directory中的數(shù)據(jù)拷貝到RAMDirectory中來。

     

    1    private RAMDirectory(Directory dir, boolean closeDir) throws IOException {
    2        this();
    3        Directory.copy(dir, this, closeDir);    // 拷貝數(shù)據(jù)
    4    }

     

    list()用來列出RAMDirectory中的所有文件,也就是fileMap中的所有文件名。

     

     1    public synchronized final String[] list() // 列出fileMap中的文件清單
     2        ensureOpen(); // 確保fileMap不為空
     3        Set fileNames = fileMap.keySet(); // 返回文件名set
     4        String[] result = new String[fileNames.size()];
     5        int i = 0;
     6        Iterator it = fileNames.iterator();
     7        while (it.hasNext())
     8            // 遍歷文件名
     9            result[i++= (String) it.next();
    10        return result; // 返回文件名數(shù)組
    11    }

     

    在查詢某文件是否存在時(shí),只需要到fileMap中看下對(duì)應(yīng)的文件名是否存在。

     

    1    public final boolean fileExists(String name) // 查詢是否存在名為name的文件
    2        ensureOpen();
    3        RAMFile file;
    4        synchronized (this{
    5            file = (RAMFile) fileMap.get(name); // 從fileMap中取name文件
    6        }

    7        // file != null 說明文件存在;反之,不存在
    8        return file != null;
    9    }

     

    touchFile(String)功能是修改給定文件名的文件的最近修改時(shí)間。方法本身并不是同步方法,因此在方法體內(nèi)部需要考慮同步的問題。

     

     1    public void touchFile(String name) throws IOException {
     2        // 修設(shè)置最近修改時(shí)間為當(dāng)前時(shí)間
     3        ensureOpen();
     4        RAMFile file;
     5        synchronized (this{
     6            file = (RAMFile) fileMap.get(name);
     7        }

     8        if (file == null)
     9            throw new FileNotFoundException(name);
    10
    11        long ts2, ts1 = System.currentTimeMillis();
    12        do // 這個(gè)循環(huán)的用意是什么?????有人告訴我不????
    13            try {
    14                Thread.sleep(01); // 睡 1ns
    15            }
     catch (InterruptedException e) {
    16            }

    17            ts2 = System.currentTimeMillis(); // 獲取當(dāng)前時(shí)間
    18        }
     while (ts1 == ts2);
    19
    20        file.setLastModified(ts2);    // 同步修改最近修改時(shí)間
    21    }

     

    deleteFile(String)功能為刪除給定文件名的文件,不存在則拋出異常。

     

     1    public synchronized void deleteFile(String name) throws IOException // 刪除name文件
     2        ensureOpen();
     3        RAMFile file = (RAMFile) fileMap.get(name);
     4        if (file != null{
     5            fileMap.remove(name); // 從fileMap中刪除此文件,也就是刪掉該文件的相關(guān)記錄:名字和buffer地址
     6            file.directory = null// 設(shè)置file的所屬文件夾為null,即它不再屬于任何文件夾
     7            sizeInBytes -= file.sizeInBytes; // updates to RAMFile.sizeInBytes synchronized on directory
     8        }
     else
     9            throw new FileNotFoundException(name);
    10    }

     

    createOutput()創(chuàng)建一個(gè)新文件并返回其寫通道。若同名文件已存在,則刪除之。

     

        public IndexOutput createOutput(String name) throws IOException // 新建給定名字的文件并返回它的寫通道
            ensureOpen(); // 確保fileMap不為null
            RAMFile file = new RAMFile(this); // 創(chuàng)建一個(gè)內(nèi)存文件,參數(shù)為當(dāng)前文件夾
            synchronized (this// 獲取同步鎖
                RAMFile existing = (RAMFile) fileMap.get(name);
                
    if (existing != null// 存在同名文件,則刪除之
                    sizeInBytes -= existing.sizeInBytes; // 更改文件夾大小
                    existing.directory = null// 設(shè)置其directory為null
                }

                fileMap.put(name, file);
            }

            
    return new RAMOutputStream(file); // 返回該文件的寫通道
        }

     

    posted on 2008-11-17 19:30 Rolandz 閱讀(1293) 評(píng)論(0)  編輯  收藏


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


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

    導(dǎo)航

    統(tǒng)計(jì)

    留言簿(1)

    隨筆分類(12)

    隨筆檔案(19)

    積分與排名

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 黄色网址免费观看| 麻豆亚洲av熟女国产一区二| 亚洲精品久久无码av片俺去也 | 国产精品免费AV片在线观看| 亚洲国产午夜中文字幕精品黄网站| 亚洲男同gay片| 一二三四免费观看在线视频中文版 | 国产精品免费_区二区三区观看| 亚洲人成网站在线观看播放动漫| 人妻丰满熟妇无码区免费 | 久久亚洲国产成人精品无码区| 色噜噜的亚洲男人的天堂| 成人免费看黄20分钟| 亚洲jjzzjjzz在线播放| 国产精品视频免费| 亚洲综合久久久久久中文字幕| 日韩精品无码一区二区三区免费| 国产亚洲精品a在线观看app| 两个人www免费高清视频| 亚洲中文字幕成人在线| 一级黄色片免费观看| 亚洲精品高清一二区久久| 精品亚洲成a人在线观看| 国产gav成人免费播放视频| 亚洲AV女人18毛片水真多| 狠狠久久永久免费观看| 亚洲JLZZJLZZ少妇| 永久中文字幕免费视频网站| 亚洲国产综合AV在线观看| 国产成人综合久久精品免费| 精品免费AV一区二区三区| 亚洲精品高清在线| 久久国产福利免费| 亚洲精品无码av人在线观看| a级毛片100部免费观看| 亚洲国产精品国自产拍电影| 91久久青青草原线免费| 亚洲另类视频在线观看| 成人毛片免费观看视频| 国产精品亚洲专区一区| 亚洲成av人片不卡无码久久|