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

📄 reps-strings.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* reps-strings.c : intepreting representations with respect to strings * * ==================================================================== * Copyright (c) 2000-2004 CollabNet.  All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution.  The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals.  For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */#include <assert.h>#include <apr_md5.h>#define APU_WANT_DB#include <apu_want.h>#include "svn_fs.h"#include "svn_pools.h"#include "svn_md5.h"#include "fs.h"#include "err.h"#include "trail.h"#include "reps-strings.h"#include "bdb/reps-table.h"#include "bdb/strings-table.h"#include "../libsvn_fs/fs-loader.h"#include "svn_private_config.h"/*** Helper Functions ***//* Return non-zero iff REP is mutable under transaction TXN_ID. */static svn_boolean_t rep_is_mutable(representation_t *rep,                                    const char *txn_id){  if ((! rep->txn_id) || (strcmp(rep->txn_id, txn_id) != 0))    return FALSE;  return TRUE;}/* Helper macro that evaluates to an error message indicating that   the representation referred to by X has an unknown node kind. */#define UNKNOWN_NODE_KIND(x)                                   \  svn_error_createf                                            \    (SVN_ERR_FS_CORRUPT, NULL,                                 \     _("Unknown node kind for representation '%s'"), x)/* Return a `fulltext' representation, allocated in POOL, which * references the string STR_KEY. * * If TXN_ID is non-zero and non-NULL, make the representation mutable * under that TXN_ID. * * If STR_KEY is non-null, copy it into an allocation from POOL. * * If CHECKSUM is non-null, use it as the checksum for the new rep; * else initialize the rep with an all-zero (i.e., always successful) * checksum. */static representation_t *make_fulltext_rep(const char *str_key,                  const char *txn_id,                  const unsigned char *checksum,                  apr_pool_t *pool){  representation_t *rep = apr_pcalloc(pool, sizeof(*rep));  if (txn_id && *txn_id)    rep->txn_id = apr_pstrdup(pool, txn_id);  rep->kind = rep_kind_fulltext;  if (checksum)    memcpy(rep->checksum, checksum, APR_MD5_DIGESTSIZE);  else    memset(rep->checksum, 0, APR_MD5_DIGESTSIZE);  rep->contents.fulltext.string_key    = str_key ? apr_pstrdup(pool, str_key) : NULL;  return rep;}/* Set *KEYS to an array of string keys gleaned from `delta'   representation REP.  Allocate *KEYS in POOL. */static svn_error_t *delta_string_keys(apr_array_header_t **keys,                  const representation_t *rep,                  apr_pool_t *pool){  const char *key;  int i;  apr_array_header_t *chunks;  if (rep->kind != rep_kind_delta)    return svn_error_create      (SVN_ERR_FS_GENERAL, NULL,       _("Representation is not of type 'delta'"));  /* Set up a convenience variable. */  chunks = rep->contents.delta.chunks;  /* Initialize *KEYS to an empty array. */  *keys = apr_array_make(pool, chunks->nelts, sizeof(key));  if (! chunks->nelts)    return SVN_NO_ERROR;  /* Now, push the string keys for each window into *KEYS */  for (i = 0; i < chunks->nelts; i++)    {      rep_delta_chunk_t *chunk =        (((rep_delta_chunk_t **) chunks->elts)[i]);      key = apr_pstrdup(pool, chunk->string_key);      (*((const char **)(apr_array_push(*keys)))) = key;    }  return SVN_NO_ERROR;}/* Delete the strings associated with array KEYS in FS as part of TRAIL.  */static svn_error_t *delete_strings(apr_array_header_t *keys,               svn_fs_t *fs,               trail_t *trail,               apr_pool_t *pool){  int i;  const char *str_key;  apr_pool_t *subpool = svn_pool_create(pool);  for (i = 0; i < keys->nelts; i++)    {      svn_pool_clear(subpool);      str_key = ((const char **) keys->elts)[i];      SVN_ERR(svn_fs_bdb__string_delete(fs, str_key, trail, subpool));    }  svn_pool_destroy(subpool);  return SVN_NO_ERROR;}/*** Reading the contents from a representation. ***/struct compose_handler_baton{  /* The combined window, and the pool it's allocated from. */  svn_txdelta_window_t *window;  apr_pool_t *window_pool;  /* If the incoming window was self-compressed, and the combined WINDOW     exists from previous iterations, SOURCE_BUF will point to the     expanded self-compressed window. */  char *source_buf;  /* The trail for this operation. WINDOW_POOL will be a child of     TRAIL->pool. No allocations will be made from TRAIL->pool itself. */  trail_t *trail;  /* TRUE when no more windows have to be read/combined. */  svn_boolean_t done;  /* TRUE if we've just started reading a new window. We need this     because the svndiff handler will push a NULL window at the end of     the stream, and we have to ignore that; but we must also know     when it's appropriate to push a NULL window at the combiner. */  svn_boolean_t init;};/* Handle one window. If BATON is emtpy, copy the WINDOW into it;   otherwise, combine WINDOW with the one in BATON, unless WINDOW   is self-compressed (i.e., does not copy from the source view),   in which case expand. */static svn_error_t *compose_handler(svn_txdelta_window_t *window, void *baton){  struct compose_handler_baton *cb = baton;  assert(!cb->done || window == NULL);  assert(cb->trail && cb->trail->pool);  if (!cb->init && !window)    return SVN_NO_ERROR;  /* We should never get here if we've already expanded a     self-compressed window. */  assert(!cb->source_buf);  if (cb->window)    {      if (window && (window->sview_len == 0 || window->src_ops == 0))        {          /* This is a self-compressed window. Don't combine it with             the others, because the combiner may go quadratic. Instead,             expand it here and signal that the combination has             ended. */          apr_size_t source_len = window->tview_len;          assert(cb->window->sview_len == source_len);          cb->source_buf = apr_palloc(cb->window_pool, source_len);          svn_txdelta_apply_instructions(window, NULL,                                         cb->source_buf, &source_len);          cb->done = TRUE;        }      else        {          /* Combine the incoming window with whatever's in the baton. */          apr_pool_t *composite_pool = svn_pool_create(cb->trail->pool);          svn_txdelta_window_t *composite;          composite = svn_txdelta_compose_windows(window, cb->window,                                                  composite_pool);          svn_pool_destroy(cb->window_pool);          cb->window = composite;          cb->window_pool = composite_pool;          cb->done = (composite->sview_len == 0 || composite->src_ops == 0);        }    }  else if (window)    {      /* Copy the (first) window into the baton. */      apr_pool_t *window_pool = svn_pool_create(cb->trail->pool);      assert(cb->window_pool == NULL);      cb->window = svn_txdelta_window_dup(window, window_pool);      cb->window_pool = window_pool;      cb->done = (window->sview_len == 0 || window->src_ops == 0);    }  else    cb->done = TRUE;  cb->init = FALSE;  return SVN_NO_ERROR;}/* Read one delta window from REP[CUR_CHUNK] and push it at the   composition handler. */static svn_error_t *get_one_window(struct compose_handler_baton *cb,               svn_fs_t *fs,               representation_t *rep,               int cur_chunk){  svn_stream_t *wstream;  char diffdata[4096];   /* hunk of svndiff data */  svn_filesize_t off;    /* offset into svndiff data */  apr_size_t amt;        /* how much svndiff data to/was read */  const char *str_key;  apr_array_header_t *chunks = rep->contents.delta.chunks;  rep_delta_chunk_t *this_chunk, *first_chunk;  cb->init = TRUE;  if (chunks->nelts <= cur_chunk)    return compose_handler(NULL, cb);  /* Set up a window handling stream for the svndiff data. */  wstream = svn_txdelta_parse_svndiff(compose_handler, cb, TRUE,                                      cb->trail->pool);  /* First things first:  send the "SVN"{version} header through the     stream.  ### For now, we will just use the version specified     in the first chunk, and then verify that no chunks have a     different version number than the one used.  In the future,     we might simply convert chunks that use a different version     of the diff format -- or, heck, a different format     altogether -- to the format/version of the first chunk.  */  first_chunk = APR_ARRAY_IDX(chunks, 0, rep_delta_chunk_t*);  diffdata[0] = 'S';  diffdata[1] = 'V';  diffdata[2] = 'N';  diffdata[3] = (char) (first_chunk->version);  amt = 4;  SVN_ERR(svn_stream_write(wstream, diffdata, &amt));  /* FIXME: The stream write handler is borked; assert (amt == 4); */  /* Get this string key which holds this window's data.     ### todo: make sure this is an `svndiff' DIFF skel here. */  this_chunk = APR_ARRAY_IDX(chunks, cur_chunk, rep_delta_chunk_t*);  str_key = this_chunk->string_key;  /* Run through the svndiff data, at least as far as necessary. */  off = 0;  do    {      amt = sizeof(diffdata);      SVN_ERR(svn_fs_bdb__string_read(fs, str_key, diffdata,                                      off, &amt, cb->trail,                                       cb->trail->pool));      off += amt;      SVN_ERR(svn_stream_write(wstream, diffdata, &amt));    }  while (amt != 0);  SVN_ERR(svn_stream_close(wstream));  assert(!cb->init);  assert(cb->window != NULL);  assert(cb->window_pool != NULL);  return SVN_NO_ERROR;}/* Undeltify a range of data. DELTAS is the set of delta windows to   combine, FULLTEXT is the source text, CUR_CHUNK is the index of the   delta chunk we're starting from. OFFSET is the relative offset of   the requested data within the chunk; BUF and LEN are what we're   undeltifying to. */static svn_error_t *rep_undeltify_range(svn_fs_t *fs,                    apr_array_header_t *deltas,                    representation_t *fulltext,                    int cur_chunk,                    char *buf,                    apr_size_t offset,                    apr_size_t *len,                    trail_t *trail,                    apr_pool_t *pool){  apr_size_t len_read = 0;  do    {      struct compose_handler_baton cb = { 0 };      char *source_buf, *target_buf;      apr_size_t target_len;      int cur_rep;      cb.trail = trail;      cb.done = FALSE;      for (cur_rep = 0; !cb.done && cur_rep < deltas->nelts; ++cur_rep)        {          representation_t *const rep =            APR_ARRAY_IDX(deltas, cur_rep, representation_t*);          SVN_ERR(get_one_window(&cb, fs, rep, cur_chunk));        }      if (!cb.window)          /* That's it, no more source data is available. */          break;      /* The source view length should not be 0 if there are source         copy ops in the window. */      assert(cb.window->sview_len > 0 || cb.window->src_ops == 0);      /* cb.window is the combined delta window. Read the source text         into a buffer. */      if (cb.source_buf)        {          /* The combiner already created the source text from a             self-compressed window. */          source_buf = cb.source_buf;        }      else if (fulltext && cb.window->sview_len > 0 && cb.window->src_ops > 0)        {          apr_size_t source_len = cb.window->sview_len;          source_buf = apr_palloc(cb.window_pool, source_len);          SVN_ERR(svn_fs_bdb__string_read                  (fs, fulltext->contents.fulltext.string_key,                   source_buf, cb.window->sview_offset, &source_len,                    trail, pool));          if (source_len != cb.window->sview_len)            return svn_error_create                (SVN_ERR_FS_CORRUPT, NULL,                 _("Svndiff source length inconsistency"));        }      else        {          source_buf = NULL;    /* Won't read anything from here. */        }      if (offset > 0)        {          target_len = *len - len_read + offset;          target_buf = apr_palloc(cb.window_pool, target_len);        }      else        {          target_len = *len - len_read;          target_buf = buf;        }

⌨️ 快捷键说明

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