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

📄 dag.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 4 页
字号:
    {
      /* This has already been cloned */
      new_node_id = cur_entry->id;
    }
  else
    {
      node_revision_t *noderev;

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

      /* Do the clone thingy here. */
      noderev->predecessor_id = svn_fs_base__id_copy (cur_entry->id,
                                                      trail->pool);
      if (noderev->predecessor_count != -1)
        noderev->predecessor_count++;
      noderev->created_path = svn_path_join (parent_path, name, trail->pool);
      SVN_ERR (svn_fs_base__create_successor (&new_node_id, fs, cur_entry->id,
                                              noderev, copy_id, txn_id,
                                              trail));

      /* Replace the ID in the parent's ENTRY list with the ID which
         refers to the mutable clone of this child. */
      SVN_ERR (set_entry (parent, name, new_node_id, txn_id, trail));
    }

  /* Initialize the youngster. */
  return svn_fs_base__dag_get_node (child_p, fs, new_node_id, trail);
}



svn_error_t *
svn_fs_base__dag_clone_root (dag_node_t **root_p,
                             svn_fs_t *fs,
                             const char *txn_id,
                             trail_t *trail)
{
  const svn_fs_id_t *base_root_id, *root_id;
  node_revision_t *noderev;

  /* Get the node ID's of the root directories of the transaction and
     its base revision.  */
  SVN_ERR (svn_fs_base__get_txn_ids (&root_id, &base_root_id, fs, txn_id,
                                     trail));

  /* Oh, give me a clone...
     (If they're the same, we haven't cloned the transaction's root
     directory yet.)  */
  if (svn_fs_base__id_eq (root_id, base_root_id))
    {
      const char *base_copy_id = svn_fs_base__id_copy_id (base_root_id);

      /* Of my own flesh and bone...
         (Get the NODE-REVISION for the base node, and then write
         it back out as the clone.) */
      SVN_ERR (svn_fs_bdb__get_node_revision (&noderev, fs, base_root_id,
                                              trail));

      /* Store it. */
      /* ### todo: Does it even makes sense to have a different copy id for
         the root node?  That is, does this function need a copy_id
         passed in?  */
      noderev->predecessor_id = svn_fs_base__id_copy (base_root_id,
                                                      trail->pool);
      if (noderev->predecessor_count != -1)
        noderev->predecessor_count++;
      SVN_ERR (svn_fs_base__create_successor (&root_id, fs, base_root_id,
                                              noderev, base_copy_id,
                                              txn_id, trail));

      /* ... And when it is grown
       *      Then my own little clone
       *        Will be of the opposite sex!
       */
      SVN_ERR (svn_fs_base__set_txn_root (fs, txn_id, root_id, trail));
    }

  /* One way or another, root_id now identifies a cloned root node. */
  SVN_ERR (svn_fs_base__dag_get_node (root_p, fs, root_id, trail));

  /*
   * (Sung to the tune of "Home, Home on the Range", with thanks to
   * Randall Garrett and Isaac Asimov.)
   */

  return SVN_NO_ERROR;
}


/* Delete the directory entry named NAME from PARENT, as part of
   TRAIL.  PARENT must be mutable.  NAME must be a single path
   component.  If REQUIRE_EMPTY is true and the node being deleted is
   a directory, it must be empty.

   If return SVN_ERR_FS_NO_SUCH_ENTRY, then there is no entry NAME in
   PARENT.  */
svn_error_t *
svn_fs_base__dag_delete (dag_node_t *parent,
                         const char *name,
                         const char *txn_id,
                         trail_t *trail)
{
  node_revision_t *parent_noderev;
  const char *rep_key, *mutable_rep_key;
  apr_hash_t *entries = NULL;
  skel_t *entries_skel;
  svn_fs_t *fs = parent->fs;
  svn_string_t str;
  svn_fs_id_t *id = NULL;
  dag_node_t *node;

  /* Make sure parent is a directory. */
  if (parent->kind != svn_node_dir)
    return svn_error_createf
      (SVN_ERR_FS_NOT_DIRECTORY, NULL,
       "Attempted to delete entry '%s' from *non*-directory node", name);

  /* Make sure 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 delete entry '%s' from immutable directory node", name);

  /* 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 delete a node with an illegal name '%s'", name);

  /* Get a fresh NODE-REVISION for the parent node. */
  SVN_ERR (get_node_revision (&parent_noderev, parent, trail));

  /* Get the key for the parent's entries list (data) representation. */
  rep_key = parent_noderev->data_key;

  /* No REP_KEY means no representation, and no representation means
     no data, and no data means no entries...there's nothing here to
     delete! */
  if (! rep_key)
    return svn_error_createf
      (SVN_ERR_FS_NO_SUCH_ENTRY, NULL,
       "Delete failed--directory has no entry '%s'", name);

  /* Ensure we have a key to a mutable representation of the entries
     list.  We'll have to update the NODE-REVISION if it points to an
     immutable version.  */
  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))
    {
      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));
    }

  /* Read the representation, then use it to get the string that holds
     the entries list.  Parse that list into a skel, and parse *that*
     into a hash. */

  SVN_ERR (svn_fs_base__rep_contents (&str, fs, rep_key, trail));
  entries_skel = svn_fs_base__parse_skel (str.data, str.len, trail->pool);
  if (entries_skel)
    SVN_ERR (svn_fs_base__parse_entries_skel (&entries, entries_skel,
                                              trail->pool));

  /* Find NAME in the ENTRIES skel.  */
  if (entries)
    id = apr_hash_get (entries, name, APR_HASH_KEY_STRING);

  /* If we never found ID in ENTRIES (perhaps because there are no
     ENTRIES, perhaps because ID just isn't in the existing ENTRIES
     ... it doesn't matter), return an error.  */
  if (! id)
    return svn_error_createf
      (SVN_ERR_FS_NO_SUCH_ENTRY, NULL,
       "Delete failed--directory has no entry '%s'", name);

  /* Use the ID of this ENTRY to get the entry's node.  */
  SVN_ERR (svn_fs_base__dag_get_node (&node, svn_fs_base__dag_get_fs (parent),
                                      id, trail));

  /* If mutable, remove it and any mutable children from db. */
  SVN_ERR (svn_fs_base__dag_delete_if_mutable (parent->fs, id, txn_id, trail));

  /* Remove this entry from its parent's entries list. */
  apr_hash_set (entries, name, APR_HASH_KEY_STRING, NULL);

  /* Replace the old entries list with the new one. */
  {
    svn_stream_t *ws;
    svn_stringbuf_t *unparsed_entries;
    apr_size_t len;

    SVN_ERR (svn_fs_base__unparse_entries_skel (&entries_skel, entries,
                                                trail->pool));
    unparsed_entries = svn_fs_base__unparse_skel (entries_skel, trail->pool);
    SVN_ERR (svn_fs_base__rep_contents_write_stream (&ws, fs, mutable_rep_key,
                                                     txn_id, TRUE, trail,
                                                     trail->pool));
    len = unparsed_entries->len;
    SVN_ERR (svn_stream_write (ws, unparsed_entries->data, &len));
    SVN_ERR (svn_stream_close (ws));
  }

  return SVN_NO_ERROR;
}


svn_error_t *
svn_fs_base__dag_remove_node (svn_fs_t *fs,
                              const svn_fs_id_t *id,
                              const char *txn_id,
                              trail_t *trail)
{
  dag_node_t *node;
  node_revision_t *noderev;

  /* Fetch the node. */
  SVN_ERR (svn_fs_base__dag_get_node (&node, fs, id, trail));

  /* If immutable, do nothing and return immediately. */
  if (! svn_fs_base__dag_check_mutable (node, txn_id))
    return svn_error_createf (SVN_ERR_FS_NOT_MUTABLE, NULL,
                              "Attempted removal of immutable node");

  /* Get a fresh node-revision. */
  SVN_ERR (svn_fs_bdb__get_node_revision (&noderev, fs, id, trail));

  /* Delete any mutable property representation. */
  if (noderev->prop_key)
    SVN_ERR (svn_fs_base__delete_rep_if_mutable (fs, noderev->prop_key,
                                                 txn_id, trail));

  /* Delete any mutable data representation. */
  if (noderev->data_key)
    SVN_ERR (svn_fs_base__delete_rep_if_mutable (fs, noderev->data_key,
                                                 txn_id, trail));

  /* Delete any mutable edit representation (files only). */
  if (noderev->edit_key)
    SVN_ERR (svn_fs_base__delete_rep_if_mutable (fs, noderev->edit_key,
                                                 txn_id, trail));

  /* Delete the node revision itself. */
  SVN_ERR (svn_fs_base__delete_node_revision (fs, id, trail));

  return SVN_NO_ERROR;
}


svn_error_t *
svn_fs_base__dag_delete_if_mutable (svn_fs_t *fs,
                                    const svn_fs_id_t *id,
                                    const char *txn_id,
                                    trail_t *trail)
{
  dag_node_t *node;

  /* Get the node. */
  SVN_ERR (svn_fs_base__dag_get_node (&node, fs, id, trail));

  /* If immutable, do nothing and return immediately. */
  if (! svn_fs_base__dag_check_mutable (node, txn_id))
    return SVN_NO_ERROR;

  /* Else it's mutable.  Recurse on directories... */
  if (node->kind == svn_node_dir)
    {
      apr_hash_t *entries;
      apr_hash_index_t *hi;
      apr_pool_t *pool = trail->pool;

      /* Loop over hash entries */
      SVN_ERR (svn_fs_base__dag_dir_entries (&entries, node, trail));
      if (entries)
        {
          for (hi = apr_hash_first (pool, entries);
               hi;
               hi = apr_hash_next (hi))
            {
              void *val;
              svn_fs_dirent_t *dirent;

              apr_hash_this (hi, NULL, NULL, &val);
              dirent = val;
              SVN_ERR (svn_fs_base__dag_delete_if_mutable (fs, dirent->id,
                                                           txn_id, trail));
            }
        }
    }

  /* ... then delete the node itself, after deleting any mutable
     representations and strings it points to. */
  SVN_ERR (svn_fs_base__dag_remove_node (fs, id, txn_id, trail));

  return SVN_NO_ERROR;
}


svn_error_t *
svn_fs_base__dag_make_file (dag_node_t **child_p,
                            dag_node_t *parent,
                            const char *parent_path,
                            const char *name,
                            const char *txn_id,
                            trail_t *trail)
{
  /* Call our little helper function */
  return make_entry (child_p, parent, parent_path, name, FALSE, txn_id, trail);
}


svn_error_t *
svn_fs_base__dag_make_dir (dag_node_t **child_p,
                           dag_node_t *parent,
                           const char *parent_path,
                           const char *name,
                           const char *txn_id,
                           trail_t *trail)
{
  /* Call our little helper function */
  return make_entry (child_p, parent, parent_path, name, TRUE, txn_id, trail);
}


svn_error_t *
svn_fs_base__dag_get_contents (svn_stream_t **contents,
                               dag_node_t *file,
                               apr_pool_t *pool,
                               trail_t *trail)
{
  node_revision_t *noderev;

  /* Make sure our node is a file. */
  if (file->kind != svn_node_file)
    return svn_error_createf
      (SVN_ERR_FS_NOT_FILE, NULL,
       "Attempted to get textual contents of a *non*-file node");

  /* Go get a fresh node-revision for FILE. */
  SVN_ERR (get_node_revision (&noderev, file, trail));

  /* Our job is to _return_ a stream on the file's contents, so the
     stream has to be trail-independent.  Here, we pass NULL to tell
     the stream that we're not providing it a trail that lives across
     reads.  This means the stream will do each read in a one-off,
     temporary trail.  */
  SVN_ERR (svn_fs_base__rep_contents_read_stream (contents, file->fs,
                                                  noderev->data_key,
                                                  FALSE, trail, pool));

  /* Note that we're not registering any `close' func, because there's
     nothing to cleanup outside of our trail.  When the trail is
     freed, the stream/baton will be too. */

  return SVN_NO_ERROR;
}


svn_error_t *
svn_fs_base__dag_file_length (svn_filesize_t *length,
                              dag_node_t *file,
                              trail_t *trail)
{
  node_revision_t *noderev;

  /* Make sure our node is a file. */
  if (file->kind != svn_node_file)
    return svn_error_createf
      (SVN_ERR_FS_NOT_FILE, NULL,
       "Attempted to get length of a *non*-file node");

  /* Go get a fresh node-revision for FILE, and . */
  SVN_ERR (get_node_revision (&noderev, file, trail));
  if (noderev->data_key)
    SVN_ERR (svn_fs_base__rep_contents_size (length, file->fs,
                                             noderev->data_key, trail));
  else
    *length = 0;

  return SVN_NO_ERROR;
}


svn_error_t *
svn_fs_base__dag_file_checksum (unsigned char digest[],
                                dag_node_t *file,
                                trail_t *trail)
{
  node_revision_t *noderev;

  if (file->kind != svn_node_file)
    return svn_error_createf
      (SVN_ERR_FS_NOT_FILE, NULL,
       "Attempted to get checksum of a *non*-file node");

  SVN_ERR (get_node_revision (&noderev, file, trail));
  if (noderev->data_key)
    SVN_ERR (svn_fs_base__rep_contents_checksum (digest, file->fs,
                                                 noderev->data_key, trail));
  else
    memset (digest, 0, APR_MD5_DIGESTSIZE);

  return SVN_NO_ERROR;
}


svn_error_t *
svn_fs_base__dag_get_edit_stream (svn_stream_t **contents,
                                  dag_node_t *file,
                                  apr_pool_t *pool,
                                  const char *txn_id,
                                  trail_t *trail)
{
  svn_fs_t *fs = file->fs;   /* just for nicer indentation */
  node_revision_t *noderev;
  const char *mutable_rep_key;
  svn_stream_t *ws;

  /* Make sure our node is a file. */
  if (file->kind != svn_node_file)
    return svn_error_createf

⌨️ 快捷键说明

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