Solved QSqlDatabase using SQlite and timing of concurrent write attempts
-
@l3u_ said in QSqlDatabase using SQlite and timing of concurrent write attempts:
I thought about not actually changing anything, but only to send a change request to the server. If everything is fine, the server applies the change and broadcasts it, as it would be done if the change originated from the server.
Good idea.
There are no threads.
(I assume this means ther's a single thread) in that case all requests will be managed one after the other. You might have little control on the order of execution but you can be sure there's no chance of 2 things happening at the same time
-
@VRonin Yes, the program is single-threaded, as well as the handling of client connections. So if I can be sure that each write attempt will be mad one after another, I can simply check if I can do it before I do it. Either, it works and can be done and distributed, or it I can't do it, because it has been done remotely in the very moment the user clicked the "Save" button. This actually should be a rare event, but I definitely have to handle that case.
Thanks for the clarification :-)
-
Threading is a red herring here, you can't run
QSqlDatabase
from different threads anyway. Your problem is how you can provide atomicity of the operation, correct? Well as it happens I'm working on something remotely similar (at lest the technical infra behind it). So I have decided how I would handle that: tokens.An object on the server (doesn't matter if there's a database behind, but let's roll with a db) is assigned a token - that is an identifier of the current state of the object (think of object in this context as a record in the db). So when the client (application) wants to edit something it requests the token for that object from the server, and issues it back alongside with its changes when ready. Now, when the object's updated successfully it's token is re-generated. The idea is that if it so happens that two clients are trying to edit some object on the server, only one of them will succeed, while the server will "know" the other's update request is based on stale data and return back an error message.
-
@VRonin said in QSqlDatabase using SQlite and timing of concurrent write attempts:
(I assume this means ther's a single thread) in that case all requests will be managed one after the other. You might have little control on the order of execution but you can be sure there's no chance of 2 things happening at the same time
That's somewhat misleading, because the network is asynchronous and (quite importantly) has latency. Not everything that is issued from the client happens instantaneously on the server (and vice versa).
-
@kshegunov It's actually about atomic operations. But I think if all write attempts happen one after another, I think I'm safe by always checking if the requested change is possible, am I?
Example:
We have a name entry "foo". The server wants to change it to "bar". The client wants to change it to "whatever". And these two requests happen at the very same time. Now, there are two possibilities:
The server request happens first. I check if we have a "foo" name entry. It's there, and I change it to "bar". Then, the client request is processed. I check if there is a "foo" entry, but there is none – so I tell the client that the change is no more possible and do nothing.
Same for the other order: If the client request is processed first, "foo" is renamed to "whatever", and the server request will fail, because there's no more "foo" name.
Or am I wrong here?!
-
@l3u_ said in QSqlDatabase using SQlite and timing of concurrent write attempts:
Or am I wrong here?!
No, you are correct, and this is indeed the way to do it. I was just trying to provide additional "insight", rather clumsily. In my program the data is entered by people (users), so for me it's not enough simply to tell the user "Sorry dude, somebody beat you to it". I'd have to provide some means for the user to reload the whole piece of data, which can consist of multiple fields. As I'm sending the messages as a whole I'd want to check if any of the fields (i.e. any part of the DB record) got changed in the mean time, not only one single string, or an integer.
-
@kshegunov Okay, nice! Luckily, in my case, I actually can say "bad luck, dude, somebody already changed it" ;-)
-
Hi,
Out of curiosity, why not use a database system that already does that kind of things ? Like a PostgreSQL cluster
@kshegunov IIRC, you can use QSqlDatabase in a multi-threaded setup however, each thread must have its own connection to the database.
-
@SGaist said in QSqlDatabase using SQlite and timing of concurrent write attempts:
@kshegunov IIRC, you can use QSqlDatabase in a multi-threaded setup however, each thread must have its own connection to the database.
Yes, this is exactly what I meant. By the way from, the point of view of the database two connections might as well be 2 separate clients.
-
@SGaist It's a special case ;-)
It's about a program to manage tournaments for a card game. For a normal tournament, it's completely sufficient to have one notebook to manage the registration. For a big tournament, it's nice to have two laptops to registrate people so that the queue won't grow too long.
What I'm doing is a simple network connection so that the registration computers can talk to each other and everybody has the current list of participants.
It's important that the program stays as simple to use as it is at the moment. With SQLite as the backend, it just works out of the box. Nobody using it would want to or even be able to setup a database server before using it.