<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類系可以被理解成是一個文件夾,它提供些對文件夾內容及本身的一些操作。比如:

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

    1Directory類系層次圖

    2. 部分代碼說明

    Directory

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

     1    public static void copy(Directory src, Directory dest, boolean closeDirSrc)
     2            throws IOException {    // 文件夾之間的的復制
     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++{    // 對每個文件進行復制操作
    11            IndexOutput os = null;    // 寫通道
    12            IndexInput is = null;    // 讀通道
    13            try {
    14                // create file in dest directory
    15                os = dest.createOutput(files[i]);    // 創建對file[i]的寫通道
    16                // read current file
    17                is = src.openInput(files[i]);    // 讀通道
    18                // and copy to dest directory
    19                long len = is.length();    // 文件總長度
    20                long readCount = 0;    // 已讀取長度
    21                while (readCount < len) {    // 循環讀取文件數據
    22                    int toRead = readCount + BufferedIndexOutput.BUFFER_SIZE > len ? (int) (len - readCount)
    23                            : BufferedIndexOutput.BUFFER_SIZE;    // 實際一次讀取長度 
    24                    is.readBytes(buf, 0, toRead);    // 讀取
    25                    os.writeBytes(buf, toRead);    // 寫入
    26                    readCount += toRead;    // 記錄已寫入數量
    27                }

    28            }
     finally {    // 關閉操作
    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中最重要的實例生成方法就是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())    // 試圖創建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();    // 創建一個新實例
    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實例的方法,只能內部調用。

     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("")) {    // 系統設置了默認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();    // 實例化系統默認的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) {    // 根據lockFactory的類型各自調用setLockDir()
    49                        ((NativeFSLockFactory) lockFactory).setLockDir(path);
    50                    }
     else if (lockFactory instanceof SimpleFSLockFactory) {
    51                        ((SimpleFSLockFactory) lockFactory).setLockDir(path);
    52                    }

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

    59            }

    60        }

    61
    62        setLockFactory(lockFactory);    // 設置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()方法。他們的區別是,在讀取文件時,FSDirectory在底層用BufferedIndexInput(把文件部分讀入內存),而MMapDirectory則用MMapDirectory/MultiMMapDirectory(把文件一次性全部讀入內存)。

     

    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 {    // 根據文件的大小選擇適當的IndexInput
     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不同,它是基于內存的。它在內存中劃出一個區域,用來存放文件,在性能上肯定要比FSDirectory快的多。當然它也有它的局限性,比如,文件過大,內存小放不下,呵呵。

     

    RAMDirectory里定義了變量:HashMap fileMap = new HashMap()用來存放文件名及與之對應得文件在內存中的指針。還有一個變量long sizeInBytes:文件夾總字節數。

     

    當通過Directory來創建RAMDirectory時,RAMDirectory需要把Directory中的數據拷貝到RAMDirectory中來。

     

    1    private RAMDirectory(Directory dir, boolean closeDir) throws IOException {
    2        this();
    3        Directory.copy(dir, this, closeDir);    // 拷貝數據
    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; // 返回文件名數組
    11    }

     

    在查詢某文件是否存在時,只需要到fileMap中看下對應的文件名是否存在。

     

    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)功能是修改給定文件名的文件的最近修改時間。方法本身并不是同步方法,因此在方法體內部需要考慮同步的問題。

     

     1    public void touchFile(String name) throws IOException {
     2        // 修設置最近修改時間為當前時間
     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 // 這個循環的用意是什么?????有人告訴我不????
    13            try {
    14                Thread.sleep(01); // 睡 1ns
    15            }
     catch (InterruptedException e) {
    16            }

    17            ts2 = System.currentTimeMillis(); // 獲取當前時間
    18        }
     while (ts1 == ts2);
    19
    20        file.setLastModified(ts2);    // 同步修改最近修改時間
    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中刪除此文件,也就是刪掉該文件的相關記錄:名字和buffer地址
     6            file.directory = null// 設置file的所屬文件夾為null,即它不再屬于任何文件夾
     7            sizeInBytes -= file.sizeInBytes; // updates to RAMFile.sizeInBytes synchronized on directory
     8        }
     else
     9            throw new FileNotFoundException(name);
    10    }

     

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

     

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

                fileMap.put(name, file);
            }

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

     

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


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


    網站導航:
     

    導航

    統計

    留言簿(1)

    隨筆分類(12)

    隨筆檔案(19)

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 看Aⅴ免费毛片手机播放| 日本免费一区二区三区最新 | 女人被免费视频网站| 国产羞羞的视频在线观看免费| 亚洲精品成a人在线观看☆| 亚洲一区免费观看| 中文字幕不卡亚洲| 国产成人精品男人免费| 4hu四虎最新免费地址| 日本一区二区免费看| www.av在线免费观看| 老司机午夜在线视频免费观| 亚洲免费综合色在线视频| 亚洲乱码一二三四区国产| 亚洲国产美国国产综合一区二区| 亚洲另类少妇17p| 国产免费怕怕免费视频观看| 成年网站免费视频A在线双飞| 99在线在线视频免费视频观看| 少妇性饥渴无码A区免费| 一级毛片大全免费播放下载 | 18pao国产成视频永久免费| 精品成人免费自拍视频| 三级黄色片免费看| 精品一区二区三区免费观看| 人碰人碰人成人免费视频| 精品视频免费在线| 青娱乐在线免费观看视频| 免费无码又爽又黄又刺激网站 | 国产一级一片免费播放i| 永久黄网站色视频免费观看| 四虎成人免费网址在线| 曰皮全部过程视频免费国产30分钟 | 免费A级毛片在线播放不收费| 日本牲交大片免费观看| 免费国产成人午夜电影| 午夜亚洲av永久无码精品| 亚洲精品无码久久毛片| 亚洲视频在线精品| 精品国产亚洲一区二区三区| 亚洲AV无码一区二区乱孑伦AS |