How to implement multithreading in Libsoup server? - c

I want to implement multithreading in Libsoup server such that every time when a client request comes, a new thread will be created to serve that request.
How can I implement this using the Libsoup and GLib libraries?
My current server main code is like this:
sending_file = fopen("abc/project_foo.zip", "r");
fseek(sending_file, 0L, SEEK_END);
size_of_file = ftell(sending_file);
fseek(sending_file, 0L, SEEK_SET);
int port = 15000;
server = soup_server_new(SOUP_SERVER_RAW_PATHS,TRUE,SOUP_SERVER_PORT,port, SOUP_SERVER_SERVER_HEADER,"simple-httpd",NULL);
soup_server_add_handler(server , "/foo" , server_callback, NULL , NULL);
soup_server_run_async (server);
printf("Waiting for Requests...\n");
//Running a main loop so Async will work
GMainLoop *loop;
loop = g_main_loop_new (NULL, TRUE);
g_main_loop_run (loop);
return 0;

Create a new thread in the callback you pass to soup_server_add_handler. The manual explains the rest; the relevant part:
By default, libsoup assumes that you have completely finished processing the message when you return from the callback, and that it can therefore begin sending the response. If you are not ready to send a response immediately (eg, you have to contact another server, or wait for data from a database), you must call soup_server_pause_message on the message before returning from the callback. This will delay sending a response until you call soup_server_unpause_message. (You must also connect to the finished signal on the message in this case, so that you can break off processing if the client unexpectedly disconnects before you start sending the data.)
So make sure you call soup_server_pause_message in the callback you pass to soup_server_add_handler, then when you're done processing the request in your thread call soup_server_unpause_message.
Instead of creating a new thread for each request you might want to think about using a thread pool, but the idea is pretty much the sameā€”just add a task to the pool instead of creating a new thread.

Related

Low Level DBus C API main loop

When trying to use a callback function for a DBus reply I get stuck on creating a good/well working main loop.
What I want to do is simple, make a DBus call and specify a function which should be called when the reply comes. This is because I do not want to block my thread for the whole time until a reply has been calculated and arrived.
I first use dbus_connection_send_with_reply(..) to get a DBusPendingCall, then i specify a callback function using dbus_pending_call_set_notify(..). Before doing this, when connecting to the bus, I have started another thread which should wait for a response and call the callback functions. I have found no examples at all and no very good documentation of how I should design a dbus main-loop like this. I have tried:
// Main dbus loop handling data transfer and callbacks..
void *dbus_main(void *args)
{
my_dbus dbus = (my_dbus)args;
while (MY_DBUS_STATUS_STOPPING != dbus->status
&& dbus_connection_read_write_dispatch(dbus->conn, -1))
;
return 0;
}
// Start the dbus main loop in a new thread
void dbus_main_start(my_dbus dbus) {
if (!pthread_create(&dbus->th, NULL, dbus_main, dbus)) {
// PRINT ERROR
}
}
My problem is two things:
I try to stop the app by setting the dbus->status flag to MY_DBUS_STATUS_STOPPING and waiting for the threads to join. This does not work if the thread is blocked in the dbus_connection_read_write_dispatch(..) function. If i want the app to stop fast then I need to specify a very short timeout. Can't I wake the blocked thread in some other way?
More seriously, with this code i don't get any callback from the method I call. If I add some fprintf(..) to write to stdout I might suddenly get my callback. It seems quite random, so maybe some kind of deadlock? I have tried having a dbus_connection_flush(..) between sending the message and adding the callback with _set_notify(..) function. Doesn't do any difference... But printing some letters to stdout in the same place fixes the problem. Printing to stdout in the dbus-main-loop insted of an empty ";" seems to do the trick sometimes...
So anyone who has an example of using the low-level dbus api together with async methods, ie not using _block(..)??
You can create a simple DBus application as follows...
To setup a server to handle incoming messages, call dbus_connection_register_object_path passing in a VTable containing function pointers to handle the messages. Such as:
{ .unregister_function = UnregisteredMessage, .message_function = ServiceMessage }
To send a new message, call dbus_connection_send_with_reply and then dbus_pending_call_set_notify to associate a callback function to handle the reply.
Next you will need to service DBus. This can be done in a separate thread or by calling periodically with non-blocking calls in the same thread, as shown below:
/* Non-blocking read of the next available message */
dbus_connection_read_write ( MyDBusConnection, 0 ) ;
while ( dbus_connection_get_dispatch_status ( MyDBusConnection ) == DBUS_DISPATCH_DATA_REMAINS )
{
dbus_connection_dispatch ( MyDBusConnection ) ;
}
There are some good example of using the DBUS C API here: http://www.matthew.ath.cx/misc/dbus
It is highly recommended that you use a D-Bus library other than libdbus, as libdbus is fiddly to use correctly, as you are finding. If possible, use GDBus or QtDBus instead, as they are much higher-level bindings which are easier to use. If you need a lower-level binding, sd-bus is more modern than libdbus.
If you use GDBus, you can use GMainLoop to implement a main loop. If you use sd-bus, you can use sd-event.

C Multithreading - Sqlite3 database access by 2 threads crash

Here is a description of my problem:
I have 2 threads in my program. One is the main thread and the other one that i create using pthread_create
The main thread performs various functions on an sqlite3 database. Each function opens to perform the required actions and closing it when done.
The other thread simply reads from the database after a set interval of time and uploads it onto a server. The thread also opens and closes the database to perform its operation.
The problem occurs when both threads happen to open the database. If one finishes first, it closes the database thus causing the other to crash making the application unusable.
Main requires the database for every operation.
Is there a way I can prevent this from happening? Mutex is one way but if I use mutex it will make my main thread useless. Main thread must remain functional at all times and the other thread runs in the background.
Any advice to make this work would be great.
I did not provide snippets as this problem is a bit too vast for that but if you do not understand anything about the problem please do let me know.
EDIT:
static sqlite3 *db = NULL;
Code snippet for opening database
int open_database(char* DB_dir) // argument is the db path
rc = sqlite3_open(DB_dir , &db);
if( rc )
{
//failed to open message
sqlite3_close(db);
db = NULL;
return SDK_SQL_ERR;
}
else
{
//success message
}
}
return SDK_OK;
}
And to close db
int close_database()
{
if(db!=NULL)
{
sqlite3_close(db);
db = NULL;
//success message
}
return 1;
}
EDIT: I forgot to add that the background thread performs one single write operation that updates 1 field of the table for each row it uploads onto the server
Have your threads each use their own database connection. There's no reason for the background thread to affect the main thread's connection.
Generally, I would want to be using connection pooling, so that I don't open and close database connections very frequently; connection opening is an expensive operation.
In application servers we very often have many threads, we find that a connection pool of a few tens of connections is sufficient to service requests on behalf of many hundreds of users.
Basically built into sqlite3 there are mechanisms to provide locking... BEGIN EXCLUSIVE then you can also register a sleep callback so that the other thread can do other things...
see sqlite3_busy_handler()

Looping over byte channels

While reading from the good-old InputStream, I used the following code(with which I was never comfortable) :
int read = 0;
InputStream is = ....;
while((i = is.read() != -1){
....
}
Now I'm trying to read 10MB from an InputStream using NIO :
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("In Controller.doPost(...)");
ByteBuffer chunk = ByteBuffer.allocateDirect(1000000);
/* Source channel */
int numRead = 0;
ReadableByteChannel rbc = Channels.newChannel(request.getInputStream());
/* Destination channel */
File destFile = new File(
"D:\\SegyDest.sgy");
FileOutputStream destFileFos = new FileOutputStream(destFile);
FileChannel destFileChannel = destFileFos.getChannel();
/* Read-Write code */
while (numRead >= 0) {
chunk.rewind();
numRead = rbc.read(chunk);
System.out.println("numRead = " + numRead);
chunk.rewind();
destFileChannel.write(chunk);
}
/* clean-up */
rbc.close();
destFileChannel.close();
destFileFos.close();
request.setAttribute("ops", "File Upload");
request.getRequestDispatcher("/jsp/Result.jsp").forward(request,
response);
}
My question is /* How to loop over the source channel to read all the bytes ? */
OR perform IO in chunks of more than 1 byte the API like so:
byte[] bA = new byte[4096];
int i;
InputStream is = ....;
OutputStream os = ....;
while((i = is.read(bA) != -1){
os.write(bA, 0, i);
}
I've looked at your other question and my comments still stand. NIO is not the solution you are looking for. You have a low end machine with limits RAM acting as a proxy.
The best you can do is have your Servlet create a new thread, have this thread create and setup an outgoing connection using NIO sockets/HTTP-libraries. This new (and extra) thread is waiting on any of 3 things to happen and it pushes whatever APIs to try and make progress in these 3 areas.
The 3 things are:
Trying to write data to the remote server (if there is buffered in memory data to send)
Waiting for the main Servlet thread to indicate there is new data in the shared buffer. Or that End-of-stream was reached.
Waiting for the main Servlet thread to indicate the extra thread needs to shutdown (this is error recovery and cleanup).
You probably need a drainWithTimeout(long millis) function that the doPost() method calls on the extra thread to give it an amount of time to push the final data to the remote server. This gets called when an End-of-Stream if observed by the Servlet from the InputStream.
You MUST ensure your extra thread is 100% reliably reaped before the doPost() method returns. So controlling startup/shutdown of it is important, especially in the scenarios that the InputStream had an error because the sending client disconnected or was idle too long.
Then two threads (the normal Servlet thread in doPost() and the new thread you create) would setup and share some arbitrary memory buffer, maybe 16Mb or more that is shared.
If you can not have a 16Mb buffer due to limitations in clients/concurrent-users and 2Gb RAM then you really should stick with the example code at the top of this answer, since the network and the O/S kernels will already buffer some Mb's of data.
The point of using two threads is that you can not fix the issue that the Servlet API receiving the data is a blocking I/O API, you can not change that if you are writing the application to conform to Servlet specification/standards. If you know your specific Servlet container has a feature then that is outside the scope of this answer.
The two threads allow the main Servlet doPost thread to be in control and STILL use a blocking I/O API for InputStream.
There is no point using one thread and a blocking InputStream with a non-blocking OutputStream, you still have the problem that you can not service the output stream while the in.read() API call is blocked (waiting for more data or End-of-stream).
The correct way to copy between NIO channels is as follows:
while (in.read(buffer) > 0 || buffer.position() > 0)
{
buffer.flip();
out.write(buffer);
buffer.compact();
}
Note that this automatically takes care of EOS, partial reads, and partial writes.

Multi-clients on a server

For an application in C, i need to response more than one clients.
I setup the connection with a code like,
bind(...);
listen(...);
while(1){
accept(...);//accept a client
recv(...);//receive something
send(...);//send something to client
bzero(buf);//clear buffer
}
This works great when i have only one client. Other clients also can connect to the server but although they command something, server does not response back to clients who connected after the first client. How can i solve this problem?
Write a server using asynchronous, nonblocking connections.
Instead of a single set of data about a client, you need to create a struct. Each instance of the struct holds the data for each client.
The code looks vaguely like:
socket(...)
fcntl(...) to mark O_NONBLOCK
bind(...)
listen(...)
create poll entry for server socket.
while(1) {
poll(...)
if( fds[server_slot].revents & POLLIN ) {
accept(...)
fcntl(...) mark O_NONBLOCK
create poll and data array entries.
}
if( fds[i].revents & POLLIN ) {
recv(...) into data[i]
if connection i closed then clean up.
}
if( fds[i].revents & POLLOUT ) {
send(...) pending info for data[i]
}
}
If any of your calls return the error EAGAIN instead of success then don't panic. You just try again later. Be prepared for EAGAIN even if poll claims the socket is ready: it's good practice and more robust.
i need to response more than one clients.
Use Threading.
Basically you want your main thread to only do the accept part, and then handle the rest to another thread of execution (which can be either a thread or a process).
Whenever your main thread returns from "accept", give the socket descriptor to another thread, and call accept again (this can be done with fork, with pthread_create, or by maintaining a thread pool and using synchronization, for instance condition variables, to indicate that a new client has been accepted).
While the main thread will handle possible new clients incoming, the other threads will deal with the recv/send.

Silverlight web service callback performance

I have a silverlight client that communicates with a web service on a server. It has a DoSomething method that does nothing and returns void.
On the client, I call the service and listen to when the response comes back:
proxy.OnDoSomethingCompleted+=OnDoSomethingCompleted;
t0 = Environment.TickCount;
proxy.DoSomethingAsync();
void DoSomething(..)
{
t1 = Environment.TickCount;
}
Network capture indicates the response is sent back within 2ms. However, OnDoSomethingCompleted is not called until 80ms later. Is there a way to change when the callback is executed?
Normally, OnDoSomethingCompleted() would be executed on the UI thread, i.e., behind the scenes, something is calling some code that (conceptually) looks a little like this:
Dispatcher.BeginInvoke(() => OnDoSomethingCompleted());
This means that OnDoSomethingCompleted() won't get executed until the UI thread decides to cooperate and run it. Most of the time that's fine, but there can be times when you want it to run faster. The basic approach is to use a thread pool to make the original call, which means that the response will get handled from the same thread pool (not necessarily ont he same thread). If you can do some real processing in this return method, and don't just automatically marshal it back onto the UI thread, this can speed up your processing somewhat.
Tomek (from the MS WCF team) gives a good example of how do this here:
http://tomasz.janczuk.org/2009/08/improving-performance-of-concurrent-wcf.html
It's also my understanding that the synchronization context for the WCF connection gets set when you first open it. This means that whatever thread the WCF connection is first opened on is the one that will handle all later calls. So in my own code, I do something like this:
// Spin up the connection on a new worker thread.
// According to Tomek, this will cause all WCF calls to be made from this thread.
ManualResetEvent resetEvent = new ManualResetEvent(false);
wcfWorkerThread = new Thread(new ThreadStart(() => InitializeNotificationClient(resetEvent)));
wcfWorkerThread.Name = "WcfWorkerThread";
wcfWorkerThread.Start();
resetEvent.WaitOne();
And then InitializeNotificationClient() looks something like this:
private void InitializeNotificationClient(ManualResetEvent resetEvent = null)
{
try
{
notificationClient = GetRoomServiceClient();
notificationClient.OpenAsync(callback);
notificationClient.InnerChannel.Faulted += new EventHandler(Channel_Faulted);
notificationClient.InnerChannel.Closed += new EventHandler(Channel_Closed);
}
finally
{
// Tell the waiting thread that we're ready.
if (resetEvent != null)
{
resetEvent.Set();
}
}
}

Resources