summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2011-07-15 17:45:20 +0300
committerLars Wirzenius <liw@liw.fi>2011-07-15 17:45:20 +0300
commitc0e137d0e003ce2f9bf11a3a08c4aaf4f6b37825 (patch)
tree2cffcef476d60a3782f8586ee15dbff7a339b0d6
parent9923407a330f84b2c6c74a600644d3fccfc1f39c (diff)
downloadobnam-c0e137d0e003ce2f9bf11a3a08c4aaf4f6b37825.tar.gz
Move metadata encoding and decoding into the metadata module.
That's where it belongs.
-rwxr-xr-xmetadata-speed6
-rw-r--r--obnamlib/__init__.py2
-rw-r--r--obnamlib/clientmetadatatree_tests.py4
-rw-r--r--obnamlib/metadata.py97
-rw-r--r--obnamlib/metadata_tests.py36
-rw-r--r--obnamlib/repo.py98
-rw-r--r--obnamlib/repo_tests.py36
7 files changed, 141 insertions, 138 deletions
diff --git a/metadata-speed b/metadata-speed
index 6d93cad6..3b6525cf 100755
--- a/metadata-speed
+++ b/metadata-speed
@@ -37,10 +37,10 @@ def main():
fs = obnamlib.LocalFS('.')
fs.connect()
metadata = obnamlib.read_metadata(fs, '.')
- encoded = obnamlib.repo.encode_metadata(metadata)
+ encoded = obnamlib.encode_metadata(metadata)
calibrate = measure(n, lambda: None)
- encode = measure(n, lambda: obnamlib.repo.encode_metadata(metadata))
- decode = measure(n, lambda: obnamlib.repo.decode_metadata(encoded))
+ encode = measure(n, lambda: obnamlib.encode_metadata(metadata))
+ decode = measure(n, lambda: obnamlib.decode_metadata(encoded))
print 'encode: %.1f s' % (n/(encode - calibrate))
print 'decode: %.1f s' % (n/(decode - calibrate))
diff --git a/obnamlib/__init__.py b/obnamlib/__init__.py
index cdbc8f60..da5b8c3c 100644
--- a/obnamlib/__init__.py
+++ b/obnamlib/__init__.py
@@ -56,7 +56,7 @@ from pluginbase import ObnamPlugin
from vfs import VirtualFileSystem, VfsFactory, VfsTests
from vfs_local import LocalFS
from metadata import (read_metadata, set_metadata, Metadata, metadata_fields,
- metadata_verify_fields)
+ metadata_verify_fields, encode_metadata, decode_metadata)
from repo_tree import RepositoryTree
from chunklist import ChunkList
from clientlist import ClientList
diff --git a/obnamlib/clientmetadatatree_tests.py b/obnamlib/clientmetadatatree_tests.py
index 2fe02a28..dd3503c9 100644
--- a/obnamlib/clientmetadatatree_tests.py
+++ b/obnamlib/clientmetadatatree_tests.py
@@ -150,9 +150,9 @@ class ClientMetadataTreeFileOpsTests(unittest.TestCase):
self.client.start_generation()
self.clientid = self.client.get_generation_id(self.client.tree)
self.file_metadata = obnamlib.Metadata(st_mode=stat.S_IFREG | 0666)
- self.file_encoded = obnamlib.repo.encode_metadata(self.file_metadata)
+ self.file_encoded = obnamlib.encode_metadata(self.file_metadata)
self.dir_metadata = obnamlib.Metadata(st_mode=stat.S_IFDIR | 0777)
- self.dir_encoded = obnamlib.repo.encode_metadata(self.dir_metadata)
+ self.dir_encoded = obnamlib.encode_metadata(self.dir_metadata)
def tearDown(self):
shutil.rmtree(self.tempdir)
diff --git a/obnamlib/metadata.py b/obnamlib/metadata.py
index e81852f0..0fd25032 100644
--- a/obnamlib/metadata.py
+++ b/obnamlib/metadata.py
@@ -18,6 +18,9 @@ import grp
import os
import pwd
import stat
+import struct
+
+import obnamlib
metadata_verify_fields = (
@@ -146,4 +149,98 @@ def set_metadata(fs, filename, metadata, getuid=None):
getuid = getuid or os.getuid
if getuid() == 0:
fs.lchown(filename, metadata.st_uid, metadata.st_gid)
+
+
+metadata_format = struct.Struct('!Q' + # flags
+ 'Q' + # st_mode
+ 'QQ' + # st_mtime (as two integers)
+ 'QQ' + # st_atime (as two integers)
+ 'Q' + # st_nlink
+ 'Q' + # st_size
+ 'Q' + # st_uid
+ 'Q' + # st_gid
+ 'Q' + # st_dev
+ 'Q' + # st_ino
+ 'Q' + # st_blocks
+ 'Q' + # len of groupname
+ 'Q' + # len of username
+ 'Q' + # len of symlink target
+ '')
+
+def encode_metadata(metadata):
+ flags = 0
+ for i, name in enumerate(obnamlib.metadata_fields):
+ if getattr(metadata, name) is not None:
+ flags |= (1 << i)
+
+ if metadata.st_mtime is None:
+ mtime_a, mtime_b = 0, 0
+ else:
+ mtime_a, mtime_b = metadata.st_mtime.as_integer_ratio()
+ if metadata.st_atime is None:
+ atime_a, atime_b = 0, 0
+ else:
+ atime_a, atime_b = metadata.st_atime.as_integer_ratio()
+ packed = metadata_format.pack(flags,
+ metadata.st_mode or 0,
+ mtime_a, mtime_b,
+ atime_a, atime_b,
+ metadata.st_nlink or 0,
+ metadata.st_size or 0,
+ metadata.st_uid or 0,
+ metadata.st_gid or 0,
+ metadata.st_dev or 0,
+ metadata.st_ino or 0,
+ metadata.st_blocks or 0,
+ len(metadata.groupname or ''),
+ len(metadata.username or ''),
+ len(metadata.target or ''))
+ return (packed +
+ (metadata.groupname or '') +
+ (metadata.username or '') +
+ (metadata.target or ''))
+
+def decode_metadata(encoded):
+
+ items = metadata_format.unpack_from(encoded)
+ flags = items[0]
+ pos = [1, metadata_format.size]
+ metadata = obnamlib.Metadata()
+
+ def is_present(field):
+ i = obnamlib.metadata_fields.index(field)
+ return (flags & (1 << i)) != 0
+
+ def decode(field, num_items, inc_offset, getvalue):
+ if is_present(field):
+ value = getvalue(pos[0], pos[1])
+ setattr(metadata, field, value)
+ if inc_offset:
+ pos[1] += len(value)
+ pos[0] += num_items
+
+ def decode_integer(field):
+ decode(field, 1, False, lambda i, o: items[i])
+
+ def decode_float(field):
+ decode(field, 2, False, lambda i, o: float(items[i]) / items[i+1])
+
+ def decode_string(field):
+ decode(field, 1, True, lambda i, o: encoded[o:o + items[i]])
+
+ decode_integer('st_mode')
+ decode_float('st_mtime')
+ decode_float('st_atime')
+ decode_integer('st_nlink')
+ decode_integer('st_size')
+ decode_integer('st_uid')
+ decode_integer('st_gid')
+ decode_integer('st_dev')
+ decode_integer('st_ino')
+ decode_integer('st_blocks')
+ decode_string('groupname')
+ decode_string('username')
+ decode_string('target')
+
+ return metadata
diff --git a/obnamlib/metadata_tests.py b/obnamlib/metadata_tests.py
index 2d356cca..c57ee303 100644
--- a/obnamlib/metadata_tests.py
+++ b/obnamlib/metadata_tests.py
@@ -206,3 +206,39 @@ class SetMetadataTests(unittest.TestCase):
self.assertEqual(st.st_mode, self.metadata.st_mode)
self.assertEqual(st.st_mtime, self.metadata.st_mtime)
+
+class MetadataCodingTests(unittest.TestCase):
+
+ def test_round_trip(self):
+ metadata = obnamlib.metadata.Metadata(st_mode=1,
+ st_mtime=2.12756,
+ st_nlink=3,
+ st_size=4,
+ st_uid=5,
+ st_blocks=6,
+ st_dev=7,
+ st_gid=8,
+ st_ino=9,
+ st_atime=10.123,
+ groupname='group',
+ username='user',
+ target='target')
+ encoded = obnamlib.encode_metadata(metadata)
+ decoded = obnamlib.decode_metadata(encoded)
+ for name in dir(metadata):
+ if name in obnamlib.metadata.metadata_fields:
+ self.assertEqual(getattr(metadata, name),
+ getattr(decoded, name),
+ 'attribute %s must be equal (%s vs %s)' %
+ (name, getattr(metadata, name),
+ getattr(decoded, name)))
+
+ def test_round_trip_for_None_values(self):
+ metadata = obnamlib.metadata.Metadata()
+ encoded = obnamlib.encode_metadata(metadata)
+ decoded = obnamlib.decode_metadata(encoded)
+ for name in dir(metadata):
+ if name in obnamlib.metadata.metadata_fields:
+ self.assertEqual(getattr(decoded, name), None,
+ 'attribute %s must be None' % name)
+
diff --git a/obnamlib/repo.py b/obnamlib/repo.py
index 36651423..b7204f98 100644
--- a/obnamlib/repo.py
+++ b/obnamlib/repo.py
@@ -83,100 +83,6 @@ def require_started_generation(method):
return method(self, *args, **kwargs)
return helper
-
-
-metadata_format = struct.Struct('!Q' + # flags
- 'Q' + # st_mode
- 'QQ' + # st_mtime (as two integers)
- 'QQ' + # st_atime (as two integers)
- 'Q' + # st_nlink
- 'Q' + # st_size
- 'Q' + # st_uid
- 'Q' + # st_gid
- 'Q' + # st_dev
- 'Q' + # st_ino
- 'Q' + # st_blocks
- 'Q' + # len of groupname
- 'Q' + # len of username
- 'Q' + # len of symlink target
- '')
-
-def encode_metadata(metadata):
- flags = 0
- for i, name in enumerate(obnamlib.metadata_fields):
- if getattr(metadata, name) is not None:
- flags |= (1 << i)
-
- if metadata.st_mtime is None:
- mtime_a, mtime_b = 0, 0
- else:
- mtime_a, mtime_b = metadata.st_mtime.as_integer_ratio()
- if metadata.st_atime is None:
- atime_a, atime_b = 0, 0
- else:
- atime_a, atime_b = metadata.st_atime.as_integer_ratio()
- packed = metadata_format.pack(flags,
- metadata.st_mode or 0,
- mtime_a, mtime_b,
- atime_a, atime_b,
- metadata.st_nlink or 0,
- metadata.st_size or 0,
- metadata.st_uid or 0,
- metadata.st_gid or 0,
- metadata.st_dev or 0,
- metadata.st_ino or 0,
- metadata.st_blocks or 0,
- len(metadata.groupname or ''),
- len(metadata.username or ''),
- len(metadata.target or ''))
- return (packed +
- (metadata.groupname or '') +
- (metadata.username or '') +
- (metadata.target or ''))
-
-def decode_metadata(encoded):
-
- items = metadata_format.unpack_from(encoded)
- flags = items[0]
- pos = [1, metadata_format.size]
- metadata = obnamlib.Metadata()
-
- def is_present(field):
- i = obnamlib.metadata_fields.index(field)
- return (flags & (1 << i)) != 0
-
- def decode(field, num_items, inc_offset, getvalue):
- if is_present(field):
- value = getvalue(pos[0], pos[1])
- setattr(metadata, field, value)
- if inc_offset:
- pos[1] += len(value)
- pos[0] += num_items
-
- def decode_integer(field):
- decode(field, 1, False, lambda i, o: items[i])
-
- def decode_float(field):
- decode(field, 2, False, lambda i, o: float(items[i]) / items[i+1])
-
- def decode_string(field):
- decode(field, 1, True, lambda i, o: encoded[o:o + items[i]])
-
- decode_integer('st_mode')
- decode_float('st_mtime')
- decode_float('st_atime')
- decode_integer('st_nlink')
- decode_integer('st_size')
- decode_integer('st_uid')
- decode_integer('st_gid')
- decode_integer('st_dev')
- decode_integer('st_ino')
- decode_integer('st_blocks')
- decode_string('groupname')
- decode_string('username')
- decode_string('target')
-
- return metadata
class HookedFS(object):
@@ -601,12 +507,12 @@ class Repository(object):
encoded = self.client.get_metadata(gen, filename)
except KeyError:
raise obnamlib.Error('%s does not exist' % filename)
- return decode_metadata(encoded)
+ return obnamlib.decode_metadata(encoded)
@require_started_generation
def create(self, filename, metadata):
'''Create a new (empty) file in the new generation.'''
- encoded = encode_metadata(metadata)
+ encoded = obnamlib.encode_metadata(metadata)
self.client.create(filename, encoded)
@require_started_generation
diff --git a/obnamlib/repo_tests.py b/obnamlib/repo_tests.py
index 8729160b..c5b563f7 100644
--- a/obnamlib/repo_tests.py
+++ b/obnamlib/repo_tests.py
@@ -24,42 +24,6 @@ import unittest
import obnamlib
-class MetadataCodingTests(unittest.TestCase):
-
- def test_round_trip(self):
- metadata = obnamlib.metadata.Metadata(st_mode=1,
- st_mtime=2.12756,
- st_nlink=3,
- st_size=4,
- st_uid=5,
- st_blocks=6,
- st_dev=7,
- st_gid=8,
- st_ino=9,
- st_atime=10.123,
- groupname='group',
- username='user',
- target='target')
- encoded = obnamlib.repo.encode_metadata(metadata)
- decoded = obnamlib.repo.decode_metadata(encoded)
- for name in dir(metadata):
- if name in obnamlib.metadata.metadata_fields:
- self.assertEqual(getattr(metadata, name),
- getattr(decoded, name),
- 'attribute %s must be equal (%s vs %s)' %
- (name, getattr(metadata, name),
- getattr(decoded, name)))
-
- def test_round_trip_for_None_values(self):
- metadata = obnamlib.metadata.Metadata()
- encoded = obnamlib.repo.encode_metadata(metadata)
- decoded = obnamlib.repo.decode_metadata(encoded)
- for name in dir(metadata):
- if name in obnamlib.metadata.metadata_fields:
- self.assertEqual(getattr(decoded, name), None,
- 'attribute %s must be None' % name)
-
-
class RepositoryRootNodeTests(unittest.TestCase):
def setUp(self):