opengrok源码浅析
来源:互联网 发布:阿里云怎么收费标准 编辑:程序博客网 时间:2024/05/22 06:50
最近公司想搭一套代码搜索系统,所以调研了一下Oracle的开源代码搜索系统opengrok的索引建立机制。
opengrok建立索引主要架构图如下所示:
入口在Indexer类中,其中Indexer会对每个project建立一个索引类IndexDatabase,IndexDatabase通过遍历代码目录下的所有文件对每个文件生成索引。IndexDatabase中的indexDown是建立索引的核心方法,对每个文件进行三层解析,第一层解析出文件本身的一些属性(文件名,目录等),第二层用ctags解析出代码中的所有变量定义,第三层用源文件对应对解析器解析出源文件中的所有变量引用,最终把所有解析出来的属性存在一个lucene的Document对象中。
第一层解析关键代码:
doc.add(new Field(QueryBuilder.U, Util.path2uid(path, date), string_ft_stored_nanalyzed_norms)); doc.add(new Field(QueryBuilder.FULLPATH, file.getAbsolutePath(), string_ft_nstored_nanalyzed_norms)); doc.add(new SortedDocValuesField(QueryBuilder.FULLPATH, new BytesRef(file.getAbsolutePath()))); try { HistoryReader hr = HistoryGuru.getInstance().getHistoryReader(file); if (hr != null) { doc.add(new TextField(QueryBuilder.HIST, hr)); // date = hr.getLastCommentDate() //RFE } } catch (HistoryException e) { LOGGER.log(Level.WARNING, "An error occurred while reading history: ", e); } doc.add(new Field(QueryBuilder.DATE, date, string_ft_stored_nanalyzed_norms)); doc.add(new SortedDocValuesField(QueryBuilder.DATE, new BytesRef(date))); if (path != null) { doc.add(new TextField(QueryBuilder.PATH, path, Store.YES)); Project project = Project.getProject(path); if (project != null) { doc.add(new TextField(QueryBuilder.PROJECT, project.getPath(), Store.YES)); } }
其中doc就是lucene的Document,可以看到第一层是解析出了文件的通用的一些信息。
第二和第三层的解析代码:
doc.add(new TextField(QueryBuilder.FULL, getReader(src.getStream()))); String fullpath = doc.get(QueryBuilder.FULLPATH); if (fullpath != null && ctags != null) { defs = ctags.doCtags(fullpath + "\n"); if (defs != null && defs.numberOfSymbols() > 0) { doc.add(new TextField(QueryBuilder.DEFS, new IteratorReader(defs.getSymbols()))); //this is to explicitly use appropriate analyzers tokenstream to workaround #1376 symbols search works like full text search TextField ref=new TextField(QueryBuilder.REFS,this.SymbolTokenizer); this.SymbolTokenizer.setReader(getReader(src.getStream())); doc.add(ref); byte[] tags = defs.serialize(); doc.add(new StoredField(QueryBuilder.TAGS, tags)); } } if (scopesEnabled && xrefOut == null) { /* * Scopes are generated during xref generation. If xrefs are * turned off we still need to run writeXref to produce scopes, * we use a dummy writer that will throw away any xref output. */ xrefOut = new NullWriter(); } if (xrefOut != null) { try (Reader in = getReader(src.getStream())) { writeXref(in, xrefOut); } Scopes scopes = xref.getScopes(); if (scopes.size() > 0) { byte[] scopesSerialized = scopes.serialize(); doc.add(new StoredField(QueryBuilder.SCOPES, scopesSerialized)); } }
可以看到其中区分了代码中的引用(ref)和定义(def)。
最终生成的doc中其实就包含了一个源文件中的若干属性字段,每个字段都可以暴露给客户端进行代码搜索的条件。
结语:代码搜索系统的核心就是根据代码文件的各种属性建立索引,提供给客户端查询,如果做深入的话需要结合语法进行索引,比如有哪些类定义哪些枚举定义有哪些变量定义都可以单独建立索引,opengrok中还有一个很重要的部分是处理文件历史版本以及变化更新索引的机制,这部分暂时还看的不太懂,有时间再继续研究。
阅读全文
0 0
- opengrok源码浅析
- 配置OpenGrok查看源码
- OpenGrok源码搜索引擎搭建
- openGrok
- OpenGrok
- OpenGrok
- OpenGrok
- Mark: Ubuntu搭建OpenGrok阅读源码
- Android系统源码极速搜索引擎(OpenGrok)
- Android系统源码极速搜索引擎(OpenGrok)
- Android系统源码极速搜索引擎(OpenGrok)
- 工具使用-Mac上搭建OpenGrok查看Android源码
- 在Ubuntu 上安装OpenGrok浏览Android源码
- 爱测未来移动-Android源码阅读利器之openGrok
- 搭建大型源码阅读环境——使用 OpenGrok 搭建大型源码阅读环境——使用 OpenGrok
- 安装OpenGrok
- opengrok搭建
- OpenGrok安装
- 如何禁用迅雷9右侧浏览器
- 关于PHP中的sha1和md5的加密函数
- 线程的调度(线程休眠,线程让步,线程插队)
- devexpress(16.2.6)破解不完全
- WebStorm快捷键
- opengrok源码浅析
- kernel初体验
- FieldII命令汇总(part)
- 网络流题目
- java错题mark_4
- 他人理解+自理解+学习Mysql存储过程
- js弹出框、对话框、提示框、弹窗总结
- 面向对象_基本概念(1)
- 四、C_base——基本语句