Logo Search packages:      
Sourcecode: zookeeper version File versions  Download package

int ZkFuseFile::update ( bool  newFile  )  [inline]

Update the children information and the data caches as needed.

This method is invoked when a ZkFuse regular file or directory implemented by this ZkFuseFile instance is opened, e.g. using open or opendir. It attempts to:

  • make sure that the cache has valid children information
  • register for watches for changes if no previous watches have been registered.

The newFile flag indicates if the ZkFuseFile instance has just been constructed and that ZooKeeper has not been contacted to determine if the ZooKeeper path for this file really exist. When a ZkFuseFile instance is created, the _deleted flag is set to true because it is safer to assume that the ZooKeeper node does not exist. The newFile flag causes the _deleted flag to be ignored and ZooKeeper to be contacted to update the caches.

If the newFile flag is false, then the ZkFuseFile instance is currently open and have been opened before. Hence, these previous opens should have contacted ZooKeeper and would like learned from ZooKeeper whether the ZooKeeper path exists. Therefore, the _deleted flag should be trustworthy, i.e. it has accurate information on whether the ZooKeeper path actually exists.

Returns:
0 if successful, otherwise return negative errno.
Parameters:
newFile set to true if the ZkFuseFile instance is newly created.

Definition at line 2195 of file zkfuse.cc.

References _activeData, _activeStat, _children, _childrenListener, _clearChildren(), _dataListener, _deleted, _dirtyData, _getZkContext(), _hasChildrenListener, _hasDataListener, _initializedChildren, _initializedData, _isOnlyRegOpen(), _isZombie(), _latestData, _latestStat, _manager, _mutex, _path, zk::ZooKeeperException::getZKErrorCode(), zk::ZooKeeperException::what(), and ZNONODE.

Referenced by ZkFuseHandleManager::open().

    {
        LOG_DEBUG(LOG, "update(newFile %d) path %s", newFile, _path.c_str());

        int res = 0;
        {
            AutoLock lock(_mutex);

            /* At this point, cannot be zombie.
             */
            assert(!_isZombie());
            if (!newFile && _deleted) {
                /* Deleted file, don't bother to update caches */
                LOG_DEBUG(LOG, "deleted, not new file"); 
                res = -ENOENT;
            }
            else {
                try {
                    LOG_DEBUG(LOG, "initialized children %d, data %d",
                              _initializedChildren, _initializedData);
                    LOG_DEBUG(LOG, "has children watch %d, data watch %d",
                              _hasChildrenListener, _hasDataListener);
                    /*
                     * Children handling starts here.
                     * If don't have children listener,
                     *    then must establish listener.
                     * If don't have cached children information, 
                     *    then must get children information. 
                     * It just happens, that the same ZooKeeper API 
                     * is used for both.
                     */
                    if (_initializedChildren == false ||
                        _hasChildrenListener == false
#ifdef ZOOKEEPER_ROOT_CHILDREN_WATCH_BUG
                        /* HACK for root node because changes to children
                         * on a root node does not cause children watches to
                         * fire.
                         */
                        || _path.length() == 1
#endif // ZOOKEEPER_ROOT_CHILDREN_WATCH_BUG
                    ) {
                        LOG_DEBUG(LOG, "update children");
                        NodeNames children;
                        _manager->getCommon().getZkAdapter()->
                          getNodeChildren( children, _path, 
                                          &_childrenListener, _getZkContext());
                        _hasChildrenListener = true;
                        LOG_DEBUG(LOG, "update children done"); 
                        _children.swap(children);
                        _initializedChildren = true;
                        /* Since getNodeChildren is successful, the
                         * path must exist */
                        _deleted = false;
                    }
                    else {
                        /* Children information is fresh since 
                         * it is initialized and and have been 
                         * updated by listener.
                         */
                    }
                    /*
                     * Data handling starts here.
                     */
                    assert(newFile == false || _isOnlyRegOpen());
                    if (!_isOnlyRegOpen()) {
                        /* If is already currently opened by someone,
                         * then don't update data with latest from ZooKeeper,
                         * use current active data (which may be initialized 
                         * or not).
                         * \see _activeData
                         */
                        LOG_DEBUG(LOG, "node currently in-use, no data update");
                    } 
                    else {
                        /* If not opened/reopened by someone else, 
                         *    then perform more comprehensive checks of
                         *    to make data and listener is setup correctly.
                         * If don't have data listener,
                         *    then must establish listener.
                         * If don't have cached data, 
                         *    then must get data.
                         * It just happens, that the same ZooKeeper API 
                         * is used for both.  
                         */
                        LOG_DEBUG(LOG, "node first use or reuse");
                        if (_initializedData == false ||
                            _hasDataListener == false) {
                            /* Don't have any data for now or need to register
                             * for callback */
                            LOG_DEBUG(LOG, "update data");
                            _latestData = 
                                _manager->getCommon().getZkAdapter()->
                                getNodeData(_path, &_dataListener, 
                                            _getZkContext(), 
                                            &_latestStat);
                            _hasDataListener = true;
                            LOG_DEBUG(LOG, 
                                      "update data done, latest version %d",
                                      _latestStat.version);
                            /* Since getNodeData is successful, the
                             * path must exist. */
                            _deleted = false;
                        } 
                        else {
                            /* Data is fresh since it is initialized and
                             * and have been updated by listener.
                             */
                        }
                        /* Update active data to the same as the most 
                         * recently acquire data.
                         */
                        _activeData = _latestData;
                        _activeStat = _latestStat;
                        _initializedData = true;
                        _dirtyData = false;
                        LOG_DEBUG(LOG, "update set active version %d",
                                  _activeStat.version);
                    } 
                    res = 0;
                } catch (const ZooKeeperException & e) {
                    /* May have ZNONODE exception if path does exist. */
                    if (e.getZKErrorCode() == ZNONODE) {
                        LOG_DEBUG(LOG, "update %s exception %s", 
                                  _path.c_str(), e.what());
                        /* Path does not exist, set _deleted, 
                         * clear children information cache 
                         */
                        _deleted = true;
                        _clearChildren();
                        res = -ENOENT;
                    } else {
                        LOG_ERROR(LOG, "update %s exception %s", 
                                  _path.c_str(), e.what());
                        res = -EIO;
                    }
                }
            }
        }
    
        LOG_DEBUG(LOG, "update returns %d", res);
        return res;
    }


Generated by  Doxygen 1.6.0   Back to index