Database synchronisation - database

I have some problem in system I am developing. I have one python script which first works with a virtulisation software and if that operation succeeds, it writes things to database.
If some exception occurs in the virtulisation software then I can manage all things, but the real problem will occur if inserting in database fails. If insert fails , i will have to revert things in that virtulization software otherwise things will become asynchronous. But problem is, reverting things in that software is not possible all the time.
How to handle things so that i can keep the database in sync with that software? Any middle ware or special application??? Or any logic in programming?

You want two actions in your system (OP: operation in your virt. software; WDB: write to database) to be atomic (either both take place, or none). Kind of a distributed transaction, but your virtualized software does not directly support directly a transactionable behaviour (no rollback). If you could make them part of some distributed transactional system, you'd be done (see eg), but that is often impossible or impractical. Different strategies to attain a pseudo-transactional behaviour depends on the particulars of your scenario. Some examples:
Open TX (transaction in DB)
WDB
OP
If OP succeeded, commit TX, else rollback TX.
Only feasible if what you write to DB does not depend on OP operation (improbable).
OP1 (first phase of the operation: you get the results, but do not alter anything)
Open TX
WDB
OP2 (second phase: you modify the virt. sofware)
Commit TX or rollback
(Steps 4-5 can be switched) This would be a poor's man "Two-phase commit" implementation. Only feasible if you can divide your operation in those two phases.
Open TX
Dummy WDB (write a dummy result to DB)
Rollback TX
OP
WDB
This checks that the DB is operational, doing a dummy writing before attempting the real operation and writing. Feasible, but not foolproof.
OP
WDB
If fail: save data to a raw file, log error, send mail to IT, turn red lights on.
Sound pathetic... but sometimes it's the only feasible way.

Related

Detect a power failure on a PC using C programming

I want to detect a power failure on a PC using C programming, there are few functions for CTRL_LOG_OFF , CTRL_SHUTDOWN etc in wincon.h .. how to handle unexpected power failure using c programming?
The only way to recover from an unexpected power failure is to regularly safe state data so either your program can a) just restart when the system is operational again, or b) can recover when the system is operational again.
When a power failure occurrs, the system just stops. Sometimes, hard disks manage to flush their internal cache buffers so the filesystem is consistent. But in general, there is insufficient power left for the system to "shutdown" or even to let your program know the power went off. And even, when it could tell your program, and can tell all the other 100 programs running on you system, there won't be enough power to let these do any action to be able to recover later. At best the system could dump memory and state to the hibernate file, but even for that there won't be enough power.
However, if you system is a laptop with battery, Windows will tell tour program it changed power status. The program receives the WM_POWERBROADCAST message for this. Then check the wParam parameter for the type of change. See Windows documentation for this message.
When a computer looses power, the CPU (along with all other system peripherals) will also loose power and fail to continue executing instructions. Hence, C (or any other language) code cannot be relied upon to catch such a catastrophic event, let alone take any action as the event occurs.
A common method is to note the status of a program in a file. For example, when the program initializes, it could write a "running" status to the file. When the program terminates, it would write a "terminated" status to the file. This would also allow the program to check the file status prior to initialization to see if the program terminated normally previously.
Update:
What does SIGPWR do in Linux?
The SIGPWR signal indicates a change in the system's power status.
For example, a SIGPWR signal might issued by a processes associated with an "uninterruptible power supply" (UPS) that supplies power to the Linux system. The same (UPS) process writes status information to the file:
/var/run/powerstatus (or the now deprecated, /etc/powerstatus). The one letter value of this file will indicate the state of the system's power. States include:
'F' Failing power. UPS is providing emergency power from its battery backup due to an external (or building) power failure.
'L' Low power. UPS is providing emergency power from its battery backup due to an external (or building) power failure. However the UPS battery backup is critical low. The system should shut-down immediately (within the next two minutes).
'O' Power OK. External (or building) power has been restored.
Other examples of SIGPWR might be associated with a system that has multiple (backup/redundant) power supplies, or a laptop that has its own battery power supply.

sqlite3/C transaction begin end -- overflow?

In C on an embedded system (where memory is an issue), trying to optimize performance, multiple inserts are combined into larger transactions.
Intuitively, SQLITE must keep the unsent transactions in a cache somewhere in the limited memory.
Is it possible to have too many inserts between two calls of 'BEGIN TRANSACTION' and 'END TRANSACTION'? Can the cache overflow?
Or, does sqlite3 take care of it and initiate a transaction before a overflow happens?
If the cache may overflow, what is the best strategy to call BEGIN/END?
Any changes you make are written to the database file. To support rollbacks, the old contents of the changed database pages are saved in the journal file.
When you commit a transaction, the journal file is just deleted; when you roll back a transaction, those pages are written back.
So there is not limit on the size of the data in a transaction, as long as you have enough disk space.
(The cache can help with avoiding some writes, but it works transparently and does not affect the semantics of your code.)

What are the reasons to check for error on close()?

Note: Please read to the end before marking this as duplicate. While it's similar, the scope of what I'm looking for in an answer extends beyond what the previous question was asking for.
Widespread practice, which I tend to agree with, tends to be treating close purely as a resource-deallocation function for file descriptors rather than a potential IO operation with meaningful failure cases. And indeed, prior to the resolution of issue 529, POSIX left the state of the file descriptor (i.e. whether it was still allocated or not) unspecified after errors, making it impossible to respond portably to errors in any meaningful way.
However, a lot of GNU software goes to great lengths to check for errors from close, and the Linux man page for close calls failure to do so "a common but nevertheless serious programming error". NFS and quotas are cited as circumstances under which close might produce an error but does not give details.
What are the situations under which close might fail, on real-world systems, and are they relevant today? I'm particularly interested in knowing whether there are any modern systems where close fails for any non-NFS, non-device-node-specific reasons, and as for NFS or device-related failures, under what conditions (e.g. configurations) they might be seen.
Once upon a time (24 march, 2007), Eric Sosman had the following tale to share in the comp.lang.c newsgroup:
(Let me begin by confessing to a little white lie: It wasn't
fclose() whose failure went undetected, but the POSIX close()
function; this part of the application used POSIX I/O. The lie
is harmless, though, because the C I/O facilities would have
failed in exactly the same way, and an undetected failure would
have had the same consequences. I'll describe what happened in
terms of C's I/O to avoid dwelling on POSIX too much.)
The situation was very much as Richard Tobin described.
The application was a document management system that loaded a
document file into memory, applied the user's edits to the in-
memory copy, and then wrote everything to a new file when told
to save the edits. It also maintained a one-level "old version"
backup for safety's sake: the Save operation wrote to a temp
file, and then if that was successful it deleted the old backup,
renamed the old document file to the backup name, and renamed the
temp file to the document. bak -> trash, doc -> bak, tmp -> doc.
The write-to-temp-file step checked almost everything. The
fopen(), obviously, but also all the fwrite()s and even a final
fflush() were checked for error indications -- but the fclose()
was not. And on one system it happened that the last few disk
blocks weren't actually allocated until fclose() -- the I/O
system sat atop VMS' lower-level file access machinery, and a
little bit of asynchrony was inherent in the arrangement.
The customer's system had disk quotas enabled, and the
victim was right up close to his limit. He opened a document,
edited for a while, saved his work thus far, and exceeded his
quota -- which went undetected because the error didn't appear
until the unchecked fclose(). Thinking that the save succeeded,
the application discarded the old backup, renamed the original
document to become the backup, and renamed the truncated temp
file to be the new document. The user worked a little longer
and saved again -- same thing, except you'll note that this time
the only surviving complete file got deleted, and both the
backup and the master document file are truncated. Result: the
whole document file became trash, not just the latest session
of work but everything that had gone before.
As Murphy would have it, the victim was the boss of the
department that had purchased several hundred licenses for our
software, and I got the privilege of flying to St. Louis to be
thrown to the lions.
[...]
In this case, the failure of fclose() would (if detected) have
stopped the delete-and-rename sequence. The user would have been
told "Hey, there was a problem saving the document; do something
about it and try again. Meanwhile, nothing has changed on disk."
Even if he'd been unable to save his latest batch of work, he would
at least not have lost everything that went before.
Consider the inverse of your question: "Under what situations can we guarantee that close will succeed?" The answer is:
when you call it correctly, and
when you know that the file system the file is on does not return errors from close in this OS and Kernel version
If you are convinced that you program doesn't have any logic errors and you have complete control over the Kernel and file system, then you don't need to check the return value of close.
Otherwise, you have to ask yourself how much you care about diagnosing problems with close. I think there is value in checking and logging the error for diagnostic purposes:
If a coder makes a logic error and passes an invalid fd to close, then you'll be able to quickly track it down. This may help to catch a bug early before it causes problems.
If a user runs the program in an environment where close does return an error when (for example) data was not flushed, then you'll be able to quickly diagnose why the data got corrupted. It's an easy red flag because you know the error should not occur.

c linux msync(MS_ASYNC) flush order

Is the order of page flushes with msync(MS_ASYNC) on linux guaranteed to be the same as the order the pages where written to?
If it depends on circumstances, is there a way for me (full server access) to make sure they are in the same order?
Background
I'm currently using OpenLDAP Symas MDB as a persistent key/value storage and without MDB_MAPASYNC - which results in using msync(MS_ASYNC) (I looked through the source code) - the writes are so slow, that even while processing data a single core is permanently waiting on IO at sometimes < 1MB/s. After analyzing, the problem seems to be many small IO Ops. Using MDB_MAPASYNC I can hit the max rate of my disk easily, but the documentation of MDB states that in that case the database can become corrupted. Unfortunately the code is too complex to me/I currently don't have the time to work through the whole codebase step by step to find out why this would be, and also, I don't need many of the features MDB provides (transactions, cursors, ACID compliance), so I was thinking of writing my own KV Store backed by mmap, using msync(MS_ASYNC) and making sure to write in a way that an un-flushed page would only lose the last touched data, and not corrupt the database or lose any other data.
But for that I'd need an answer to my question, which I totally can't find by googling or going through linux mailing lists unfortunately (I've found a few mails regarding msync patches, but nothing else)
On a note, I've looked through dozens of other available persistent KV stores, and wasn't able to find a better fit for me (fast writes, easy to use, embedded(so no http services or the like), deterministic speed(so no garbage collection or randomly run compression like leveldb), sane space requirements(so no append-only databases), variable key lengths, binary keys and data), but if you know of one which could help me out here, I'd also be very thankful.
msync(MS_ASYNC) doesn't guarantee the ordering of the stores, because the IO elevator algos operating in the background try to maximize efficiency by merging and ordering the writes to maximize the throughput to the device.
From man 2 msync:
Since Linux 2.6.19, MS_ASYNC is in fact a no-op, since the kernel properly tracks dirty pages and flushes them to storage as necessary.
Unfortunately, the only mechanism to sync a mapping with its backing storage is the blocking MS_SYNC, which also does not have any ordering guarantees (if you sync a 1 MiB region, the 256 4 KiB pages can propagate to the drive in any order -- all you know is that if msync returns, all of the 1 MiB has been synced).

Very slow open() (six seconds plus) on full UFS just starting to undergo a mass delete?

We have a UFS partition on solaris.
The volume becomes full. We're still trying to write to it - and naturally open() returns -1 immediately.
When a cronjob fires up which does a mass delete, it looks like open() doesn't return in a timely manner - it's taking at least six seconds, because that's how long before the watchdog kills the process.
Now, the obvious thought is that the deletes are keeping the file system busy and open() just takes forever...but is there any concrete knowledge out there about this behaviour?
Perhaps the program doing the 'mass delete' could be changed to operate more smoothly on a filesystem that's having problems. If it does queries to find the files to delete, it might not be the open call that's timing out. To test the theory, is there some way to set up a cron job which simply removes a single file with a known name during the disk-full state? How does the 'mass delete' program decide what 'open' call to make?
It's also possible to control the percentage of disk utilization before writes stop working. You could also try setting this to a lower percentage. If you are detecting the 'disk full' state by waiting until a file-creation step returns -1, then you should consider adding an explicit check to your code so that if the filesystem is over a certain percentage full, take corrective action.
Mass delete causes a storm of random IO which really hurts performance. And it makes as much of journal/log transactions to commit (try with the nologging option ?). Moreover, if your fs is nearly full, open would anyway takes some time to find space for a new inode.
Deleting files more often, fewer at a time, may help you to get lower response time. Or simply delete them slower, sleeping between rm.

Resources