def findClusters(self, toSend): """ Return a list of tuples of (alias, deleteFlag) pairs, clustering recordsets that need to be serialized together (recurrence modifications and masters). The first pair will be the master. For instance: [((master1, False), (mod1, False)), ((master2, False),)] """ mastersChanged = set() mastersDeleted = set() view = self.itsView translator = self.translator(self.itsView) for alias, rs in toSend.iteritems(): masterAlias, recurrenceID = splitUUID(view, alias) s = mastersChanged if (rs is not None or recurrenceID) else mastersDeleted s.add(masterAlias) mastersChanged = mastersChanged - mastersDeleted clusters = [((alias, True), ) for alias in mastersDeleted] for masterAlias in mastersChanged: cluster = [(masterAlias, False)] clusters.append(cluster) master = view.findUUID(masterAlias) for mod in getattr(EventStamp(master), 'modifications', []): cluster.append((translator.getAliasForItem(mod), False)) return clusters
def findClusters(self, toSend): """ Return a list of tuples of (alias, deleteFlag) pairs, clustering recordsets that need to be serialized together (recurrence modifications and masters). The first pair will be the master. For instance: [((master1, False), (mod1, False)), ((master2, False),)] """ mastersChanged = set() mastersDeleted = set() view = self.itsView translator = self.translator(self.itsView) for alias, rs in toSend.iteritems(): masterAlias, recurrenceID = splitUUID(view, alias) s = mastersChanged if (rs is not None or recurrenceID) else mastersDeleted s.add(masterAlias) mastersChanged = mastersChanged - mastersDeleted clusters = [((alias, True),) for alias in mastersDeleted] for masterAlias in mastersChanged: cluster = [(masterAlias, False)] clusters.append(cluster) master = view.findUUID(masterAlias) for mod in getattr(EventStamp(master), 'modifications', []): cluster.append((translator.getAliasForItem(mod), False)) return clusters
def inbound(peer, text, filter=None, allowDeletion=False, debug=False): logger.info("itemcentric.inbound(%s)", str(peer)) if isinstance(peer, list): # Peer email address items can have several that match. We pass in # a list so this code can reuse the one (if any) already associated # to the inbound item. peers = peer else: peers = [peer] rv = peers[0].itsView # At some point, which serializer and translator to use should be # configurable serializer = eimml.EIMMLSerializer # only using class methods trans = translator.SharingTranslator(rv) inbound, extra = serializer.deserialize(rv, text, helperView=rv) peerRepoId = extra.get('repo', None) peerItemVersion = int(extra.get('version', '-1')) itemToReturn = None aliases = inbound.keys() aliases.sort() for alias in aliases: rsExternal = inbound[alias] uuid = trans.getUUIDForAlias(alias) if uuid: item = rv.findUUID(uuid) else: item = None if rsExternal is not None: if item is not None and not getattr(item, '_fake', False): # Item already exists if not pim.has_stamp(item, shares.SharedItem): shares.SharedItem(item).add() shared = shares.SharedItem(item) if not getattr(shared, 'peerStates', False): # has no peer states yet, use the first peer in list peer = peers[0] else: for state in shared.peerStates: peerUUID = shared.peerStates.getAlias(state) for peer in peers: if peer.itsUUID.str16() == peerUUID: # peer matches break else: # no match; use the first one passed in peer = peers[0] state = shared.getPeerState(peer) rsInternal= eim.RecordSet(trans.exportItem(item)) else: # Item doesn't exist yet peer = peers[0] state = shares.State(itsView=rv, peer=peer) rsInternal = eim.RecordSet() if state.peerRepoId and (peerRepoId != state.peerRepoId): # This update is not from the peer repository we last saw. # Treat the update is entirely new state.clear() if uuid is not None: masterAlias, recurrenceID = utility.splitUUID(rv, alias) if masterAlias != alias and not state.agreed: # This is a new inbound modification state.agreed += eim.RecordSet( recordset_conduit.getInheritRecords( rsExternal.inclusions, alias)) state.peerRepoId = peerRepoId # Only process recordsets whose version is greater than the last one # we say. In the case of null-repository-view testing, versions are # always stuck at zero, so process those as well. if ((peerItemVersion == 0) or (peerItemVersion > state.peerItemVersion)): state.peerItemVersion = peerItemVersion dSend, dApply, pending = state.merge(rsInternal, rsExternal, isDiff=False, filter=filter, debug=debug) state.autoResolve(rsInternal, dApply, dSend) state.updateConflicts(item) if dApply: logger.debug("Applying: %s %s", uuid, dApply) trans.startImport() trans.importRecords(dApply) trans.finishImport() uuid = trans.getUUIDForAlias(alias) if uuid: item = rv.findUUID(uuid) else: item = None if item is not None and item.isLive(): if not pim.has_stamp(item, shares.SharedItem): shares.SharedItem(item).add() shares.SharedItem(item).addPeerState(state, peer) if itemToReturn is None: # the item to return should always be a master, not # a modification itemToReturn = getattr(item, 'inheritFrom', item) else: logger.info("Out-of-sequence update for %s", uuid) raise errors.OutOfSequence("Update %d arrived after %d" % (peerItemVersion, state.peerItemVersion)) else: # Deletion if item is not None: # Remove the state if pim.has_stamp(item, shares.SharedItem): shared = shares.SharedItem(item) shared.removePeerState(peer) # Remove the item (if allowed) if allowDeletion: logger.debug("Deleting item: %s", uuid) item.delete(True) item = None return itemToReturn
def inbound(peer, text, filter=None, allowDeletion=False, debug=False): logger.info("itemcentric.inbound(%s)", str(peer)) if isinstance(peer, list): # Peer email address items can have several that match. We pass in # a list so this code can reuse the one (if any) already associated # to the inbound item. peers = peer else: peers = [peer] rv = peers[0].itsView # At some point, which serializer and translator to use should be # configurable serializer = eimml.EIMMLSerializer # only using class methods trans = translator.SharingTranslator(rv) inbound, extra = serializer.deserialize(rv, text, helperView=rv) peerRepoId = extra.get('repo', None) peerItemVersion = int(extra.get('version', '-1')) itemToReturn = None aliases = inbound.keys() aliases.sort() for alias in aliases: rsExternal = inbound[alias] uuid = trans.getUUIDForAlias(alias) if uuid: item = rv.findUUID(uuid) else: item = None if rsExternal is not None: if item is not None and not getattr(item, '_fake', False): # Item already exists if not pim.has_stamp(item, shares.SharedItem): shares.SharedItem(item).add() shared = shares.SharedItem(item) if not getattr(shared, 'peerStates', False): # has no peer states yet, use the first peer in list peer = peers[0] else: for state in shared.peerStates: peerUUID = shared.peerStates.getAlias(state) for peer in peers: if peer.itsUUID.str16() == peerUUID: # peer matches break else: # no match; use the first one passed in peer = peers[0] state = shared.getPeerState(peer) rsInternal = eim.RecordSet(trans.exportItem(item)) else: # Item doesn't exist yet peer = peers[0] state = shares.State(itsView=rv, peer=peer) rsInternal = eim.RecordSet() if state.peerRepoId and (peerRepoId != state.peerRepoId): # This update is not from the peer repository we last saw. # Treat the update is entirely new state.clear() if uuid is not None: masterAlias, recurrenceID = utility.splitUUID(rv, alias) if masterAlias != alias and not state.agreed: # This is a new inbound modification state.agreed += eim.RecordSet( recordset_conduit.getInheritRecords( rsExternal.inclusions, alias)) state.peerRepoId = peerRepoId # Only process recordsets whose version is greater than the last one # we say. In the case of null-repository-view testing, versions are # always stuck at zero, so process those as well. if ((peerItemVersion == 0) or (peerItemVersion > state.peerItemVersion)): state.peerItemVersion = peerItemVersion dSend, dApply, pending = state.merge(rsInternal, rsExternal, isDiff=False, filter=filter, debug=debug) state.autoResolve(rsInternal, dApply, dSend) state.updateConflicts(item) if dApply: logger.debug("Applying: %s %s", uuid, dApply) trans.startImport() trans.importRecords(dApply) trans.finishImport() uuid = trans.getUUIDForAlias(alias) if uuid: item = rv.findUUID(uuid) else: item = None if item is not None and item.isLive(): if not pim.has_stamp(item, shares.SharedItem): shares.SharedItem(item).add() shares.SharedItem(item).addPeerState(state, peer) if itemToReturn is None: # the item to return should always be a master, not # a modification itemToReturn = getattr(item, 'inheritFrom', item) else: logger.info("Out-of-sequence update for %s", uuid) raise errors.OutOfSequence( "Update %d arrived after %d" % (peerItemVersion, state.peerItemVersion)) else: # Deletion if item is not None: # Remove the state if pim.has_stamp(item, shares.SharedItem): shared = shares.SharedItem(item) shared.removePeerState(peer) # Remove the item (if allowed) if allowDeletion: logger.debug("Deleting item: %s", uuid) item.delete(True) item = None return itemToReturn