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

📄 dag.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 4 页
字号:
      (SVN_ERR_FS_NOT_FILE, NULL,
       "Attempted to set textual contents of a *non*-file node");

  /* Make sure our node is mutable. */
  if (! svn_fs_base__dag_check_mutable (file, txn_id))
    return svn_error_createf
      (SVN_ERR_FS_NOT_MUTABLE, NULL,
       "Attempted to set textual contents of an immutable node");

  /* Get the node revision. */
  SVN_ERR (get_node_revision (&noderev, file, trail));

  /* If this node already has an EDIT-DATA-KEY, destroy the data
     associated with that key.  */
  if (noderev->edit_key)
    SVN_ERR (svn_fs_base__delete_rep_if_mutable (fs, noderev->edit_key,
                                                 txn_id, trail));

  /* Now, let's ensure that we have a new EDIT-DATA-KEY available for
     use. */
  SVN_ERR (svn_fs_base__get_mutable_rep (&mutable_rep_key, NULL, fs,
                                         txn_id, trail));

  /* We made a new rep, so update the node revision. */
  noderev->edit_key = mutable_rep_key;
  SVN_ERR (svn_fs_bdb__put_node_revision (fs, file->id, noderev, trail));

  /* Return a writable stream with which to set new contents. */
  SVN_ERR (svn_fs_base__rep_contents_write_stream (&ws, fs, mutable_rep_key,
                                                   txn_id, FALSE, trail,
                                                   pool));
  *contents = ws;

  return SVN_NO_ERROR;
}



svn_error_t *
svn_fs_base__dag_finalize_edits (dag_node_t *file,
                                 const char *checksum,
                                 const char *txn_id,
                                 trail_t *trail)
{
  svn_fs_t *fs = file->fs;   /* just for nicer indentation */
  node_revision_t *noderev;
  const char *old_data_key;

  /* 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 set textual contents of a *non*-file node");

  /* Make sure our node is mutable. */
  if (! svn_fs_base__dag_check_mutable (file, txn_id))
    return svn_error_createf
      (SVN_ERR_FS_NOT_MUTABLE, NULL,
       "Attempted to set textual contents of an immutable node");

  /* Get the node revision. */
  SVN_ERR (get_node_revision (&noderev, file, trail));

  /* If this node has no EDIT-DATA-KEY, this is a no-op. */
  if (! noderev->edit_key)
    return SVN_NO_ERROR;

  if (checksum)
    {
      unsigned char digest[APR_MD5_DIGESTSIZE];
      const char *hex;

      SVN_ERR (svn_fs_base__rep_contents_checksum
               (digest, fs, noderev->edit_key, trail));

      hex = svn_md5_digest_to_cstring (digest, trail->pool);
      if (strcmp (checksum, hex) != 0)
        return svn_error_createf
          (SVN_ERR_CHECKSUM_MISMATCH,
           NULL,
           "Checksum mismatch, rep '%s':\n"
           "   expected:  %s\n"
           "     actual:  %s\n",
           noderev->edit_key, checksum, hex);
    }

  /* Now, we want to delete the old representation and replace it with
     the new.  Of course, we don't actually delete anything until
     everything is being properly referred to by the node-revision
     skel. */
  old_data_key = noderev->data_key;
  noderev->data_key = noderev->edit_key;
  noderev->edit_key = NULL;
  SVN_ERR (svn_fs_bdb__put_node_revision (fs, file->id, noderev, trail));

  /* Only *now* can we safely destroy the old representation (if it
     even existed in the first place). */
  if (old_data_key)
    SVN_ERR (svn_fs_base__delete_rep_if_mutable (fs, old_data_key, txn_id,
                                                 trail));

  return SVN_NO_ERROR;
}



dag_node_t *
svn_fs_base__dag_dup (dag_node_t *node,
                      apr_pool_t *pool)
{
  /* Allocate our new node. */
  dag_node_t *new_node = apr_pcalloc (pool, sizeof (*new_node));

  new_node->fs = node->fs;
  new_node->pool = pool;
  new_node->id = svn_fs_base__id_copy (node->id, pool);
  new_node->kind = node->kind;
  new_node->created_path = apr_pstrdup (pool, node->created_path);

  /* Leave new_node->node_revision zero for now, so it'll get read in.
     We can get fancy and duplicate node's cache later.  */

  return new_node;
}


svn_error_t *
svn_fs_base__dag_open (dag_node_t **child_p,
                       dag_node_t *parent,
                       const char *name,
                       trail_t *trail)
{
  const svn_fs_id_t *node_id;

  /* Ensure that NAME exists in PARENT's entry list. */
  SVN_ERR (dir_entry_id_from_node (&node_id, parent, name, trail));
  if (! node_id)
    return svn_error_createf
      (SVN_ERR_FS_NOT_FOUND, NULL,
       "Attempted to open non-existent child node '%s'", 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 open node with an illegal name '%s'", name);

  /* Now get the node that was requested. */
  return svn_fs_base__dag_get_node (child_p, svn_fs_base__dag_get_fs (parent),
                                    node_id, trail);
}


svn_error_t *
svn_fs_base__dag_copy (dag_node_t *to_node,
                       const char *entry,
                       dag_node_t *from_node,
                       svn_boolean_t preserve_history,
                       svn_revnum_t from_rev,
                       const char *from_path,
                       const char *txn_id,
                       trail_t *trail)
{
  const svn_fs_id_t *id;

  if (preserve_history)
    {
      node_revision_t *from_noderev, *to_noderev;
      const char *copy_id;
      svn_fs_t *fs = svn_fs_base__dag_get_fs (from_node);
      const svn_fs_id_t *src_id = svn_fs_base__dag_get_id (from_node);
      const char *from_txn_id = NULL;

      /* Make a copy of the original node revision. */
      SVN_ERR (get_node_revision (&from_noderev, from_node, trail));
      to_noderev = copy_node_revision (from_noderev, trail->pool);

      /* Reserve a copy ID for this new copy. */
      SVN_ERR (svn_fs_bdb__reserve_copy_id (&copy_id, fs, trail));

      /* Create a successor with its predecessor pointing at the copy
         source. */
      to_noderev->predecessor_id = svn_fs_base__id_copy (src_id, trail->pool);
      if (to_noderev->predecessor_count != -1)
        to_noderev->predecessor_count++;
      to_noderev->created_path =
        svn_path_join (svn_fs_base__dag_get_created_path (to_node), entry,
                       trail->pool);
      SVN_ERR (svn_fs_base__create_successor (&id, fs, src_id, to_noderev,
                                              copy_id, txn_id, trail));

      /* Translate FROM_REV into a transaction ID. */
      SVN_ERR (svn_fs_base__rev_get_txn_id (&from_txn_id, fs, from_rev,
                                            trail));

      /* Now that we've done the copy, we need to add the information
         about the copy to the `copies' table, using the COPY_ID we
         reserved above.  */
      SVN_ERR (svn_fs_bdb__create_copy
               (fs, copy_id,
                svn_fs_base__canonicalize_abspath (from_path, trail->pool),
                from_txn_id, id, copy_kind_real, trail));

      /* Finally, add the COPY_ID to the transaction's list of copies
         so that, if this transaction is aborted, the `copies' table
         entry we added above will be cleaned up. */
      SVN_ERR (svn_fs_base__add_txn_copy (fs, txn_id, copy_id, trail));
    }
  else  /* don't preserve history */
    {
      id = svn_fs_base__dag_get_id (from_node);
    }

  /* Set the entry in to_node to the new id. */
  SVN_ERR (svn_fs_base__dag_set_entry (to_node, entry, id, txn_id, trail));

  return SVN_NO_ERROR;
}



/*** Deltification ***/

svn_error_t *
svn_fs_base__dag_deltify (dag_node_t *target,
                          dag_node_t *source,
                          svn_boolean_t props_only,
                          trail_t *trail)
{
  node_revision_t *source_nr, *target_nr;
  svn_fs_t *fs = svn_fs_base__dag_get_fs (target);

  /* Get node revisions for the two nodes.  */
  SVN_ERR (get_node_revision (&target_nr, target, trail));
  SVN_ERR (get_node_revision (&source_nr, source, trail));

  /* If TARGET and SOURCE both have properties, and are not sharing a
     property key, deltify TARGET's properties.  */
  if (target_nr->prop_key
      && source_nr->prop_key
      && (strcmp (target_nr->prop_key, source_nr->prop_key)))
    SVN_ERR (svn_fs_base__rep_deltify (fs, target_nr->prop_key,
                                       source_nr->prop_key, trail));

  /* If we are not only attending to properties, and if TARGET and
     SOURCE both have data, and are not sharing a data key, deltify
     TARGET's data.  */
  if ((! props_only)
      && target_nr->data_key
      && source_nr->data_key
      && (strcmp (target_nr->data_key, source_nr->data_key)))
   SVN_ERR (svn_fs_base__rep_deltify (fs, target_nr->data_key,
                                      source_nr->data_key, trail));

  return SVN_NO_ERROR;
}




/*** Committing ***/

svn_error_t *
svn_fs_base__dag_commit_txn (svn_revnum_t *new_rev,
                             svn_fs_t *fs,
                             const char *txn_id,
                             trail_t *trail)
{
  revision_t revision;
  svn_string_t date;

  /* Add new revision entry to `revisions' table. */
  revision.txn_id = txn_id;
  if (new_rev)
    *new_rev = SVN_INVALID_REVNUM;
  SVN_ERR (svn_fs_bdb__put_rev (new_rev, fs, &revision, trail));

  /* Promote the unfinished transaction to a committed one. */
  SVN_ERR (svn_fs_base__txn_make_committed (fs, txn_id, *new_rev, trail));

  /* Set a date on the commit.  We wait until now to fetch the date,
     so it's definitely newer than any previous revision's date. */
  date.data = svn_time_to_cstring (apr_time_now(), trail->pool);
  date.len = strlen (date.data);
  SVN_ERR (svn_fs_base__set_rev_prop (fs, *new_rev, SVN_PROP_REVISION_DATE,
                                      &date, trail));

  return SVN_NO_ERROR;
}



/*** Comparison. ***/

svn_error_t *
svn_fs_base__things_different (svn_boolean_t *props_changed,
                               svn_boolean_t *contents_changed,
                               dag_node_t *node1,
                               dag_node_t *node2,
                               trail_t *trail)
{
  node_revision_t *noderev1, *noderev2;

  /* If we have no place to store our results, don't bother doing
     anything. */
  if (! props_changed && ! contents_changed)
    return SVN_NO_ERROR;

  /* The the node revision skels for these two nodes. */
  SVN_ERR (get_node_revision (&noderev1, node1, trail));
  SVN_ERR (get_node_revision (&noderev2, node2, trail));

  /* Compare property keys. */
  if (props_changed != NULL)
    *props_changed = (! svn_fs_base__same_keys (noderev1->prop_key,
                                                noderev2->prop_key));

  /* Compare contents keys. */
  if (contents_changed != NULL)
    *contents_changed = (! svn_fs_base__same_keys (noderev1->data_key,
                                                   noderev2->data_key));

  return SVN_NO_ERROR;
}



struct is_ancestor_baton
{
  const svn_fs_id_t *node1_id;
  svn_boolean_t is_ancestor;
  svn_boolean_t need_parent; /* TRUE if we only care about parenthood, not
                                full ancestry */
};


static svn_error_t *
is_ancestor_callback (void *baton,
                      dag_node_t *node,
                      svn_boolean_t *done,
                      trail_t *trail)
{
  struct is_ancestor_baton *b = baton;

  /* If there is no NODE, then this is the last call, and we didn't
     find an ancestor.  But if there is ... */
  if (node)
    {
      /* ... compare NODE's ID with the ID we're looking for. */
      if (svn_fs_base__id_eq (b->node1_id, svn_fs_base__dag_get_id (node)))
        b->is_ancestor = TRUE;

      /* Now, if we only are interested in parenthood, we don't care
         to look any further than this. */
      if (b->need_parent)
        *done = TRUE;
    }

  return SVN_NO_ERROR;
}

svn_error_t *
svn_fs_base__dag_is_ancestor (svn_boolean_t *is_ancestor,
                              dag_node_t *node1,
                              dag_node_t *node2,
                              trail_t *trail)
{
  struct is_ancestor_baton baton;
  const svn_fs_id_t
    *id1 = svn_fs_base__dag_get_id (node1),
    *id2 = svn_fs_base__dag_get_id (node2);

  /* Pessimism. */
  *is_ancestor = FALSE;

  /* Ancestry holds relatedness as a prerequisite. */
  if (! svn_fs_base__id_check_related (id1, id2))
    return SVN_NO_ERROR;

  baton.is_ancestor = FALSE;
  baton.need_parent = FALSE;
  baton.node1_id = id1;

  SVN_ERR (svn_fs_base__dag_walk_predecessors (node2, is_ancestor_callback,
                                               &baton, trail));
  if (baton.is_ancestor)
    *is_ancestor = TRUE;

  return SVN_NO_ERROR;
}


svn_error_t *
svn_fs_base__dag_is_parent (svn_boolean_t *is_parent,
                            dag_node_t *node1,
                            dag_node_t *node2,
                            trail_t *trail)
{
  struct is_ancestor_baton baton;
  const svn_fs_id_t
    *id1 = svn_fs_base__dag_get_id (node1),
    *id2 = svn_fs_base__dag_get_id (node2);

  /* Pessimism. */
  *is_parent = FALSE;

  /* Parentry holds relatedness as a prerequisite. */
  if (! svn_fs_base__id_check_related (id1, id2))
    return SVN_NO_ERROR;

  baton.is_ancestor = FALSE;
  baton.need_parent = TRUE;
  baton.node1_id = id1;

  SVN_ERR (svn_fs_base__dag_walk_predecessors (node2, is_ancestor_callback,
                                               &baton, trail));
  if (baton.is_ancestor)
    *is_parent = TRUE;

  return SVN_NO_ERROR;
}

⌨️ 快捷键说明

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