~svn/ubuntu/raring/subversion/ppa

« back to all changes in this revision

Viewing changes to contrib/server-side/backup-recipe.sh

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-12-05 01:26:14 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051205012614-qom4xfypgtsqc2xq
Tags: 1.2.3dfsg1-3ubuntu1
Merge with the final Debian release of 1.2.3dfsg1-3, bringing in
fixes to the clean target, better documentation of the libdb4.3
upgrade and build fixes to work with swig1.3_1.3.27.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/bin/sh
 
2
 
 
3
###########################################################################
 
4
#                                                                         #
 
5
#  This shell script demonstrates a backup/restore recipe for live        #
 
6
#  Subversion repositories, using a standard full+incrementals process.   #
 
7
#                                                                         #
 
8
#  This script is intended only as an example; the idea is that you       #
 
9
#  can read over it, understand how it works (it's extensively commented) #
 
10
#  and then implement real backup and restore scripts based on this       #
 
11
#  recipe.                                                                #
 
12
#                                                                         #
 
13
#  To reiterate: this is *not* a backup and restore solution.  It's       #
 
14
#  really just documentation, in the form of code with comments.          #
 
15
#                                                                         #
 
16
#  If you do implement your own scripts based on the recipe here, and     #
 
17
#  your implementations are generic enough to be generally useful,        #
 
18
#  please post them to dev@subversion.tigris.org.  It would be great if   #
 
19
#  we could offer a real solution, and not just a description of one.     #
 
20
#                                                                         #
 
21
#  This recipe is distilled from the Berkeley DB documentation, see       #
 
22
#  http://www.sleepycat.com/docs/ref/transapp/archival.html.              #
 
23
#                                                                         #
 
24
#  See also http://www.sleepycat.com/docs/ref/transapp/reclimit.html for  #
 
25
#  for possible problems using standard 'cp' in this recipe.              #
 
26
#                                                                         #
 
27
###########################################################################
 
28
 
 
29
# High-level overview of the full backup recipe:
 
30
 
31
#    1. Ask BDB's db_archive for a list of unused log files.
 
32
#
 
33
#    2. Copy the entire db/ dir to the backup area.
 
34
#
 
35
#    3. Recopy all the logfiles to the backup area.  There may be more
 
36
#       logfiles now than there were when step (1) ran.
 
37
#
 
38
#    4. Remove the logfiles listed as inactive in step (1) from the
 
39
#       repository, though not from the backup.
 
40
#    
 
41
# High-level overview of the incremental backup recipe:
 
42
#
 
43
#    1. Just copy the Berkeley logfiles to a backup area.
 
44
#    
 
45
# High-level overview of the restoration recipe:
 
46
#
 
47
#    1. Copy all the datafiles and logfiles back to the repository, in
 
48
#       the same order they were backed up.
 
49
#
 
50
#    2. Run Berkeley's "catastrophic recovery" command on the repository.
 
51
#
 
52
# That's it.  Here we go...
 
53
 
 
54
# You might need to customize some of these paths.
 
55
SVN=svn
 
56
SVNADMIN=svnadmin
 
57
SVNLOOK=svnlook
 
58
# See http://www.sleepycat.com/docs/utility/db_archive.html:
 
59
DB_ARCHIVE=/usr/local/BerkeleyDB.4.2/bin/db_archive
 
60
# See http://www.sleepycat.com/docs/utility/db_recover.html:
 
61
DB_RECOVER=/usr/local/BerkeleyDB.4.2/bin/db_recover
 
62
 
 
63
# This is just source data to generate repository activity.
 
64
# Any binary file of about 64k will do, it doesn't have to be /bin/ls.
 
65
DATA_BLOB=/bin/ls
 
66
 
 
67
# You shouldn't need to customize below here.
 
68
SANDBOX=`pwd`/backups-test-tmp
 
69
FULL_BACKUPS=${SANDBOX}/full
 
70
INCREMENTAL_PREFIX=${SANDBOX}/incremental-logs
 
71
RECORDS=${SANDBOX}/records
 
72
PROJ=myproj
 
73
REPOS=${PROJ}-repos
 
74
 
 
75
rm -rf ${SANDBOX}
 
76
mkdir ${SANDBOX}
 
77
mkdir ${RECORDS}
 
78
 
 
79
cd ${SANDBOX}
 
80
 
 
81
${SVNADMIN} create --bdb-log-keep ${REPOS}
 
82
${SVN} co file://${SANDBOX}/${REPOS} wc
 
83
 
 
84
cd wc
 
85
 
 
86
# Put in enough data for us to exercise the logfiles.
 
87
cp ${DATA_BLOB} ./a1
 
88
cp ${DATA_BLOB} ./b1
 
89
cp ${DATA_BLOB} ./c1
 
90
${SVN} -q add a1 b1 c1
 
91
${SVN} -q ci -m "Initial add."
 
92
 
 
93
echo "Created test data."
 
94
 
 
95
cd ..
 
96
 
 
97
# Exercise the logfiles by moving data around a lot.  Note that we
 
98
# avoid adds-with-history, since those cause much less Berkeley
 
99
# activity than plain adds.
 
100
#
 
101
# Call this from the parent of wc, that is, with $SANDBOX as CWD.
 
102
# Pass one argument, a number, indicating how many cycles of exercise
 
103
# you want.  The more cycles, the more logfiles will be generated.
 
104
# The ratio is about two cycles per logfile.
 
105
function exercise
 
106
{
 
107
   limit=${1}
 
108
 
 
109
   saved_cwd=`pwd`
 
110
   cd ${SANDBOX}/wc
 
111
 
 
112
   echo ""
 
113
   i=1
 
114
   while [ ${i} -le ${limit} ]; do
 
115
     mv a1 a2
 
116
     mv b1 b2
 
117
     mv c1 c2
 
118
     ${SVN} -q rm a1 b1 c1
 
119
     ${SVN} -q add a2 b2 c2
 
120
     ${SVN} -q ci -m "Move 1s to 2s, but not as cheap copies."
 
121
 
 
122
     mv a2 a1
 
123
     mv b2 b1
 
124
     mv c2 c1
 
125
     ${SVN} -q rm a2 b2 c2
 
126
     ${SVN} -q add a1 b1 c1
 
127
     ${SVN} -q ci -m "Move 2s back to 1s, same way."
 
128
 
 
129
     echo "Exercising repository, pass ${i} of ${limit}."
 
130
     i=`dc -e "${i} 1 + p"`
 
131
   done
 
132
   echo ""
 
133
 
 
134
   cd ${saved_cwd}
 
135
}
 
136
 
 
137
# Generate some logfile activity.
 
138
exercise 10
 
139
 
 
140
# Do a full backup.
 
141
head=`${SVNLOOK} youngest ${REPOS}`
 
142
echo "Starting full backup (at r${head})..."
 
143
mkdir ${FULL_BACKUPS}
 
144
mkdir ${FULL_BACKUPS}/${PROJ}
 
145
mkdir ${FULL_BACKUPS}/${PROJ}/repos
 
146
mkdir ${FULL_BACKUPS}/${PROJ}/logs
 
147
cd ${REPOS}/db
 
148
${DB_ARCHIVE} > ${RECORDS}/${PROJ}-full-backup-inactive-logfiles
 
149
cd ../..
 
150
cp -a ${REPOS} ${FULL_BACKUPS}/${PROJ}/repos/
 
151
cd ${REPOS}/db
 
152
for logfile in `${DB_ARCHIVE} -l`; do
 
153
  # For maximum paranoia, we want repository activity *while* we're
 
154
  # making the full backup.
 
155
  exercise 5
 
156
  cp ${logfile} ${FULL_BACKUPS}/${PROJ}/logs
 
157
done
 
158
cat ${RECORDS}/${PROJ}-full-backup-inactive-logfiles | xargs rm -f
 
159
cd ../..
 
160
echo "Full backup completed (r${head} was head when started)."
 
161
 
 
162
# Do the incremental backups for a nominal week.
 
163
for day in 1 2 3 4 5 6; do
 
164
  exercise 5
 
165
  head=`${SVNLOOK} youngest ${REPOS}`
 
166
  echo "Starting incremental backup ${day} (at r${head})..."
 
167
  mkdir ${INCREMENTAL_PREFIX}-${day}
 
168
  mkdir ${INCREMENTAL_PREFIX}-${day}/${PROJ}
 
169
  cd ${REPOS}/db
 
170
  ${DB_ARCHIVE} > ${RECORDS}/${PROJ}-incr-backup-${day}-inactive-logfiles
 
171
  for logfile in `${DB_ARCHIVE} -l`; do
 
172
    # For maximum paranoia, we want repository activity *while* we're
 
173
    # making the incremental backup.  But if we did commits with each
 
174
    # logfile copy, this script would be quite slow (Fibonacci effect). 
 
175
    # So we only exercise on the last two "days" of incrementals.
 
176
    if [ ${day} -ge 5 ]; then
 
177
      exercise 3
 
178
    fi
 
179
    cp ${logfile} ${INCREMENTAL_PREFIX}-${day}/${PROJ}
 
180
  done
 
181
  cat ${RECORDS}/${PROJ}-incr-backup-${day}-inactive-logfiles | xargs rm -f
 
182
  cd ../..
 
183
  echo "Incremental backup ${day} done (r${head} was head when started)."
 
184
done
 
185
 
 
186
# The last revision a restoration is guaranteed to contain is whatever
 
187
# was head at the start of the last incremental backup.
 
188
last_guaranteed_rev=${head}
 
189
 
 
190
# Make the repository vanish, so we can restore it.
 
191
mv ${REPOS} was_${REPOS}
 
192
 
 
193
echo ""
 
194
echo "Oliver Cromwell has destroyed the repository!  Restoration coming
 
195
up..."
 
196
echo ""
 
197
 
 
198
# Restore.
 
199
#
 
200
# After copying the full repository backup over, we remove the shared
 
201
# memory segments and the dav/* stuff.  Recovery recreates the shmem
 
202
# segments, and anything in dav/* is certainly obsolete if we're doing
 
203
# a restore.
 
204
#
 
205
# Note that we use db_recover instead of 'svnadmin recover'.  This is
 
206
# because we want to pass the -c ('catastrophic') flag to db_recover.
 
207
# As of Subversion 1.0.x, there is no '--catastrophic' flag to
 
208
# 'svnadmin recover', unfortunately.
 
209
cp -a ${FULL_BACKUPS}/${PROJ}/repos/${REPOS} .
 
210
cp -a ${FULL_BACKUPS}/${PROJ}/logs/* ${REPOS}/db
 
211
rm -rf ${REPOS}/db/__db*
 
212
rm -rf ${REPOS}/dav/*
 
213
cd ${REPOS}/db
 
214
${DB_RECOVER} -ce
 
215
cd ../..
 
216
head=`${SVNLOOK} youngest ${REPOS}`
 
217
echo ""
 
218
echo "(Restored from full backup to r${head}...)"
 
219
for day in 1 2 3 4 5 6; do
 
220
  cd ${REPOS}/db
 
221
  cp ${INCREMENTAL_PREFIX}-${day}/${PROJ}/* .
 
222
  ${DB_RECOVER} -ce
 
223
  cd ../..
 
224
  head=`${SVNLOOK} youngest ${REPOS}`
 
225
  echo "(Restored from incremental-${day} to r${head}...)"
 
226
done
 
227
echo ""
 
228
echo "Restoration complete.  All hail the King."
 
229
 
 
230
# Verify the restoration.
 
231
was_head=`${SVNLOOK} youngest was_${REPOS}`
 
232
restored_head=`${SVNLOOK} youngest ${REPOS}`
 
233
echo ""
 
234
echo "Highest revision in original repository:  ${was_head}"
 
235
echo "Highest revision restored:                ${restored_head}"
 
236
echo ""
 
237
echo "(It's okay if restored is less than original, even much less.)"
 
238
 
 
239
if [ ${restored_head} -lt ${last_guaranteed_rev} ]; then
 
240
   echo ""
 
241
   echo "Restoration failed because r${restored_head} is too low --"
 
242
   echo "should have restored to at least r${last_guaranteed_rev}."
 
243
   exit 1
 
244
fi
 
245
 
 
246
# Looks like we restored at least to the minimum required revision.
 
247
# Let's do some spot checks, though.
 
248
 
 
249
echo ""
 
250
echo "Comparing logs up to r${restored_head} for both repositories..."
 
251
${SVN} log -v -r1:${restored_head} file://`pwd`/was_${REPOS} > a
 
252
${SVN} log -v -r1:${restored_head} file://`pwd`/${REPOS}     > b
 
253
if cmp a b; then
 
254
  echo "Done comparing logs."
 
255
else
 
256
  echo "Log comparison failed -- restored repository is not right."
 
257
  exit 1
 
258
fi
 
259
 
 
260
echo ""
 
261
echo "Comparing r${restored_head} exported trees from both repositories..."
 
262
${SVN} -q export -r${restored_head} file://`pwd`/was_${REPOS} orig-export
 
263
${SVN} -q export -r${restored_head} file://`pwd`/${REPOS} restored-export
 
264
if diff -q -r orig-export restored-export; then
 
265
  echo "Done comparing r${restored_head} exported trees."
 
266
else
 
267
  echo "Recursive diff failed -- restored repository is not right."
 
268
fi
 
269
 
 
270
echo ""
 
271
echo "Done."