[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Bulk copying locks

From: Philip Martin <philip.martin_at_wandisco.com>
Date: Thu, 24 Sep 2015 12:48:35 +0100

Bulk copying locks is a similar issue to bulk copying revprops. There
is no easy way to bulk copy locks from a repository to a copy of the
repository (even hotcopy has problems: issue 3750).

As with revprops I can write a script using the bindings (see below).
However this script is less useful that the one to copy revprops. It
has a performance problem when the number of locks is large due to the
O(N^2) behaviour of the index. It may be possible to mitigate this by
collecting the locks and using the _many API although I suspect the
bindings need to be enhanced first.

Another problem is that Subversion's current API doesn't allow setting
the lock's creation date, the date is always set from the local clock.
That means there is no way to write code using the current API that will
copy locks. It is possible that the best way to copy locks is to do an
OS copy of the entire locks subdir from an offline repository and rely
on the fact that the on-disk representation remains valid across FSFS
formats.

We should have a better method. At a minimum we need a new FS API that
allows the lock's creation date to be specified.

We don't have dump/load support for locks but we probably don't need it.
'svnadmin lslocks' is effectively a dump for locks. The lock order is
lexical MD5 of the path, which is probably not optimal for adding locks
in a bulk load. Getting a better order might be tricky as is deciding
how to break the list into batches. As with revprops making sure the FS
layer can detect an add that doesn't change anything and then avoid all
disk writes will probably help.

#!/usr/bin/python

import sys
from svn import core, fs, repos

src_path = core.svn_path_canonicalize(sys.argv[1])
dst_path = core.svn_path_canonicalize(sys.argv[2])
src_repo = repos.open(src_path)
dst_repo = repos.open(dst_path)
src_fs = repos.fs(src_repo)
dst_fs = repos.fs(dst_repo)
dst_head = fs.youngest_rev(dst_fs)

def add_locks(src_lock, pool):
    dst_lock = fs.get_lock(dst_fs, src_lock.path)
    if (dst_lock and src_lock.token == dst_lock.token
        and src_lock.comment == dst_lock.comment
        and src_lock.is_dav_comment == dst_lock.is_dav_comment
        and src_lock.expiration_date == dst_lock.expiration_date):
        print "elide: " + src_lock.path
        return
    
    access = fs.create_access(src_lock.owner)
    fs.set_access(dst_fs, access)
    fs.lock(dst_fs,
            src_lock.path, src_lock.token, src_lock.comment,
            src_lock.is_dav_comment, src_lock.expiration_date,
            dst_head, True)
    print "set: " + src_lock.path

fs.get_locks(src_fs, "", add_locks)

def rm_locks(dst_lock, pool):
    src_lock = fs.get_lock(src_fs, dst_lock.path)
    if not src_lock:
        fs.unlock(dst_fs, dst_lock.path, dst_lock.token, True)
        print "rm: " + dst_lock.path

access = fs.create_access("dummy")
fs.set_access(dst_fs, access)
fs.get_locks(dst_fs, "", rm_locks)

-- 
Philip Martin
WANdisco
Received on 2015-09-24 13:48:44 CEST

This is an archived mail posted to the Subversion Dev mailing list.