"""DistributedLargeBlobSenderAI module: contains the DistributedLargeBlobSenderAI class""" from direct.distributed import DistributedObjectAI from direct.directnotify import DirectNotifyGlobal import LargeBlobSenderConsts class DistributedLargeBlobSenderAI(DistributedObjectAI.DistributedObjectAI): """DistributedLargeBlobSenderAI: for sending large chunks of data through the DC system to a specific avatar""" notify = DirectNotifyGlobal.directNotify.newCategory('DistributedLargeBlobSenderAI') def __init__(self, air, zoneId, targetAvId, data, useDisk=0): DistributedObjectAI.DistributedObjectAI.__init__(self, air) self.targetAvId = targetAvId self.mode = 0 if useDisk: self.mode |= LargeBlobSenderConsts.USE_DISK self.generateWithRequired(zoneId) # send the data s = str(data) if useDisk: # write the data to a file and tell the client where to get it import os import random origDir = os.getcwd() bPath = LargeBlobSenderConsts.getLargeBlobPath() try: os.chdir(bPath) except OSError: DistributedLargeBlobSenderAI.notify.error( 'could not access %s' % bPath) # find an unused temp filename while 1: num = random.randrange((1 << 30)-1) filename = LargeBlobSenderConsts.FilePattern % num try: os.stat(filename) except OSError: break # NOTE: there's a small chance of a race condition here, if # the file is created by another AI just after the stat fails f = file(filename, 'wb') f.write(s) f.close() os.chdir(origDir) self.sendUpdateToAvatarId(self.targetAvId, 'setFilename', [filename]) else: chunkSize = LargeBlobSenderConsts.ChunkSize while len(s): self.sendUpdateToAvatarId(self.targetAvId, 'setChunk', [s[:chunkSize]]) s = s[chunkSize:] # send final empty string self.sendUpdateToAvatarId(self.targetAvId, 'setChunk', ['']) def getMode(self): return self.mode def getTargetAvId(self): return self.targetAvId def setAck(self): DistributedLargeBlobSenderAI.notify.debug('setAck') assert self.air.getAvatarIdFromSender() == self.targetAvId self.requestDelete()