summaryrefslogtreecommitdiff
path: root/portato/ipc.pyx
diff options
context:
space:
mode:
authorRené 'Necoro' Neumann <necoro@necoro.net>2009-08-15 11:51:15 +0200
committerRené 'Necoro' Neumann <necoro@necoro.net>2009-08-15 11:51:15 +0200
commit088452702812614cbbbaa64b116f29971920fac2 (patch)
tree6ebcac8a97e12720e09630e4f41c3cc7ecacd6bb /portato/ipc.pyx
parent44d410d007e88d794e35e322082bec3ec69d5fa7 (diff)
downloadportato-088452702812614cbbbaa64b116f29971920fac2.tar.gz
portato-088452702812614cbbbaa64b116f29971920fac2.tar.bz2
portato-088452702812614cbbbaa64b116f29971920fac2.zip
Renamed 'mq' to 'ipc'
Diffstat (limited to 'portato/ipc.pyx')
-rw-r--r--portato/ipc.pyx144
1 files changed, 144 insertions, 0 deletions
diff --git a/portato/ipc.pyx b/portato/ipc.pyx
new file mode 100644
index 0000000..4a06102
--- /dev/null
+++ b/portato/ipc.pyx
@@ -0,0 +1,144 @@
+# -*- coding: utf-8 -*-
+#
+# File: portato/ipc.pyx
+# This file is part of the Portato-Project, a graphical portage-frontend.
+#
+# Copyright (C) 2006-2009 René 'Necoro' Neumann
+# This is free software. You may redistribute copies of it under the terms of
+# the GNU General Public License version 2.
+# There is NO WARRANTY, to the extent permitted by law.
+#
+# Written by René 'Necoro' Neumann <necoro@necoro.net>
+
+class MessageQueueError(Exception):
+ pass
+
+class MessageQueueRemovedError (MessageQueueError):
+ pass
+
+cdef class MessageQueue (object):
+
+ CREAT = IPC_CREAT
+ EXCL = IPC_EXCL
+
+ cdef int msgid
+ cdef readonly key_t key
+
+ def __init__ (self, key = None, int flags = 0):
+
+ if (flags & IPC_EXCL) and not (flags & IPC_CREAT):
+ raise MessageQueueError("EXCL must be combined with CREAT.")
+
+ if key is None and not (flags & IPC_EXCL):
+ raise MessageQueueError("The key can only be None if EXCL is set.")
+
+ # make sure there is nothing ... obscure
+ flags &= (IPC_CREAT | IPC_EXCL)
+
+ flags |= 0600 # mode
+
+ if key is None:
+ check = True
+ while check:
+ self.key = self.random_key()
+ self.msgid = msgget(self.key, flags)
+ check = (self.msgid == -1 and errno == EEXIST)
+ else:
+ self.key = key
+ self.msgid = msgget(key, flags)
+
+ if self.msgid == -1:
+ if errno == EACCES:
+ raise MessageQueueError("Permission denied.")
+ elif errno == EEXIST:
+ raise MessageQueueError("Queue already exists.")
+ elif errno == ENOENT:
+ raise MessageQueueError("Queue does not exist and CREAT is not set.")
+ elif errno == ENOMEM or errno == ENOSPC:
+ raise MessageQueueError("Insufficient ressources.")
+ else:
+ raise OSError(errno, strerror(errno))
+
+ def remove (self):
+ cdef msqid_ds info
+ cdef int ret
+
+ ret = msgctl(self.msgid, IPC_RMID, &info)
+
+ if ret == -1:
+ if errno == EIDRM or errno == EINVAL:
+ raise MessageQueueRemovedError("Queue already removed.")
+ elif errno == EPERM:
+ raise MessageQueueError("Permission denied.")
+ else:
+ raise OSError(errno, strerror(errno))
+
+ def send (self, message, int type = 1):
+ cdef msg_data * msg
+ cdef int ret
+ cdef long size = len(message)
+
+ if type <= 0:
+ raise ValueError("type must be > 0")
+
+ if size >= MAX_MESSAGE_SIZE:
+ raise ValueError("Message must be smaller than %d", MAX_MESSAGE_SIZE)
+
+ msg = <msg_data*>PyMem_Malloc(sizeof(msg_data) + size)
+
+ if msg is NULL:
+ raise MemoryError("Out of memory")
+
+ memcpy(msg.mtext, <char*>message, size)
+ msg.mtype = type
+
+ with nogil:
+ ret = msgsnd(self.msgid, msg, size, 0)
+
+ try:
+ if ret == -1:
+ if errno == EIDRM or errno == EINVAL:
+ raise MessageQueueRemovedError("Queue was removed.")
+ elif errno == EINTR:
+ raise MessageQueueError("Signaled while waiting.")
+ elif errno == EACCES:
+ raise MessageQueueError("Permission denied.")
+ else:
+ raise OSError(errno, strerror(errno))
+ finally:
+ PyMem_Free(msg)
+
+ def receive (self):
+ cdef msg_data * msg
+ cdef int ret
+ cdef object retTuple
+
+ msg = <msg_data*>PyMem_Malloc(sizeof(msg_data) + MAX_MESSAGE_SIZE)
+
+ if msg is NULL:
+ raise MemoryError("Out of memory")
+
+ msg.mtype = 0
+
+ with nogil:
+ ret = msgrcv(self.msgid, msg, <size_t>MAX_MESSAGE_SIZE, 0, 0)
+
+ try:
+ if ret == -1:
+ if errno == EIDRM or errno == EINVAL:
+ raise MessageQueueRemovedError("Queue was removed.")
+ elif errno == EINTR:
+ raise MessageQueueError("Signaled while waiting.")
+ elif errno == EACCES:
+ raise MessageQueueError("Permission denied.")
+ else:
+ raise OSError(errno, strerror(errno))
+
+ retTuple = (PyString_FromStringAndSize(msg.mtext, ret), msg.mtype)
+ finally:
+ PyMem_Free(msg)
+
+ return retTuple
+
+ cdef key_t random_key (self):
+ return <int>(<double>rand() / (<double>RAND_MAX + 1) * INT_MAX)