Do UNIX message queues maintain order of messages? - unix

If, under UNIX/Linux/BSD/OSX, I use this sequence of APIs in Application A:
msgq_id = mq_open( full_queue_name,
O_RDWR | O_CREAT,
S_IRWXU | S_IRWXG,
&msgq_attr);
mq_send(msgq_id, ptrData1, len1, 0);
mq_send(msgq_id, ptrData2, len2, 0);
...
and this sequence of events in Application B:
mqd_t open_res = mq_open(full_queue_name, O_RDONLY);
...
mq_receive(...)
mq_receive(...)
... do I have a guarantee that the message queue maintains the order of the messages?
That is, that Application B will receive the data from ptrData1 first, and then the data from ptrData2?

From man mq_send on linux (emphasis added):
The msg_prio argument is a non-negative integer that specifies the priority of this message. Messages are placed on the queue in decreasing order of priority, with newer messages of the same priority being placed after older messages with the same priority.
So yes, you have a guarantee.

You get message that is oldest one of highest priority. So if you send all with same priority, you always receive them in same order.

Related

RabbitMQ DLQ: How to reprocess all messages in sequence of arrival across multiple queues?

I am stuck with an issue where lot of messages have reached several rabbitMQ dead-letter queues. I have never had to reprocess bulk messages from DLQs earlier. The requirement now is to reprocess all these messages but in the exact sequence how they were pushed, irrespective of which DLQ it was. Is there a way to group all these failed messages from across all the DLQs and then process them one by one in FIFO basis?
Example:
Event1.DLQ: Message1 at T[1], Message2 at T[3]
Event2.DLQ: Message1 at T[2], Message2 at T[5]
Event3.DLQ: Message1 at T[4], Message2 at T[6]
(T[n] -> Timestamp; T[n] is less than T[n+1])
I would like to combine the failed messages from all these 3 DLQs into a common queue and reprocess them in the following sequence one by one (in order of Time):
Event1.Message1, Event2.Message1, Event1.Message2, Event3.Message1, Event2.Message2, Event3.Message2
Not sure if this question is too naïve, any help is appreciated.

Telegram API: How do I get messages from a public channel, which I am not participant of?

I am able to successfully retrieve messages from a channel via channels.getMessages request, once I know their message IDs. I find channel id by contacts.search, by the way.
At the moment, mesage IDs are consequtive integers, so getting max_id would solve the issue.
I am sure it possible, since official clients do this (view a channel without joining it). I will try to find out how official desktop app does this by reading its sources, but any help will be much appreciated.
I need this because am writing a simple public telegram channel -> rss/web interface.
Please do not confuse Telegram Client API with Telegram Bot API. Bot API allows to receive 'push' messages on new messages, but no 'reading historical logs'.
Here are the steps you have to do in order to get messages from a channel you're not joined:
Resolve the username into ID and access_hash with contacts.resolveUsername
Invoke messages.getHistory to get your desired messages
Here is a short description of messages.getHistory parameters:
peer: The channel from whom to retrieve the message history
limit: Number of messages to be retrieved
offset_date: Offset date (messages *previous* to this date will be retrieved)
offset_id: Offset message ID (only messages *previous* to the given ID will be retrieved)
max_id: All the messages with a higher (newer) ID or equal to this will be excluded
min_id: All the messages with a lower (older) ID or equal to this will be excluded
add_offset: Additional message offset (all of the specified offsets + this offset = older messages)
It turns out messages.getHistory is just okay, gives you last N messages + total count.

MCP2515 OBD II multiple PID

I am using a raspberry Pi and arduino CAN schield which is using a MCP2515 and SPI to request a single OBD II PID.
I am able to request and receive a single PID from my OBD emulator (Freematics). I know that is possible to request multiple PIDs (up to 6 PIDs) in a single query.
Whenever I use other kind of messages, I receive only the first request. Can anybody maybe help?
Here is the message for single PID which is working (C++):
msg.id = 0x7DF; //ID_QUERY
msg.header.rtr = 0;
msg.header.length = 0x08;
msg.data[0] = 0x02;
msg.data[1] = 0x01;
msg.data[2] = PID; //Whatever PID I want!
Message for multiple request that is not working:
msg.id = 0x7DF; //ID_QUERY
msg.header.rtr = 0;
msg.header.length = 0x08;
msg.data[0] = 0x07; //! Also it is not working with 0x08
msg.data[1] = 0x01;
msg.data[2] = PID0;
msg.data[3] = PID1;
msg.data[4] = PID2;
msg.data[5] = PID3;
msg.data[6] = PID4;
msg.data[7] = PID5;
Our Freematics OBD II emulator does not support sending multiple responses. One of our test vehicles, a 2010 Toyota corolla does. In our experience it is best to send a test command at startup to see if the device we're communicating with supports multiple responses or not. For our application we send the command 00 twice,
010000
If the response its greater than 25 characters, we know the device supports multiple commands as it responded to both 00 commands. If the response is less than 25 characters, we know the device responded to just the first 00 command and consequently only supports one command at a time. checking how many responses were received could be done multiple ways, but length has worked well for us so far.
Based on your use case, it may be enough to only send single commands. But if you really need the increased speed of multiple commands, add a check at start up to see if the device responds to multiple commands and then construct your messages based on the results. Dont forget to end your messages with the expected number of response lines to further increase speed. See the attached taken from: http://elmelectronics.com/DSheets/ELM327DS.pdf
Sending canbus messages through mcp2515 is a litle bit tricky.
First of all Freematics OBD Emulator support no multiple PID requests. Secondly, the multiple PID request should be sent with ISO 15765 format. when you send a multiple request, he ECU would response only with one "First Frame" message and will wait for the "Flow Control" message from the sender. After receiving the flow control, ECU will continue to sending the responses based on your flow control setting.
For more information about the CAN-Bus messages and how "First Frame" and "Single Frame" works, read the below links:
googleBooks, ISO_15765-2, hackaday (dot) com

IPCS message passing related queries

I am dealing with Message Passing IPCS method. I do have few question regarding this:
KEY field in ipcs -q shows me 0x00000000 what does this means ?
Can i see what messsage is passes using msqid ?
If two entries are present (for a particular user) after executing command ipcs -q. Does this means that two messages were passed by this particular user ?
If used-bytes and message fields are set as 0 what does this mean?
Is there away to see if message queue is full or not?
How many queues can we have for one particular user?
I tried goggling, but was not able to find answer to these questions.
Please help
1. The "key" field of the Shared memory segments is usually 0x00000000. This indicates the IPC_PRIVATE key specified during creation of the shared memory segment. The manual of shmget() contains more details.
2. AFAIK, this cannot be done. If any msg is "de-queued" from the msgQ, then the intended receiver will not see it.
3. The 2 entries in the list of message queues indicates that there are currently 2 active message queues on the system identified by their corresponding unique keys.
Creating additional msgQ : ipcmk -Q
Deleting an existing msgQ : ipcrm -Q <unique-key>
4. The used-bytes and messages fields set to 0 indicate that currently no transfers have occurred using that particular msgQ.
5. Currently one way to do this to obtain the number of msgs currently queued-up in the msgQ programmatically as shown in the following C snippet. Next this can be compared with the size of the msgQ as demonstrated in this answer.
int ret = msgctl(msqid, IPC_STAT, &buf);
uint msg = (uint)(buf.msg_qnum);
printf("msgs in Q = %u\n", msg);
6. There exists a limit on the total memory used by all the msgQs on the system combined together. This can be obtained by ulimit -q. The amount of bytes used in a msgQ is listed under the used-bytes column in the output of ipcs -Q. The total number of msgQs is limited only by the amount of memory available to create a new msgQ from the msgQ memory pool limit seen above.
Also checkout the latter part of this answer for a few sample operations on POSIX message queues.

OpenBSD serial I/O: -lpthead makes read() block forever, even with termios VTIME set?

I have an FTDI USB serial device which I use via the termios serial API. I set up the port so that it will time-out on read() calls in half a second (by using the VTIME parameter), and this works on Linux as well as on FreeBSD. On OpenBSD 5.1, however, the read() call simply blocks forever when no data is available (see below.) I would expect read() to return 0 after 500ms.
Can anyone think of a reason that the termios API would behave differently under OpenBSD, at least with respect to the timeout feature?
EDIT: The no-timeout problem is caused by linking against pthread. Regardless of whether I'm actually using any pthreads, mutexes, etc., simply linking against that library causes read() to block forever instead of timing out based on the VTIME setting. Again, this problem only manifests on OpenBSD -- Linux and FreeBSD work as expected.
if ((sd = open(devPath, O_RDWR | O_NOCTTY)) >= 0)
{
struct termios newtio;
char input;
memset(&newtio, 0, sizeof(newtio));
// set options, including non-canonical mode
newtio.c_cflag = (CREAD | CS8 | CLOCAL);
newtio.c_lflag = 0;
// when waiting for responses, wait until we haven't received
// any characters for 0.5 seconds before timing out
newtio.c_cc[VTIME] = 5;
newtio.c_cc[VMIN] = 0;
// set the input and output baud rates to 7812
cfsetispeed(&newtio, 7812);
cfsetospeed(&newtio, 7812);
if ((tcflush(sd, TCIFLUSH) == 0) &&
(tcsetattr(sd, TCSANOW, &newtio) == 0))
{
read(sd, &input, 1); // even though VTIME is set on the device,
// this read() will block forever when no
// character is available in the Rx buffer
}
}
from the termios manpage:
Another dependency is whether the O_NONBLOCK flag is set by open() or
fcntl(). If the O_NONBLOCK flag is clear, then the read request is
blocked until data is available or a signal has been received. If the
O_NONBLOCK flag is set, then the read request is completed, without
blocking, in one of three ways:
1. If there is enough data available to satisfy the entire
request, and the read completes successfully the number of
bytes read is returned.
2. If there is not enough data available to satisfy the entire
request, and the read completes successfully, having read as
much data as possible, the number of bytes read is returned.
3. If there is no data available, the read returns -1, with errno
set to EAGAIN.
can you check if this is the case?
cheers.
Edit: OP traced back the problem to a linking with pthreads that caused the read function to block. By upgrading to OpenBSD >5.2 this issue was resolved by the change to the new rthreads implementation as the default threading library on openbsd. more info on guenther# EuroBSD2012 slides

Resources