Fossil

Check-in [916cd4b8]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Use delta compression on elements of a single purgeevent in the graveyard. Record whether or not elements were originally private when moving them into the graveyard.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | DBP-workflow
Files: files | file ages | folders
SHA1: 916cd4b885eb1370b75fa11fff563e3396dd9685
User & Date: drh 2014-11-25 12:37:14
Context
2014-11-25
14:00
Add the "fossil purge cat" command for extracting individual artifacts from the graveyard. check-in: 4b902843 user: drh tags: DBP-workflow
12:37
Use delta compression on elements of a single purgeevent in the graveyard. Record whether or not elements were originally private when moving them into the graveyard. check-in: 916cd4b8 user: drh tags: DBP-workflow
04:19
In the "fossil purge BRANCHNAME" command, purge the entire branch, not just the last checkin of the branch. check-in: cbe1fa51 user: drh tags: DBP-workflow
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/purge.c.

38
39
40
41
42
43
44

45

46


47
48
49
50
51
52
53
..
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
...
101
102
103
104
105
106
107
108







109
110
111



112
113
114








115


116
117
118
119
120
121
122
...
223
224
225
226
227
228
229


230
231
232
233

234


235
236
237
238
239
240
241

242
243
244
245
246
247
248
...
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
static const char zPurgeInit[] = 
@ CREATE TABLE IF NOT EXISTS "%w".purgeevent(
@   peid INTEGER PRIMARY KEY,  -- Unique ID for the purge event
@   ctime DATETIME,            -- When purge occurred.  Seconds since 1970.
@   pnotes TEXT                -- Human-readable notes about the purge event
@ );
@ CREATE TABLE IF NOT EXISTS "%w".purgeitem(

@   peid INTEGER REFERENCES purgeevent ON DELETE CASCADE, -- Purge event

@   uuid TEXT NOT NULL,        -- SHA1 hash of the purged artifact


@   sz INT NOT NULL,           -- Uncompressed size of the purged artifact
@   data BLOB                  -- Compressed artifact content
@ );
;

/*
** This routine purges multiple artifacts from the repository, transfering
................................................................................
  const char *zTab,       /* TEMP table containing list of RIDS to be purged */
  const char *zNote       /* Text of the purgeevent.pnotes field */
){
  int peid = 0;                 /* New purgeevent ID */
  Stmt q;                       /* General-use prepared statement */

  assert( g.repositoryOpen );   /* Main database must already be open */
  add_content_sql_commands(g.db);
  db_begin_transaction();
  if( purge_baseline_out_from_under_delta(zTab) ){
    fossil_fatal("attempt to purge a baseline manifest without also purging "
                 "all of its deltas");
  }
  db_multi_exec(zPurgeInit /*works-like:"%w%w"*/, 
                db_name("repository"), db_name("repository"));
................................................................................
  db_prepare(&q, "SELECT rid FROM delta WHERE srcid IN \"%w\""
                 " AND rid NOT IN \"%w\"", zTab, zTab);
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0);
    content_undelta(rid);
    verify_before_commit(rid);
  }
  db_finalize(&q);







  db_multi_exec(
    "INSERT INTO purgeitem(peid,uuid,sz,data)"
    "  SELECT %d, uuid, size, compress(content(uuid))"



    "    FROM blob WHERE rid IN \"%w\"",
    peid, zTab
  );








  db_multi_exec("DELETE FROM blob WHERE rid IN \"%w\"", zTab);


  db_multi_exec("DELETE FROM event WHERE objid IN \"%w\"", zTab);
  db_multi_exec("DELETE FROM private WHERE rid IN \"%w\"", zTab);
  db_multi_exec("DELETE FROM mlink WHERE mid IN \"%w\"", zTab);
  db_multi_exec("DELETE FROM plink WHERE pid IN \"%w\"", zTab);
  db_multi_exec("DELETE FROM plink WHERE cid IN \"%w\"", zTab);
  db_multi_exec("DELETE FROM leaf WHERE rid IN \"%w\"", zTab);
  db_multi_exec("DELETE FROM phantom WHERE rid IN \"%w\"", zTab);
................................................................................
/*
** Display the content of a single purge event.
*/
static void purge_event_content(int peid){
  Stmt q;
  sqlite3_int64 sz1 = 0;
  sqlite3_int64 sz2 = 0;


  db_prepare(&q, "SELECT uuid, sz, length(data) FROM purgeitem WHERE peid=%d",
             peid);
  while( db_step(&q)==SQLITE_ROW ){
    fossil_print("  %s %10d %10d\n",

                 db_column_text(&q,0),


                 db_column_int(&q,1),
                 db_column_int(&q,2));
    sz1 += db_column_int(&q,1);
    sz2 += db_column_int(&q,2);
  }
  db_finalize(&q);
  fossil_print("  %40s %10lld %10lld\n", "Total:", sz1, sz2);

}

/*
** COMMAND: purge
**
** The purge command is used to remove content from a repository into a
** "graveyard" and also to show manage the graveyard and optionally restored
................................................................................
**
**      Restore the content previously removed by purge ID.
**
**   fossil purge [checkin] TAGS... [--explain]
**
**      Move the checkins identified by TAGS and all of their descendants
**      out of the repository and into the graveyard.  If a TAG is a branch
        name then it means all the checkins on that branch.  If the --explain
        option appears, then the repository and graveyard are unchanged and
**      an explaination of what would have happened is shown instead.
**
** SUMMARY:
**   fossil purge [checkin] TAGS... [--explain]
**   fossil purge list
**   fossil purge undo ID
*/







>

>

>
>







 







<







 








>
>
>
>
>
>
>

|
<
>
>
>



>
>
>
>
>
>
>
>

>
>







 







>
>
|
<

|
>
|
>
>
|
|
|
|


<
>







 







|
|







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
..
86
87
88
89
90
91
92

93
94
95
96
97
98
99
...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
...
245
246
247
248
249
250
251
252
253
254

255
256
257
258
259
260
261
262
263
264
265
266

267
268
269
270
271
272
273
274
...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
static const char zPurgeInit[] = 
@ CREATE TABLE IF NOT EXISTS "%w".purgeevent(
@   peid INTEGER PRIMARY KEY,  -- Unique ID for the purge event
@   ctime DATETIME,            -- When purge occurred.  Seconds since 1970.
@   pnotes TEXT                -- Human-readable notes about the purge event
@ );
@ CREATE TABLE IF NOT EXISTS "%w".purgeitem(
@   piid INTEGER PRIMARY KEY,  -- ID for the purge item
@   peid INTEGER REFERENCES purgeevent ON DELETE CASCADE, -- Purge event
@   orid INTEGER,              -- Original RID before purged 
@   uuid TEXT NOT NULL,        -- SHA1 hash of the purged artifact
@   srcid INTEGER,             -- Basis purgeitem for delta compression
@   isPrivate BOOLEAN,         -- True if artifact was originally private
@   sz INT NOT NULL,           -- Uncompressed size of the purged artifact
@   data BLOB                  -- Compressed artifact content
@ );
;

/*
** This routine purges multiple artifacts from the repository, transfering
................................................................................
  const char *zTab,       /* TEMP table containing list of RIDS to be purged */
  const char *zNote       /* Text of the purgeevent.pnotes field */
){
  int peid = 0;                 /* New purgeevent ID */
  Stmt q;                       /* General-use prepared statement */

  assert( g.repositoryOpen );   /* Main database must already be open */

  db_begin_transaction();
  if( purge_baseline_out_from_under_delta(zTab) ){
    fossil_fatal("attempt to purge a baseline manifest without also purging "
                 "all of its deltas");
  }
  db_multi_exec(zPurgeInit /*works-like:"%w%w"*/, 
                db_name("repository"), db_name("repository"));
................................................................................
  db_prepare(&q, "SELECT rid FROM delta WHERE srcid IN \"%w\""
                 " AND rid NOT IN \"%w\"", zTab, zTab);
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0);
    content_undelta(rid);
    verify_before_commit(rid);
  }
  db_finalize(&q);
  db_prepare(&q, "SELECT rid FROM delta WHERE rid IN \"%w\""
                 " AND srcid NOT IN \"%w\"", zTab, zTab);
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0);
    content_undelta(rid);
  }
  db_finalize(&q);
  db_multi_exec(
    "INSERT INTO purgeitem(peid,orid,uuid,sz,isPrivate,data)"

    "  SELECT %d, rid, uuid, size,"
    "    EXISTS(SELECT 1 FROM private WHERE private.rid=blob.rid),"
    "    content"
    "    FROM blob WHERE rid IN \"%w\"",
    peid, zTab
  );
  db_multi_exec(
    "UPDATE purgeitem"
    "   SET srcid=(SELECT piid FROM purgeitem px, delta"
                  " WHERE px.orid=delta.srcid"
                  "   AND delta.rid=purgeitem.orid)"
    " WHERE peid=%d",
    peid
  );
  db_multi_exec("DELETE FROM blob WHERE rid IN \"%w\"", zTab);
  db_multi_exec("DELETE FROM delta WHERE rid IN \"%w\"", zTab);
  db_multi_exec("DELETE FROM delta WHERE srcid IN \"%w\"", zTab);
  db_multi_exec("DELETE FROM event WHERE objid IN \"%w\"", zTab);
  db_multi_exec("DELETE FROM private WHERE rid IN \"%w\"", zTab);
  db_multi_exec("DELETE FROM mlink WHERE mid IN \"%w\"", zTab);
  db_multi_exec("DELETE FROM plink WHERE pid IN \"%w\"", zTab);
  db_multi_exec("DELETE FROM plink WHERE cid IN \"%w\"", zTab);
  db_multi_exec("DELETE FROM leaf WHERE rid IN \"%w\"", zTab);
  db_multi_exec("DELETE FROM phantom WHERE rid IN \"%w\"", zTab);
................................................................................
/*
** Display the content of a single purge event.
*/
static void purge_event_content(int peid){
  Stmt q;
  sqlite3_int64 sz1 = 0;
  sqlite3_int64 sz2 = 0;
  db_prepare(&q, "SELECT piid, substr(uuid,1,16), srcid, isPrivate,"
                 "       sz, length(data)"
                 " FROM purgeitem WHERE peid=%d", peid);

  while( db_step(&q)==SQLITE_ROW ){
    fossil_print("     %5d %s %4s %c %10d %10d\n",
       db_column_int(&q,0),
       db_column_text(&q,1),
       db_column_text(&q,2),
       db_column_int(&q,3) ? 'P' : ' ',
       db_column_int(&q,4),
       db_column_int(&q,5));
    sz1 += db_column_int(&q,4);
    sz2 += db_column_int(&q,5);
  }
  db_finalize(&q);

  fossil_print("%.11c%16s%.8c%10lld %10lld\n", ' ', "Total:", ' ', sz1, sz2);
}

/*
** COMMAND: purge
**
** The purge command is used to remove content from a repository into a
** "graveyard" and also to show manage the graveyard and optionally restored
................................................................................
**
**      Restore the content previously removed by purge ID.
**
**   fossil purge [checkin] TAGS... [--explain]
**
**      Move the checkins identified by TAGS and all of their descendants
**      out of the repository and into the graveyard.  If a TAG is a branch
**      name then it means all the checkins on that branch.  If the --explain
**      option appears, then the repository and graveyard are unchanged and
**      an explaination of what would have happened is shown instead.
**
** SUMMARY:
**   fossil purge [checkin] TAGS... [--explain]
**   fossil purge list
**   fossil purge undo ID
*/

Changes to src/schema.c.

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
@   rcvid INTEGER,                  -- Origin of this record
@   size INTEGER,                   -- Size of content. -1 for a phantom.
@   uuid TEXT UNIQUE NOT NULL,      -- SHA1 hash of the content
@   content BLOB,                   -- Compressed content of this record
@   CHECK( length(uuid)==40 AND rid>0 )
@ );
@ CREATE TABLE delta(
@   rid INTEGER PRIMARY KEY,                 -- BLOB entry where content is delta-compressed
@   srcid INTEGER NOT NULL REFERENCES blob   -- BLOB entry holding delta baseline
@ );
@ CREATE INDEX delta_i1 ON delta(srcid);
@
@ -------------------------------------------------------------------------
@ -- The BLOB and DELTA tables above hold the "global state" of a Fossil
@ -- project; the stuff that is normally exchanged during "sync".  The
@ -- "local state" of a repository is contained in the remaining tables of







|
|







78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
@   rcvid INTEGER,                  -- Origin of this record
@   size INTEGER,                   -- Size of content. -1 for a phantom.
@   uuid TEXT UNIQUE NOT NULL,      -- SHA1 hash of the content
@   content BLOB,                   -- Compressed content of this record
@   CHECK( length(uuid)==40 AND rid>0 )
@ );
@ CREATE TABLE delta(
@   rid INTEGER PRIMARY KEY,                 -- BLOB that is delta-compressed 
@   srcid INTEGER NOT NULL REFERENCES blob   -- Baseline for delta-compression
@ );
@ CREATE INDEX delta_i1 ON delta(srcid);
@
@ -------------------------------------------------------------------------
@ -- The BLOB and DELTA tables above hold the "global state" of a Fossil
@ -- project; the stuff that is normally exchanged during "sync".  The
@ -- "local state" of a repository is contained in the remaining tables of