区块天下 区块链新闻 精通IPFS:IPFS 启动之 boot 函数

精通IPFS:IPFS 启动之 boot 函数

open

方法(位于 ipfs-repo 项目 index.js 文件中),打开仓库。

仓库的 open方法的主体也是一个waterfall函数。仓库的waterfall函数内部,首先调用 root 对象的open方法打开主目录(默认仓库采用的是文件系统保存数据,用的是 datastore-fs 类库),因为主目录在仓库对象初始化时候已经创建好了,所以这个方法什么不做,接下来调用_isInitialized方法检查仓库是否已经初始化过,这个方法会检查配置文件、规格文件、版本文件是否存在。对于第一次进来这咱情况,这些文件还不存在,方法直接抛出异常,导致_isInitialized下面的所有方法不再执行,流程直接到指定的错误处理中。又因为这个时候锁定文件也不存在,所以直接调用callback(err)方法,从而回到open方法的回调函数中。而对于不是第一次进来的情况,具体处理详见init函数执行分析。

仓库 open方法代码如下,后面我们还会遇到这个函数的,这里不细说。

open (callback) {    if (!this.closed) {      setImmediate( => callback(new Error('repo is already open')))      return // early    }    waterfall([      (cb) => this.root.open(ignoringAlreadyOpened(cb)),      (cb) => this._isInitialized(cb),      (cb) => this._openLock(this.path, cb),      (lck, cb) => {        log('aquired repo.lock')        this.lockfile = lck        cb      },      (cb) => {        this.datastore = backends.create('datastore', path.join(this.path, 'datastore'), this.options)        const blocksBaseStore = backends.create('blocks', path.join(this.path, 'blocks'), this.options)        blockstore( blocksBaseStore, this.options.storageBackendOptions.blocks, cb)      },      (blocks, cb) => {        this.blocks = blocks        cb      },      (cb) => {        log('creating keystore')        this.keys = backends.create('keys', path.join(this.path, 'keys'), this.options)        cb      },      (cb) => {        this.closed = false        log('all opened')        cb      }    ], (err) => {      if (err && this.lockfile) {        this._closeLock((err2) => { if (!err2) { this.lockfile = null } else { log('error removing lock', err2) } callback(err)        })      } else {        callback(err)      }    })}

open

方法的回调函数中,调用

isRepoUninitializedError

方法,检查错误的原因,我们这里的原因是仓库还未初始化,所以这个方法返回真,所以用

false

调用第二个函数。

第 1个函数的代码如下:

(cb) => {  if (!self._repo.closed) {    return cb(null, true)  }  // 打开仓库  self._repo.open((err, res) => {    if (isRepoUninitializedError(err)) return cb(null, false)    if (err) return cb(err)    cb(null, true)  })}

如果是第一次进来,那么仓库还不存在,所以没办法打开,即 repoOpened参数为假,所以跳过最上面的初始化。然后,检查doInit变量是否为真,如果为真,则根据指定的选项来初始化仓库。在这里doInit变量的值来自于选项中的init属性,这个属性只是一个简单的真值,所以使用默认的配置来初始化。

第 2个函数的代码如下:

(repoOpened, cb) => {  if (repoOpened) {    return self.init({ repo: self._repo }, (err) => {      if (err) return cb(Object.assign(err, { emitted: true }))      cb    })  }  // 如果仓库不存在,这里需要进行初始化。  if (doInit) {    const initOptions = Object.assign(      { bits: 2048, pass: self._options.pass },      typeof options.init === 'object' ? options.init : {}    )    return self.init(initOptions, (err) => {      if (err) return cb(Object.assign(err, { emitted: true }))      cb    })  }  cb}

注意,在 JS 中真值不一定仅仅只一个 true,也可能是一个对象,一个函数,一个数组等,所在这里检测是否为真,只是检测用户有没有指定这个配置而已,并且确保不是 false 而已。

上面

self

指的是 IPFS 对象,

init

方法位于

core/components/init.js

文件中。下一篇,我们仔细讲解这个函数的执行过程。

返回顶部