posix-mqueue 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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