⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dag.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 4 页
字号:
  apr_hash_index_t *hi;
  svn_string_t entries_raw;
  skel_t *entries_skel;

  /* Error if this is not a directory. */
  if (noderev->kind != svn_node_dir)
    return svn_error_create
      (SVN_ERR_FS_NOT_DIRECTORY, NULL,
       "Attempted to create entry in non-directory parent");

  /* If there's a DATA-KEY, there might be entries to fetch. */
  if (noderev->data_key)
    {
      /* Now we have a rep, follow through to get the entries. */
      SVN_ERR (svn_fs_base__rep_contents (&entries_raw, fs,
                                          noderev->data_key, trail));
      entries_skel = svn_fs_base__parse_skel (entries_raw.data,
                                              entries_raw.len, trail->pool);

      /* Were there entries?  Make a hash from them. */
      if (entries_skel)
        SVN_ERR (svn_fs_base__parse_entries_skel (&entries, entries_skel,
                                                  trail->pool));
    }

  /* No hash?  No problem.  */
  *entries_p = NULL;
  if (! entries)
    return SVN_NO_ERROR;

  /* Else, convert the hash from a name->id mapping to a name->dirent one.  */
  *entries_p = apr_hash_make (trail->pool);
  for (hi = apr_hash_first (trail->pool, entries); hi; hi = apr_hash_next (hi))
    {
      const void *key;
      apr_ssize_t klen;
      void *val;
      svn_fs_dirent_t *dirent = apr_palloc (trail->pool, sizeof (*dirent));

      /* KEY will be the entry name in ancestor, VAL the id.  */
      apr_hash_this (hi, &key, &klen, &val);
      dirent->name = key;
      dirent->id = val;
      dirent->kind = svn_node_unknown;
      apr_hash_set (*entries_p, key, klen, dirent);
    }

  /* Return our findings. */
  return SVN_NO_ERROR;
}


/* Set *ID_P to the node-id for entry NAME in PARENT, as part of
   TRAIL.  If no such entry, set *ID_P to NULL but do not error.  The
   entry is allocated in TRAIL->pool or in the same pool as PARENT;
   the caller should copy if it cares.  */
static svn_error_t *
dir_entry_id_from_node (const svn_fs_id_t **id_p,
                        dag_node_t *parent,
                        const char *name,
                        trail_t *trail)
{
  apr_hash_t *entries;
  svn_fs_dirent_t *dirent;

  SVN_ERR (svn_fs_base__dag_dir_entries (&entries, parent, trail));
  if (entries)
    dirent = apr_hash_get (entries, name, APR_HASH_KEY_STRING);
  else
    dirent = NULL;

  *id_p = dirent ? dirent->id : NULL;
  return SVN_NO_ERROR;
}


/* Add or set in PARENT a directory entry NAME pointing to ID.
   Allocations are done in TRAIL.

   Assumptions:
   - PARENT is a mutable directory.
   - ID does not refer to an ancestor of parent
   - NAME is a single path component
*/
static svn_error_t *
set_entry (dag_node_t *parent,
           const char *name,
           const svn_fs_id_t *id,
           const char *txn_id,
           trail_t *trail)
{
  node_revision_t *parent_noderev;
  const char *rep_key, *mutable_rep_key;
  apr_hash_t *entries = NULL;
  svn_stream_t *wstream;
  apr_size_t len;
  svn_string_t raw_entries;
  svn_stringbuf_t *raw_entries_buf;
  skel_t *entries_skel;
  svn_fs_t *fs = svn_fs_base__dag_get_fs (parent);

  /* Get the parent's node-revision. */
  SVN_ERR (get_node_revision (&parent_noderev, parent, trail));
  rep_key = parent_noderev->data_key;
  SVN_ERR (svn_fs_base__get_mutable_rep (&mutable_rep_key, rep_key,
                                         fs, txn_id, trail));

  /* If the parent node already pointed at a mutable representation,
     we don't need to do anything.  But if it didn't, either because
     the parent didn't refer to any rep yet or because it referred to
     an immutable one, we must make the parent refer to the mutable
     rep we just created. */
  if (! svn_fs_base__same_keys (rep_key, mutable_rep_key))
    {
      node_revision_t *new_noderev =
        copy_node_revision (parent_noderev, trail->pool);
      new_noderev->data_key = mutable_rep_key;
      SVN_ERR (set_node_revision (parent, new_noderev, trail));
    }

  /* If the new representation inherited nothing, start a new entries
     list for it.  Else, go read its existing entries list. */
  if (rep_key)
    {
      SVN_ERR (svn_fs_base__rep_contents (&raw_entries, fs, rep_key, trail));
      entries_skel = svn_fs_base__parse_skel (raw_entries.data,
                                              raw_entries.len, trail->pool);
      if (entries_skel)
        SVN_ERR (svn_fs_base__parse_entries_skel (&entries, entries_skel,
                                                  trail->pool));
    }

  /* If we still have no ENTRIES hash, make one here.  */
  if (! entries)
    entries = apr_hash_make (trail->pool);

  /* Now, add our new entry to the entries list. */
  apr_hash_set (entries, name, APR_HASH_KEY_STRING, id);

  /* Finally, replace the old entries list with the new one. */
  SVN_ERR (svn_fs_base__unparse_entries_skel (&entries_skel, entries,
                                              trail->pool));
  raw_entries_buf = svn_fs_base__unparse_skel (entries_skel, trail->pool);
  SVN_ERR (svn_fs_base__rep_contents_write_stream (&wstream, fs,
                                                   mutable_rep_key, txn_id,
                                                   TRUE, trail, trail->pool));
  len = raw_entries_buf->len;
  SVN_ERR (svn_stream_write (wstream, raw_entries_buf->data, &len));
  SVN_ERR (svn_stream_close (wstream));
  return SVN_NO_ERROR;
}


/* Make a new entry named NAME in PARENT, as part of TRAIL.  If IS_DIR
   is true, then the node revision the new entry points to will be a
   directory, else it will be a file.  The new node will be allocated
   in TRAIL->pool.  PARENT must be mutable, and must not have an entry
   named NAME.  */
static svn_error_t *
make_entry (dag_node_t **child_p,
            dag_node_t *parent,
            const char *parent_path,
            const char *name,
            svn_boolean_t is_dir,
            const char *txn_id,
            trail_t *trail)
{
  const svn_fs_id_t *new_node_id;
  node_revision_t new_noderev;

  /* Make sure that NAME is a single path component. */
  if (! svn_path_is_single_path_component (name))
    return svn_error_createf
      (SVN_ERR_FS_NOT_SINGLE_PATH_COMPONENT, NULL,
       "Attempted to create a node with an illegal name '%s'", name);

  /* Make sure that parent is a directory */
  if (parent->kind != svn_node_dir)
    return svn_error_create
      (SVN_ERR_FS_NOT_DIRECTORY, NULL,
       "Attempted to create entry in non-directory parent");

  /* Check that the parent is mutable. */
  if (! svn_fs_base__dag_check_mutable (parent, txn_id))
    return svn_error_createf
      (SVN_ERR_FS_NOT_MUTABLE, NULL,
       "Attempted to clone child of non-mutable node");

  /* Check that parent does not already have an entry named NAME. */
  SVN_ERR (dir_entry_id_from_node (&new_node_id, parent, name, trail));
  if (new_node_id)
    return svn_error_createf
      (SVN_ERR_FS_ALREADY_EXISTS, NULL,
       "Attempted to create entry that already exists");

  /* Create the new node's NODE-REVISION */
  memset (&new_noderev, 0, sizeof (new_noderev));
  new_noderev.kind = is_dir ? svn_node_dir : svn_node_file;
  new_noderev.created_path = svn_path_join (parent_path, name, trail->pool);
  SVN_ERR (svn_fs_base__create_node
           (&new_node_id, svn_fs_base__dag_get_fs (parent), &new_noderev,
            svn_fs_base__id_copy_id (svn_fs_base__dag_get_id (parent)),
            txn_id, trail));

  /* Create a new dag_node_t for our new node */
  SVN_ERR (svn_fs_base__dag_get_node (child_p,
                                      svn_fs_base__dag_get_fs (parent),
                                      new_node_id, trail));

  /* We can safely call set_entry because we already know that
     PARENT is mutable, and we just created CHILD, so we know it has
     no ancestors (therefore, PARENT cannot be an ancestor of CHILD) */
  SVN_ERR (set_entry (parent, name, svn_fs_base__dag_get_id (*child_p),
                      txn_id, trail));

  return SVN_NO_ERROR;
}


svn_error_t *
svn_fs_base__dag_dir_entries (apr_hash_t **entries,
                              dag_node_t *node,
                              trail_t *trail)
{
  node_revision_t *noderev;

  SVN_ERR (get_node_revision (&noderev, node, trail));
  return get_dir_entries (entries, svn_fs_base__dag_get_fs (node), noderev,
                          trail);
}


svn_error_t *
svn_fs_base__dag_set_entry (dag_node_t *node,
                            const char *entry_name,
                            const svn_fs_id_t *id,
                            const char *txn_id,
                            trail_t *trail)
{
  /* Check it's a directory. */
  if (node->kind != svn_node_dir)
    return svn_error_create
      (SVN_ERR_FS_NOT_DIRECTORY, NULL,
       "Attempted to set entry in non-directory node");

  /* Check it's mutable. */
  if (! svn_fs_base__dag_check_mutable (node, txn_id))
    return svn_error_create
      (SVN_ERR_FS_NOT_DIRECTORY, NULL,
       "Attempted to set entry in immutable node");

  return set_entry (node, entry_name, id, txn_id, trail);
}



/*** Proplists. ***/

svn_error_t *
svn_fs_base__dag_get_proplist (apr_hash_t **proplist_p,
                               dag_node_t *node,
                               trail_t *trail)
{
  node_revision_t *noderev;
  apr_hash_t *proplist = NULL;
  svn_string_t raw_proplist;
  skel_t *proplist_skel;

  /* Go get a fresh NODE-REVISION for this node. */
  SVN_ERR (get_node_revision (&noderev, node, trail));

  /* Get property key (returning early if there isn't one) . */
  if (! noderev->prop_key)
    {
      *proplist_p = NULL;
      return SVN_NO_ERROR;
    }

  /* Get the string associated with the property rep, parsing it as a
     skel, and then attempt to parse *that* into a property hash.  */
  SVN_ERR (svn_fs_base__rep_contents (&raw_proplist,
                                      svn_fs_base__dag_get_fs (node),
                                      noderev->prop_key, trail));
  proplist_skel = svn_fs_base__parse_skel (raw_proplist.data, raw_proplist.len,
                                           trail->pool);
  if (proplist_skel)
    SVN_ERR (svn_fs_base__parse_proplist_skel (&proplist, proplist_skel,
                                               trail->pool));

  *proplist_p = proplist;
  return SVN_NO_ERROR;
}


svn_error_t *
svn_fs_base__dag_set_proplist (dag_node_t *node,
                               apr_hash_t *proplist,
                               const char *txn_id,
                               trail_t *trail)
{
  node_revision_t *noderev;
  const char *rep_key, *mutable_rep_key;
  svn_fs_t *fs = svn_fs_base__dag_get_fs (node);

  /* Sanity check: this node better be mutable! */
  if (! svn_fs_base__dag_check_mutable (node, txn_id))
    {
      svn_string_t *idstr = svn_fs_base__id_unparse (node->id, node->pool);
      return svn_error_createf
        (SVN_ERR_FS_NOT_MUTABLE, NULL,
         "Can't set proplist on *immutable* node-revision %s", idstr->data);
    }

  /* Go get a fresh NODE-REVISION for this node. */
  SVN_ERR (get_node_revision (&noderev, node, trail));
  rep_key = noderev->prop_key;

  /* Get a mutable version of this rep (updating the node revision if
     this isn't a NOOP)  */
  SVN_ERR (svn_fs_base__get_mutable_rep (&mutable_rep_key, rep_key,
                                         fs, txn_id, trail));
  if (! svn_fs_base__same_keys (mutable_rep_key, rep_key))
    {
      noderev->prop_key = mutable_rep_key;
      SVN_ERR (svn_fs_bdb__put_node_revision (fs, node->id, noderev, trail));
    }

  /* Replace the old property list with the new one. */
  {
    svn_stream_t *wstream;
    apr_size_t len;
    skel_t *proplist_skel;
    svn_stringbuf_t *raw_proplist_buf;

    SVN_ERR (svn_fs_base__unparse_proplist_skel (&proplist_skel, proplist,
                                                 trail->pool));
    raw_proplist_buf = svn_fs_base__unparse_skel (proplist_skel, trail->pool);
    SVN_ERR (svn_fs_base__rep_contents_write_stream (&wstream, fs,
                                                     mutable_rep_key, txn_id,
                                                     TRUE, trail,
                                                     trail->pool));
    len = raw_proplist_buf->len;
    SVN_ERR (svn_stream_write (wstream, raw_proplist_buf->data, &len));
    SVN_ERR (svn_stream_close (wstream));
  }

  return SVN_NO_ERROR;
}



/*** Roots. ***/

svn_error_t *
svn_fs_base__dag_revision_root (dag_node_t **node_p,
                                svn_fs_t *fs,
                                svn_revnum_t rev,
                                trail_t *trail)
{
  const svn_fs_id_t *root_id;

  SVN_ERR (svn_fs_base__rev_get_root (&root_id, fs, rev, trail));
  return svn_fs_base__dag_get_node (node_p, fs, root_id, trail);
}


svn_error_t *
svn_fs_base__dag_txn_root (dag_node_t **node_p,
                           svn_fs_t *fs,
                           const char *txn_id,
                           trail_t *trail)
{
  const svn_fs_id_t *root_id, *ignored;

  SVN_ERR (svn_fs_base__get_txn_ids (&root_id, &ignored, fs, txn_id, trail));
  return svn_fs_base__dag_get_node (node_p, fs, root_id, trail);
}


svn_error_t *
svn_fs_base__dag_txn_base_root (dag_node_t **node_p,
                                svn_fs_t *fs,
                                const char *txn_id,
                                trail_t *trail)
{
  const svn_fs_id_t *base_root_id, *ignored;

  SVN_ERR (svn_fs_base__get_txn_ids (&ignored, &base_root_id, fs, txn_id,
                                     trail));
  return svn_fs_base__dag_get_node (node_p, fs, base_root_id, trail);
}


svn_error_t *
svn_fs_base__dag_clone_child (dag_node_t **child_p,
                              dag_node_t *parent,
                              const char *parent_path,
                              const char *name,
                              const char *copy_id,
                              const char *txn_id,
                              trail_t *trail)
{
  dag_node_t *cur_entry; /* parent's current entry named NAME */
  const svn_fs_id_t *new_node_id; /* node id we'll put into NEW_NODE */
  svn_fs_t *fs = svn_fs_base__dag_get_fs (parent);

  /* First check that the parent is mutable. */
  if (! svn_fs_base__dag_check_mutable (parent, txn_id))
    return svn_error_createf
      (SVN_ERR_FS_NOT_MUTABLE, NULL,
       "Attempted to clone child of non-mutable node");

  /* Make sure that NAME is a single path component. */
  if (! svn_path_is_single_path_component (name))
    return svn_error_createf
      (SVN_ERR_FS_NOT_SINGLE_PATH_COMPONENT, NULL,
       "Attempted to make a child clone with an illegal name '%s'", name);

  /* Find the node named NAME in PARENT's entries list if it exists. */
  SVN_ERR (svn_fs_base__dag_open (&cur_entry, parent, name, trail));

  /* Check for mutability in the node we found.  If it's mutable, we
     don't need to clone it. */
  if (svn_fs_base__dag_check_mutable (cur_entry, txn_id))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -