DistributedLargeBlobSenderAI.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. """DistributedLargeBlobSenderAI module: contains the DistributedLargeBlobSenderAI class"""
  2. from direct.distributed import DistributedObjectAI
  3. from direct.directnotify import DirectNotifyGlobal
  4. from . import LargeBlobSenderConsts
  5. class DistributedLargeBlobSenderAI(DistributedObjectAI.DistributedObjectAI):
  6. """DistributedLargeBlobSenderAI: for sending large chunks of data through
  7. the DC system to a specific avatar"""
  8. notify = DirectNotifyGlobal.directNotify.newCategory('DistributedLargeBlobSenderAI')
  9. def __init__(self, air, zoneId, targetAvId, data, useDisk=0):
  10. DistributedObjectAI.DistributedObjectAI.__init__(self, air)
  11. self.targetAvId = targetAvId
  12. self.mode = 0
  13. if useDisk:
  14. self.mode |= LargeBlobSenderConsts.USE_DISK
  15. self.generateWithRequired(zoneId)
  16. # send the data
  17. s = str(data)
  18. if useDisk:
  19. # write the data to a file and tell the client where to get it
  20. import os
  21. import random
  22. origDir = os.getcwd()
  23. bPath = LargeBlobSenderConsts.getLargeBlobPath()
  24. try:
  25. os.chdir(bPath)
  26. except OSError:
  27. DistributedLargeBlobSenderAI.notify.error(
  28. 'could not access %s' % bPath)
  29. # find an unused temp filename
  30. while 1:
  31. num = random.randrange((1 << 30)-1)
  32. filename = LargeBlobSenderConsts.FilePattern % num
  33. try:
  34. os.stat(filename)
  35. except OSError:
  36. break
  37. # NOTE: there's a small chance of a race condition here, if
  38. # the file is created by another AI just after the stat fails
  39. f = open(filename, 'wb')
  40. f.write(s)
  41. f.close()
  42. os.chdir(origDir)
  43. self.sendUpdateToAvatarId(self.targetAvId,
  44. 'setFilename', [filename])
  45. else:
  46. chunkSize = LargeBlobSenderConsts.ChunkSize
  47. while len(s) > 0:
  48. self.sendUpdateToAvatarId(self.targetAvId,
  49. 'setChunk', [s[:chunkSize]])
  50. s = s[chunkSize:]
  51. # send final empty string
  52. self.sendUpdateToAvatarId(self.targetAvId, 'setChunk', [''])
  53. def getMode(self):
  54. return self.mode
  55. def getTargetAvId(self):
  56. return self.targetAvId
  57. def setAck(self):
  58. DistributedLargeBlobSenderAI.notify.debug('setAck')
  59. assert self.air.getAvatarIdFromSender() == self.targetAvId
  60. self.requestDelete()