Revision 4819d34f pithos/backends/modular.py

b/pithos/backends/modular.py
146 146
        else:
147 147
            meta = {}
148 148
            if props is not None:
149
                meta.update(dict(self.node.attribute_get(props[self.SERIAL])))
149
                meta.update(dict(self.node.attribute_get(props[self.SERIAL], domain)))
150 150
            if until is not None:
151 151
                meta.update({'until_timestamp': tstamp})
152 152
            meta.update({'name': account, 'count': count, 'bytes': bytes})
......
161 161
        if user != account:
162 162
            raise NotAllowedError
163 163
        path, node = self._lookup_account(account, True)
164
        self._put_metadata(user, node, meta, replace)
164
        self._put_metadata(user, node, domain, meta, replace)
165 165
    
166 166
    @backend_method
167 167
    def get_account_groups(self, user, account):
......
261 261
            start, limit = self._list_limits(allowed, marker, limit)
262 262
            return allowed[start:start + limit]
263 263
        node = self.node.node_lookup(account)
264
        return [x[0] for x in self._list_objects(node, account, '', '/', marker, limit, False, [], until)]
264
        return [x[0] for x in self._list_objects(node, account, '', '/', marker, limit, False, None, [], until)]
265 265
    
266 266
    @backend_method
267 267
    def get_container_meta(self, user, account, container, domain, until=None):
......
285 285
        if user != account:
286 286
            meta = {'name': container}
287 287
        else:
288
            meta = dict(self.node.attribute_get(props[self.SERIAL]))
288
            meta = dict(self.node.attribute_get(props[self.SERIAL], domain))
289 289
            if until is not None:
290 290
                meta.update({'until_timestamp': tstamp})
291 291
            meta.update({'name': container, 'count': count, 'bytes': bytes})
......
300 300
        if user != account:
301 301
            raise NotAllowedError
302 302
        path, node = self._lookup_container(account, container)
303
        self._put_metadata(user, node, meta, replace)
303
        self._put_metadata(user, node, domain, meta, replace)
304 304
    
305 305
    @backend_method
306 306
    def get_container_policy(self, user, account, container):
......
386 386
                if not allowed:
387 387
                    return []
388 388
        path, node = self._lookup_container(account, container)
389
        return self._list_objects(node, path, prefix, delimiter, marker, limit, virtual, keys, until, allowed)
389
        return self._list_objects(node, path, prefix, delimiter, marker, limit, virtual, domain, keys, until, allowed)
390 390
    
391 391
    @backend_method
392 392
    def list_object_meta(self, user, account, container, domain, until=None):
......
402 402
                raise NotAllowedError
403 403
        path, node = self._lookup_container(account, container)
404 404
        before = until if until is not None else inf
405
        return self.node.latest_attribute_keys(node, before, CLUSTER_DELETED, allowed)
405
        return self.node.latest_attribute_keys(node, domain, before, CLUSTER_DELETED, allowed)
406 406
    
407 407
    @backend_method
408 408
    def get_object_meta(self, user, account, container, name, domain, version=None):
......
423 423
                    raise NameError('Object does not exist')
424 424
                modified = del_props[self.MTIME]
425 425
        
426
        meta = dict(self.node.attribute_get(props[self.SERIAL]))
426
        meta = dict(self.node.attribute_get(props[self.SERIAL], domain))
427 427
        meta.update({'name': name, 'bytes': props[self.SIZE], 'hash':props[self.HASH]})
428 428
        meta.update({'version': props[self.SERIAL], 'version_timestamp': props[self.MTIME]})
429 429
        meta.update({'modified': modified, 'modified_by': props[self.MUSER]})
......
436 436
        logger.debug("update_object_meta: %s %s %s %s %s %s", account, container, name, domain, meta, replace)
437 437
        self._can_write(user, account, container, name)
438 438
        path, node = self._lookup_object(account, container, name)
439
        src_version_id, dest_version_id = self._put_metadata(user, node, meta, replace)
439
        src_version_id, dest_version_id = self._put_metadata(user, node, domain, meta, replace)
440 440
        self._apply_versioning(account, container, src_version_id)
441 441
        return dest_version_id
442 442
    
......
505 505
        hashmap = self.store.map_get(binascii.unhexlify(props[self.HASH]))
506 506
        return props[self.SIZE], [binascii.hexlify(x) for x in hashmap]
507 507
    
508
    def _update_object_hash(self, user, account, container, name, size, hash, meta={}, replace_meta=False, permissions=None):
508
    def _update_object_hash(self, user, account, container, name, size, hash, permissions=None):
509 509
        if permissions is not None and user != account:
510 510
            raise NotAllowedError
511 511
        self._can_write(user, account, container, name)
......
528 528
                # This must be executed in a transaction, so the version is never created if it fails.
529 529
                raise QuotaError
530 530
        
531
        if not replace_meta and src_version_id is not None:
532
            self.node.attribute_copy(src_version_id, dest_version_id)
533
        self.node.attribute_set(dest_version_id, ((k, v) for k, v in meta.iteritems()))
534 531
        if permissions is not None:
535 532
            self.permissions.access_set(path, permissions)
536 533
        self._apply_versioning(account, container, src_version_id)
537
        return dest_version_id
534
        return src_version_id, dest_version_id
538 535
    
539 536
    @backend_method
540 537
    def update_object_hashmap(self, user, account, container, name, size, hashmap, domain, meta={}, replace_meta=False, permissions=None):
......
552 549
            raise ie
553 550
        
554 551
        hash = map.hash()
555
        dest_version_id = self._update_object_hash(user, account, container, name, size, binascii.hexlify(hash), meta, replace_meta, permissions)
552
        src_version_id, dest_version_id = self._update_object_hash(user, account, container, name, size, binascii.hexlify(hash), permissions)
553
        self._put_metadata_duplicate(src_version_id, dest_version_id, domain, meta, replace_meta)
556 554
        self.store.map_put(hash, map)
557 555
        return dest_version_id
558 556
    
559
    def _copy_object(self, user, src_account, src_container, src_name, dest_account, dest_container, dest_name, dest_meta={}, replace_meta=False, permissions=None, src_version=None):
557
    def _copy_object(self, user, src_account, src_container, src_name, dest_account, dest_container, dest_name, dest_domain=None, dest_meta={}, replace_meta=False, permissions=None, src_version=None):
560 558
        self._can_read(user, src_account, src_container, src_name)
561 559
        path, node = self._lookup_object(src_account, src_container, src_name)
562 560
        props = self._get_version(node, src_version)
......
564 562
        hash = props[self.HASH]
565 563
        size = props[self.SIZE]
566 564
        
567
        if (src_account, src_container, src_name) == (dest_account, dest_container, dest_name):
568
            dest_version_id = self._update_object_hash(user, dest_account, dest_container, dest_name, size, hash, dest_meta, replace_meta, permissions)
569
        else:
570
            if replace_meta:
571
                meta = dest_meta
572
            else:
573
                meta = {}
574
            dest_version_id = self._update_object_hash(user, dest_account, dest_container, dest_name, size, hash, meta, True, permissions)
575
            if not replace_meta:
576
                self.node.attribute_copy(src_version_id, dest_version_id)
577
                self.node.attribute_set(dest_version_id, ((k, v) for k, v in dest_meta.iteritems()))
565
        src_v_id, dest_version_id = self._update_object_hash(user, dest_account, dest_container, dest_name, size, hash, permissions)
566
        self._put_metadata_duplicate(src_version_id, dest_version_id, dest_domain, dest_meta, replace_meta)
578 567
        return dest_version_id
579 568
    
580 569
    @backend_method
......
582 571
        """Copy an object's data and metadata."""
583 572
        
584 573
        logger.debug("copy_object: %s %s %s %s %s %s %s %s %s %s %s", src_account, src_container, src_name, dest_account, dest_container, dest_name, domain, meta, replace_meta, permissions, src_version)
585
        return self._copy_object(user, src_account, src_container, src_name, dest_account, dest_container, dest_name, dest_meta, replace_meta, permissions, src_version)
574
        return self._copy_object(user, src_account, src_container, src_name, dest_account, dest_container, dest_name, domain, meta, replace_meta, permissions, src_version)
586 575
    
587 576
    @backend_method
588 577
    def move_object(self, user, src_account, src_container, src_name, dest_account, dest_container, dest_name, domain, meta={}, replace_meta=False, permissions=None):
......
591 580
        logger.debug("move_object: %s %s %s %s %s %s %s %s %s %s", src_account, src_container, src_name, dest_account, dest_container, dest_name, domain, meta, replace_meta, permissions)
592 581
        if user != src_account:
593 582
            raise NotAllowedError
594
        dest_version_id = self._copy_object(user, src_account, src_container, src_name, dest_account, dest_container, dest_name, meta, replace_meta, permissions, None)
583
        dest_version_id = self._copy_object(user, src_account, src_container, src_name, dest_account, dest_container, dest_name, domain, meta, replace_meta, permissions, None)
595 584
        if (src_account, src_container, src_name) != (dest_account, dest_container, dest_name):
596 585
            self._delete_object(user, src_account, src_container, src_name)
597 586
        return dest_version_id
......
768 757
        dest_version_id, mtime = self.node.version_create(node, hash, size, src_version_id, user, cluster)
769 758
        return src_version_id, dest_version_id
770 759
    
771
    def _put_metadata(self, user, node, meta, replace=False):
760
    def _put_metadata_duplicate(self, src_version_id, dest_version_id, domain, meta, replace=False):
761
        if src_version_id is not None:
762
            self.node.attribute_copy(src_version_id, dest_version_id)
763
        if not replace:
764
            self.node.attribute_del(dest_version_id, domain, (k for k, v in meta.iteritems() if v == ''))
765
            self.node.attribute_set(dest_version_id, domain, ((k, v) for k, v in meta.iteritems() if v != ''))
766
        else:
767
            self.node.attribute_del(dest_version_id, domain)
768
            self.node.attribute_set(dest_version_id, domain, ((k, v) for k, v in meta.iteritems()))
769
    
770
    def _put_metadata(self, user, node, domain, meta, replace=False):
772 771
        """Create a new version and store metadata."""
773 772
        
774 773
        src_version_id, dest_version_id = self._put_version_duplicate(user, node)
775
        
776
        # TODO: Merge with other functions that update metadata...
777
        if not replace:
778
            if src_version_id is not None:
779
                self.node.attribute_copy(src_version_id, dest_version_id)
780
            self.node.attribute_del(dest_version_id, (k for k, v in meta.iteritems() if v == ''))
781
            self.node.attribute_set(dest_version_id, ((k, v) for k, v in meta.iteritems() if v != ''))
782
        else:
783
            self.node.attribute_set(dest_version_id, ((k, v) for k, v in meta.iteritems()))
774
        self._put_metadata_duplicate(src_version_id, dest_version_id, domain, meta, replace)
784 775
        return src_version_id, dest_version_id
785 776
    
786 777
    def _list_limits(self, listing, marker, limit):
......
794 785
            limit = 10000
795 786
        return start, limit
796 787
    
797
    def _list_objects(self, parent, path, prefix='', delimiter=None, marker=None, limit=10000, virtual=True, keys=[], until=None, allowed=[]):
788
    def _list_objects(self, parent, path, prefix='', delimiter=None, marker=None, limit=10000, virtual=True, domain=None, keys=[], until=None, allowed=[]):
798 789
        cont_prefix = path + '/'
799 790
        prefix = cont_prefix + prefix
800 791
        start = cont_prefix + marker if marker else None
801 792
        before = until if until is not None else inf
802
        filterq = ','.join(keys) if keys else None
793
        filterq = keys if domain else []
803 794
        
804
        objects, prefixes = self.node.latest_version_list(parent, prefix, delimiter, start, limit, before, CLUSTER_DELETED, allowed, filterq)
795
        objects, prefixes = self.node.latest_version_list(parent, prefix, delimiter, start, limit, before, CLUSTER_DELETED, allowed, domain, filterq)
805 796
        objects.extend([(p, None) for p in prefixes] if virtual else [])
806 797
        objects.sort(key=lambda x: x[0])
807 798
        objects = [(x[0][len(cont_prefix):], x[1]) for x in objects]

Also available in: Unified diff