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

📄 reps-strings.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
{  struct rep_read_baton *rb;  SVN_ERR(rep_read_get_baton(&rb, fs, rep_key, use_trail_for_reads,                             trail, pool));  *rs_p = svn_stream_create(rb, pool);  svn_stream_set_read(*rs_p, rep_read_contents);  return SVN_NO_ERROR;}/* Clear the contents of REP_KEY, so that it represents the empty   string, as part of TRAIL.  TXN_ID is the id of the Subversion   transaction under which this occurs.  If REP_KEY is not mutable,   return the error SVN_ERR_FS_REP_NOT_MUTABLE.  */static svn_error_t *rep_contents_clear(svn_fs_t *fs,                   const char *rep_key,                   const char *txn_id,                   trail_t *trail,                   apr_pool_t *pool){  representation_t *rep;  const char *str_key;  SVN_ERR(svn_fs_bdb__read_rep(&rep, fs, rep_key, trail, pool));  /* Make sure it's mutable. */  if (! rep_is_mutable(rep, txn_id))    return svn_error_createf      (SVN_ERR_FS_REP_NOT_MUTABLE, NULL,       _("Rep '%s' is not mutable"), rep_key);  assert(rep->kind == rep_kind_fulltext);  /* If rep has no string, just return success.  Else, clear the     underlying string.  */  str_key = rep->contents.fulltext.string_key;  if (str_key && *str_key)    {      SVN_ERR(svn_fs_bdb__string_clear(fs, str_key, trail, pool));      memcpy(rep->checksum, svn_md5_empty_string_digest(),             APR_MD5_DIGESTSIZE);      SVN_ERR(svn_fs_bdb__write_rep(fs, rep_key, rep, trail, pool));    }  return SVN_NO_ERROR;}svn_error_t *svn_fs_base__rep_contents_write_stream(svn_stream_t **ws_p,                                       svn_fs_t *fs,                                       const char *rep_key,                                       const char *txn_id,                                       svn_boolean_t use_trail_for_writes,                                       trail_t *trail,                                       apr_pool_t *pool){  struct rep_write_baton *wb;  /* Clear the current rep contents (free mutability check!). */  SVN_ERR(rep_contents_clear(fs, rep_key, txn_id, trail, pool));  /* Now, generate the write baton and stream. */  wb = rep_write_get_baton(fs, rep_key, txn_id,                           use_trail_for_writes ? trail : NULL, pool);  *ws_p = svn_stream_create(wb, pool);  svn_stream_set_write(*ws_p, rep_write_contents);  svn_stream_set_close(*ws_p, rep_write_close_contents);  return SVN_NO_ERROR;}/*** Deltified storage. ***//* Baton for svn_write_fn_t write_string_set(). */struct write_svndiff_strings_baton{  /* The fs where lives the string we're writing. */  svn_fs_t *fs;  /* The key of the string we're writing to.  Typically this is     initialized to NULL, so svn_fs_base__string_append() can fill in a     value. */  const char *key;  /* The amount of txdelta data written to the current     string-in-progress. */  apr_size_t size;  /* The amount of svndiff header information we've written thus far     to the strings table. */  apr_size_t header_read;  /* The version number of the svndiff data written.  ### You'd better     not count on this being populated after the first chunk is sent     through the interface, since it lives at the 4th byte of the     stream. */  apr_byte_t version;  /* The trail we're writing in. */  trail_t *trail;};/* Function of type `svn_write_fn_t', for writing to a collection of   strings; BATON is `struct write_svndiff_strings_baton *'.   On the first call, BATON->key is null.  A new string key in   BATON->fs is chosen and stored in BATON->key; each call appends   *LEN bytes from DATA onto the string.  *LEN is never changed; if   the write fails to write all *LEN bytes, an error is returned.   BATON->size is used to track the total amount of data written via   this handler, and must be reset by the caller to 0 when appropriate.  */static svn_error_t *write_svndiff_strings(void *baton, const char *data, apr_size_t *len){  struct write_svndiff_strings_baton *wb = baton;  const char *buf = data;  apr_size_t nheader = 0;  /* If we haven't stripped all the header information from this     stream yet, keep stripping.  If someone sends a first window     through here that's shorter than 4 bytes long, this will probably     cause a nuclear reactor meltdown somewhere in the American     midwest.  */  if (wb->header_read < 4)    {      nheader = 4 - wb->header_read;      *len -= nheader;      buf += nheader;      wb->header_read += nheader;      /* If we have *now* read the full 4-byte header, check that         least byte for the version number of the svndiff format. */      if (wb->header_read == 4)        wb->version = *(buf - 1);    }  /* Append to the current string we're writing (or create a new one     if WB->key is NULL). */  SVN_ERR(svn_fs_bdb__string_append(wb->fs, &(wb->key), *len,                                    buf, wb->trail, wb->trail->pool));  /* Make sure we (still) have a key. */  if (wb->key == NULL)    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,                            _("Failed to get new string key"));  /* Restore *LEN to the value it *would* have been were it not for     header stripping. */  *len += nheader;  /* Increment our running total of bytes written to this string. */  wb->size += *len;  return SVN_NO_ERROR;}typedef struct window_write_t{  const char *key; /* string key for this window */  apr_size_t svndiff_len; /* amount of svndiff data written to the string */  svn_filesize_t text_off; /* offset of fulltext represented by this window */  apr_size_t text_len; /* amount of fulltext data represented by this window */} window_write_t;svn_error_t *svn_fs_base__rep_deltify(svn_fs_t *fs,                         const char *target,                         const char *source,                         trail_t *trail,                         apr_pool_t *pool){  base_fs_data_t *bfd = fs->fsap_data;  svn_stream_t *source_stream; /* stream to read the source */  svn_stream_t *target_stream; /* stream to read the target */  svn_txdelta_stream_t *txdelta_stream; /* stream to read delta windows  */  /* window-y things, and an array to track them */  window_write_t *ww;  apr_array_header_t *windows;  /* stream to write new (deltified) target data and its baton */  svn_stream_t *new_target_stream;  struct write_svndiff_strings_baton new_target_baton;  /* window handler/baton for writing to above stream */  svn_txdelta_window_handler_t new_target_handler;  void *new_target_handler_baton;  /* yes, we do windows */  svn_txdelta_window_t *window;  /* The current offset into the fulltext that our window is about to     write.  This doubles, after all windows are written, as the     total size of the svndiff data for the deltification process. */  svn_filesize_t tview_off = 0;  /* The total amount of diff data written while deltifying. */  svn_filesize_t diffsize = 0;  /* TARGET's original string keys */  apr_array_header_t *orig_str_keys;  /* The digest for the representation's fulltext contents. */  unsigned char rep_digest[APR_MD5_DIGESTSIZE];  /* MD5 digest */  const unsigned char *digest;  /* pool for holding the windows */  apr_pool_t *wpool;  /* Paranoia: never allow a rep to be deltified against itself,     because then there would be no fulltext reachable in the delta     chain, and badness would ensue.  */  if (strcmp(target, source) == 0)    return svn_error_createf      (SVN_ERR_FS_CORRUPT, NULL,       _("Attempt to deltify '%s' against itself"),       target);  /* Set up a handler for the svndiff data, which will write each     window to its own string in the `strings' table. */  new_target_baton.fs = fs;  new_target_baton.trail = trail;  new_target_baton.header_read = FALSE;  new_target_stream = svn_stream_create(&new_target_baton, pool);  svn_stream_set_write(new_target_stream, write_svndiff_strings);  /* Get streams to our source and target text data. */  SVN_ERR(svn_fs_base__rep_contents_read_stream(&source_stream, fs, source,                                                TRUE, trail, pool));  SVN_ERR(svn_fs_base__rep_contents_read_stream(&target_stream, fs, target,                                                TRUE, trail, pool));  /* Setup a stream to convert the textdelta data into svndiff windows. */  svn_txdelta(&txdelta_stream, source_stream, target_stream, pool);  if (bfd->format >= SVN_FS_BASE__MIN_SVNDIFF1_FORMAT)    svn_txdelta_to_svndiff2(&new_target_handler, &new_target_handler_baton,                            new_target_stream, 1, pool);  else    svn_txdelta_to_svndiff2(&new_target_handler, &new_target_handler_baton,                            new_target_stream, 0, pool);  /* subpool for the windows */  wpool = svn_pool_create(pool);  /* Now, loop, manufacturing and dispatching windows of svndiff data. */  windows = apr_array_make(pool, 1, sizeof(ww));  do    {      /* Reset some baton variables. */      new_target_baton.size = 0;      new_target_baton.key = NULL;      /* Free the window. */      svn_pool_clear(wpool);      /* Fetch the next window of txdelta data. */      SVN_ERR(svn_txdelta_next_window(&window, txdelta_stream, wpool));      /* Send off this package to be written as svndiff data. */      SVN_ERR(new_target_handler(window, new_target_handler_baton));      if (window)        {          /* Add a new window description to our array. */          ww = apr_pcalloc(pool, sizeof(*ww));          ww->key = new_target_baton.key;          ww->svndiff_len = new_target_baton.size;          ww->text_off = tview_off;          ww->text_len = window->tview_len;          (*((window_write_t **)(apr_array_push(windows)))) = ww;          /* Update our recordkeeping variables. */          tview_off += window->tview_len;          diffsize += ww->svndiff_len;        }    } while (window);  svn_pool_destroy(wpool);  /* Having processed all the windows, we can query the MD5 digest     from the stream.  */  digest = svn_txdelta_md5_digest(txdelta_stream);  if (! digest)    return svn_error_createf      (SVN_ERR_DELTA_MD5_CHECKSUM_ABSENT, NULL,       _("Failed to calculate MD5 digest for '%s'"),       source);  /* Construct a list of the strings used by the old representation so     that we can delete them later.  While we are here, if the old     representation was a fulltext, check to make sure the delta we're     replacing it with is actually smaller.  (Don't perform this check     if we're replacing a delta; in that case, we're going for a time     optimization, not a space optimization.)  */  {    representation_t *old_rep;    const char *str_key;    SVN_ERR(svn_fs_bdb__read_rep(&old_rep, fs, target, trail, pool));    if (old_rep->kind == rep_kind_fulltext)      {        svn_filesize_t old_size = 0;        str_key = old_rep->contents.fulltext.string_key;        SVN_ERR(svn_fs_bdb__string_size(&old_size, fs, str_key,                                         trail, pool));        orig_str_keys = apr_array_make(pool, 1, sizeof(str_key));        (*((const char **)(apr_array_push(orig_str_keys)))) = str_key;        /* If the new data is NOT an space optimization, destroy the           string(s) we created, and get outta here. */        if (diffsize >= old_size)          {            int i;            for (i = 0; i < windows->nelts; i++)              {                ww = ((window_write_t **) windows->elts)[i];                SVN_ERR(svn_fs_bdb__string_delete(fs, ww->key, trail, pool));              }            return SVN_NO_ERROR;          }      }    else if (old_rep->kind == rep_kind_delta)      SVN_ERR(delta_string_keys(&orig_str_keys, old_rep, pool));    else /* unknown kind */      return UNKNOWN_NODE_KIND(target);    /* Save the checksum, since the new rep needs it. */    memcpy(rep_digest, old_rep->checksum, APR_MD5_DIGESTSIZE);  }  /* Hook the new strings we wrote into the rest of the filesystem by     building a new representation to replace our old one. */  {    representation_t new_rep;    rep_delta_chunk_t *chunk;    apr_array_header_t *chunks;    int i;    new_rep.kind = rep_kind_delta;    new_rep.txn_id = NULL;    /* Migrate the old rep's checksum to the new rep. */    memcpy(new_rep.checksum, rep_digest, APR_MD5_DIGESTSIZE);    chunks = apr_array_make(pool, windows->nelts, sizeof(chunk));    /* Loop through the windows we wrote, creating and adding new       chunks to the representation. */    for (i = 0; i < windows->nelts; i++)      {        ww = ((window_write_t **) windows->elts)[i];        /* Allocate a chunk and its window */        chunk = apr_palloc(pool, sizeof(*chunk));        chunk->offset = ww->text_off;        /* Populate the window */        chunk->version = new_target_baton.version;        chunk->string_key = ww->key;        chunk->size = ww->text_len;        chunk->rep_key = source;        /* Add this chunk to the array. */        (*((rep_delta_chunk_t **)(apr_array_push(chunks)))) = chunk;      }    /* Put the chunks array into the representation. */    new_rep.contents.delta.chunks = chunks;    /* Write out the new representation. */    SVN_ERR(svn_fs_bdb__write_rep(fs, target, &new_rep, trail, pool));    /* Delete the original pre-deltified strings. */    SVN_ERR(delete_strings(orig_str_keys, fs, trail, pool));  }  return SVN_NO_ERROR;}

⌨️ 快捷键说明

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