posix-mqueue 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 43c80748fbbdc131f1949149a5046213b1d8ad4c
4
- data.tar.gz: acd93be843908dead256dc96cb4680fa8f045abf
3
+ metadata.gz: a832068cb72094db986882a2f8799204decdb27d
4
+ data.tar.gz: 4f7d8fb462a26bcb476a1fc3114e03910d864993
5
5
  SHA512:
6
- metadata.gz: 764bb288fad4342bcc2bc99c69c5b5b1c12f2ee3f37367f5302f58eb1a8af285e2359fcd88a2c1db7ba4c183d857e87b77cab535285fc355bce47c78819d3427
7
- data.tar.gz: 13506b7fabd6bee22da907f807bddd7bbdadc494e0d7a313e86c888048d0a2297e361a0728736763d248ba49b8a7dfcb190167ac6b44854c0d7a62c9af441f38
6
+ metadata.gz: 89f33cce3c747f8096af5ac3bc4a872b0162add9e8f6e300975a67ac67c19112f4638954ac48629d15d591d7ca95caad7901b2560d1f23a64399a41f06c34115
7
+ data.tar.gz: 7a4c6d6466be7c9a508b5dfeee9a7ccd316f1959d54f80e49b9c71f6fcad5e3c3a2dadf312cef00cdd7ef2d09278bb9f2de8dc1438c813f5eaf889021be09b67
data/README.md CHANGED
@@ -28,6 +28,31 @@ fork { POSIX::Mqueue.new("/whatever").send("world") }
28
28
  # Blocks until the forked process pushes to the queue
29
29
  m.receive
30
30
  # => "world"
31
+
32
+ # Deletes the queue and any messages remaining.
33
+ # None in this case. Otherwise the queue will persist till reboot.
34
+ m.unlink
35
+
36
+ # Queue is now full by default Linux settings, see below on how to increase it.
37
+ 10.times { m.send rand(100).to_s }
38
+
39
+ # #send will block until something is popped off the queue, but timedsend takes
40
+ # timeout arguments (first one is seconds, second is nanoseconds). If you don't
41
+ # want to block on send, pass 0 for both:
42
+
43
+ assert_raises POSIX::Mqueue::QueueFull do
44
+ m.timedsend(0, 0, "I will fail")
45
+ end
46
+
47
+ # Empty the queue again
48
+ 10.times { m.receive }
49
+
50
+ # Like timedsend, timedreceive takes timeout arguments and will raise
51
+ # POSIX::Mqueue::Queueempty when it would otherwise block
52
+ assert_raises POSIX::Mqueue::QueueEmpty do
53
+ m.timedreceive(0, 0)
54
+ end
55
+
31
56
  ```
32
57
 
33
58
  ## mqueue
@@ -37,11 +62,14 @@ about the behavior of `posix-mqueue`.
37
62
 
38
63
  ## /proc interfaces
39
64
 
40
- 1. `/proc/sys/fs/mqueue/msg_max`. Contains the maximum number of messages in
41
- queue. Defaults to 10. You should increase that number. `#send` will throw an
42
- exception if the queue is full (instead of blocking).
65
+ Linux has some default limits you can easily change.
66
+
67
+ 1. `/proc/sys/fs/mqueue/msg_max`. Contains the maximum number of messages in a
68
+ single queue. Defaults to 10. You should increase that number. `#send` will
69
+ eventually throw an exception if the queue is full (instead of blocking). It
70
+ does not do that right now.
43
71
  2. `/proc/sys/fs/mqueue/msgsize_max`. Maximum size of a single message. Defaults
44
- to 8192 bytes. `posix-mqueue` defaults to 4096 bytes. You'll be able to
72
+ to 8192 bytes. `posix-mqueue` allows up to 4096 bytes. You'll be able to
45
73
  change this, soon!
46
74
  3. `/proc/sys/fs/mqueue/queues_max`. Maximum number of queues on the system.
47
75
  Defaults to 256. Which is probably enough.
@@ -51,30 +79,35 @@ about the behavior of `posix-mqueue`.
51
79
  The message queue is created as a virtual file system. That means you can mount
52
80
  it:
53
81
 
54
- # sudo mkdir /dev/queue
55
- # sudo mount -t mqueue none /dev/queue
82
+ ```bash
83
+ # sudo mkdir /dev/queue
84
+ # sudo mount -t mqueue none /dev/queue
85
+ ```
56
86
 
57
- Add a queue and a few tasks, count the characters and you'll see it's a total of 19 bytes:
87
+ Add a queue and a few tasks, count the characters (19):
58
88
 
59
- $ irb
60
- > require 'posix/mqueue'
61
- => true
62
- > m = POSIX::Mqueue.new("/queue")
63
- => #<POSIX::Mqueue:0xb8c9fe88>
64
- > m.send "narwhal"
65
- => true
66
- > m.send "walrus"
67
- => true
68
- > m.send "ponies"
69
- => true
70
- > exit
89
+ ```ruby
90
+ $ irb
91
+ > require 'posix/mqueue'
92
+ => true
93
+ > m = POSIX::Mqueue.new("/queue")
94
+ => #<POSIX::Mqueue:0xb8c9fe88>
95
+ > m.send "narwhal"
96
+ => true
97
+ > m.send "walrus"
98
+ => true
99
+ > m.send "ponies"
100
+ => true
101
+ ```
71
102
 
72
103
  Inspect the mounted filesystem:
73
104
 
74
- $ ls /dev/queue/
75
- important mails queue
76
- $ cat /dev/queue/queue
77
- QSIZE:19 NOTIFY:0 SIGNO:0 NOTIFY_PID:0
105
+ ```bash
106
+ $ ls /dev/queue/
107
+ important mails queue
108
+ $ cat /dev/queue/queue
109
+ QSIZE:19 NOTIFY:0 SIGNO:0 NOTIFY_PID:0
110
+ ```
78
111
 
79
112
  Here `QSIZE` is the bytes of data in the queue. The other flags are about
80
113
  notifications which `posix-mqueue` does not support currently, read about them
data/Rakefile CHANGED
@@ -2,6 +2,7 @@ require "bundler/gem_tasks"
2
2
 
3
3
  require 'rake/testtask'
4
4
  Rake::TestTask.new do |t|
5
+ `cd ext/posix && ruby extconf.rb && make`
5
6
  t.libs << "test"
6
7
  t.pattern = "test/**/*_test.rb"
7
8
  end
@@ -4,10 +4,14 @@
4
4
  #include <mqueue.h>
5
5
  #include <fcntl.h>
6
6
  #include <errno.h>
7
+ #include <time.h>
7
8
 
8
9
  #include <stdlib.h>
9
10
  #include <stdio.h>
10
11
 
12
+ VALUE rb_cQueueFull = Qnil;
13
+ VALUE rb_cQueueEmpty = Qnil;
14
+
11
15
  typedef struct {
12
16
  mqd_t fd;
13
17
  struct mq_attr attr;
@@ -68,7 +72,7 @@ VALUE posix_mqueue_unlink(VALUE self)
68
72
  TypedData_Get_Struct(self, mqueue_t, &mqueue_type, data);
69
73
 
70
74
  if (mq_unlink(data->queue) == -1) {
71
- rb_sys_fail("Message queue unlinking failed");
75
+ rb_sys_fail("Message queue unlinking failed, please consume mq_unlink(3)");
72
76
  }
73
77
 
74
78
  return Qtrue;
@@ -89,7 +93,89 @@ VALUE posix_mqueue_send(VALUE self, VALUE message)
89
93
  err = mq_send(data->fd, RSTRING_PTR(message), RSTRING_LEN(message), 10);
90
94
 
91
95
  if (err < 0) {
92
- rb_sys_fail("Message sending failed");
96
+ rb_sys_fail("Message sending failed, please consult mq_send(3)");
97
+ }
98
+
99
+ return Qtrue;
100
+ }
101
+
102
+ VALUE posix_mqueue_timedreceive(VALUE self, VALUE seconds, VALUE nanoseconds)
103
+ {
104
+ int err;
105
+ mqueue_t* data;
106
+ size_t buf_size;
107
+ char *buf;
108
+ struct timespec timeout;
109
+ VALUE str;
110
+
111
+ TypedData_Get_Struct(self, mqueue_t, &mqueue_type, data);
112
+
113
+ if (!RB_TYPE_P(seconds, T_FIXNUM)) {
114
+ rb_raise(rb_eTypeError, "First argument must be a Fixnum");
115
+ }
116
+
117
+ if (!RB_TYPE_P(nanoseconds, T_FIXNUM)) {
118
+ rb_raise(rb_eTypeError, "First argument must be a fixnum");
119
+ }
120
+
121
+ timeout.tv_sec = FIX2ULONG(seconds);
122
+ timeout.tv_nsec = FIX2ULONG(nanoseconds);
123
+
124
+ buf_size = data->attr.mq_msgsize + 1;
125
+
126
+ // Make sure the buffer is capable
127
+ buf = (char*)malloc(buf_size);
128
+
129
+ // TODO: Specify priority
130
+ err = mq_timedreceive(data->fd, buf, buf_size, NULL, &timeout);
131
+
132
+ if (err < 0) {
133
+ if(errno == 110) {
134
+ rb_raise(rb_cQueueEmpty, "Queue empty");
135
+ } else {
136
+ rb_sys_fail("Message sending failed, please consult mq_send(3)");
137
+ }
138
+ }
139
+
140
+ str = rb_str_new(buf, err);
141
+ free(buf);
142
+
143
+ return str;
144
+
145
+ return Qtrue;
146
+ }
147
+
148
+ VALUE posix_mqueue_timedsend(VALUE self, VALUE seconds, VALUE nanoseconds, VALUE message)
149
+ {
150
+ int err;
151
+ mqueue_t* data;
152
+ struct timespec timeout;
153
+
154
+ TypedData_Get_Struct(self, mqueue_t, &mqueue_type, data);
155
+
156
+ if (!RB_TYPE_P(seconds, T_FIXNUM)) {
157
+ rb_raise(rb_eTypeError, "First argument must be a Fixnum");
158
+ }
159
+
160
+ if (!RB_TYPE_P(nanoseconds, T_FIXNUM)) {
161
+ rb_raise(rb_eTypeError, "First argument must be a fixnum");
162
+ }
163
+
164
+ if (!RB_TYPE_P(message, T_STRING)) {
165
+ rb_raise(rb_eTypeError, "Message must be a string");
166
+ }
167
+
168
+ timeout.tv_sec = FIX2ULONG(seconds);
169
+ timeout.tv_nsec = FIX2ULONG(nanoseconds);
170
+
171
+ err = mq_timedsend(data->fd, RSTRING_PTR(message), RSTRING_LEN(message), 10, &timeout);
172
+
173
+ if (err < 0) {
174
+ if(errno == 110) {
175
+ rb_raise(rb_cQueueFull, "Queue full, most likely you wanna bump /proc/sys/fs/mqueue/msg_max from the default maximum queue size of 10.");
176
+ } else {
177
+ rb_sys_fail("Message sending failed, please consult mq_send(3)");
178
+ }
93
179
  }
94
180
 
95
181
  return Qtrue;
@@ -115,7 +201,7 @@ VALUE posix_mqueue_receive(VALUE self)
115
201
  err = mq_receive(data->fd, buf, buf_size, NULL);
116
202
 
117
203
  if (err < 0) {
118
- rb_sys_fail("Message retrieval failed");
204
+ rb_sys_fail("Message retrieval failed, please consult mq_receive(3)");
119
205
  }
120
206
 
121
207
  str = rb_str_new(buf, err);
@@ -146,10 +232,10 @@ VALUE posix_mqueue_initialize(VALUE self, VALUE queue)
146
232
  data->attr = attr;
147
233
  data->queue_len = RSTRING_LEN(queue);
148
234
  data->queue = ruby_strdup(StringValueCStr(queue));
149
- data->fd = mq_open(data->queue, O_CREAT | O_RDWR, S_IRWXU | S_IRWXO | S_IRWXG, &data->attr);
235
+ data->fd = mq_open(data->queue, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, &data->attr);
150
236
 
151
237
  if (data->fd == (mqd_t)-1) {
152
- rb_sys_fail("Failed opening the message queue");
238
+ rb_sys_fail("Failed opening the message queue, please consult mq_open(3)");
153
239
  }
154
240
 
155
241
  return self;
@@ -159,10 +245,15 @@ void Init_mqueue()
159
245
  {
160
246
  VALUE posix = rb_define_module("POSIX");
161
247
  VALUE mqueue = rb_define_class_under(posix, "Mqueue", rb_cObject);
248
+ rb_cQueueFull = rb_define_class_under(mqueue, "QueueFull", rb_eStandardError);
249
+ rb_cQueueEmpty = rb_define_class_under(mqueue, "QueueEmpty", rb_eStandardError);
250
+
162
251
  rb_define_alloc_func(mqueue, posix_mqueue_alloc);
163
252
  rb_define_method(mqueue, "initialize", posix_mqueue_initialize, 1);
164
253
  rb_define_method(mqueue, "send", posix_mqueue_send, 1);
165
254
  rb_define_method(mqueue, "receive", posix_mqueue_receive, 0);
255
+ rb_define_method(mqueue, "timedsend", posix_mqueue_timedsend, 3);
256
+ rb_define_method(mqueue, "timedreceive", posix_mqueue_timedreceive, 2);
166
257
  rb_define_method(mqueue, "unlink", posix_mqueue_unlink, 0);
167
258
  }
168
259
 
@@ -1,5 +1,5 @@
1
1
  module POSIX
2
2
  class Mqueue
3
- VERSION = "0.0.3"
3
+ VERSION = "0.0.4"
4
4
  end
5
5
  end
@@ -45,11 +45,23 @@ class MqueueTest < MiniTest::Unit::TestCase
45
45
  other.unlink
46
46
  end
47
47
 
48
- # def test_send_raises_exception_instead_of_blocking
49
- # 10.times { @queue.send "walrus" }
48
+ def test_timedsend_raises_exception_instead_of_blocking
49
+ 10.times { @queue.timedsend 0, 0, "walrus" }
50
50
 
51
- # assert_raises Exception do
52
- # @queue.send "hi"
53
- # end
54
- # end
51
+ assert_raises POSIX::Mqueue::QueueFull do
52
+ @queue.timedsend(0, 0, "hi")
53
+ end
54
+ end
55
+
56
+ def test_timedreceive_raises_exception_instead_of_blocking
57
+ assert_raises POSIX::Mqueue::QueueEmpty do
58
+ @queue.timedreceive(0, 0)
59
+ end
60
+ end
61
+
62
+ def test_errors_when_queue_name_is_not_slash_prefixed
63
+ assert_raises Errno::EINVAL do
64
+ POSIX::Mqueue.new("notvalid")
65
+ end
66
+ end
55
67
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: posix-mqueue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Eskildsen