java - write two files atomically - java

I am facing a problem for which I don't have a clean solution. I am writing a Java application and the application stores certain data in a limited set of files. We are not using any database, just plain files. Due to some user-triggered action, certain files needs to be changed. I need this to be a all-or-nothing operation. That is, either all files are updated, or none of them. It is disastrous if for example 2 of the 5 files are changed, while the other 3 are not due to some IOException.
What is the best strategy to accomplish this?
Is embedding an in-memory database, such as hsqldb, a good reason to get this kind of atomicity/transactional behavior?
Thanks a lot!

A safe approach IMO is:
Backup
Maintain a list of processed files
On exception, restore the ones that have been processed with the backed up one.
It depends on how heavy it is going to be and the limits for time and such.

What is the best strategy to accomplish this? Is embedding an in-memory database, such as hsqldb, a good reason to get this kind of atomicity/transactional behavior?
Yes. If you want transactional behavior, use a well-tested system that was designed with that in mind instead of trying to roll your own on top of an unreliable substrate.
File systems do not, in general, support transactions involving multiple files.
Non-Windows file-systems and NTFS tend to have the property that you can do atomic file replacement, so if you can't use a database and
all of the files are under one reasonably small directory
which your application owns and
which is stored on one physical drive:
then you could do the following:
Copy the directory contents using hard-links as appropriate.
Modify the 5 files.
Atomically swap the modified copy of the directory with the original

Ive used the apache commons transactions library for atomic file operations with success. This allows you to modify files transactionally and potentially roll back on failures.
Here's a link: http://commons.apache.org/transaction/

My approach would be to use a lock, in your java code. So only one process could write some file at each time. I'm assuming your application is the only which writes the files.
If even so some write problem occurs to "rollback" your files you need to save a copy of files like upper suggested.

Can't you lock all the files and only write to them once all files have been locked?

Related

Java shared folder synchronization between clusters

There is a small task for cluster synchronization, part of which is that there will be a certain shared folder with several files that can be changed. Which solution will be the most simple and lightweight? Considering that there are not so many files (5-10) and they will not change too often?
It is assumed that there will be one folder (for example, in cloud storage), a link to which all parts of the cluster will have. This folder will contain files that can be read or modified by any of the participants. It is necessary that at any time it was possible to determine that a file was in the process of being modified in order to prevent conflicts.
I already thought about synchronizing with file locks or H2, I don’t want to pull third-party libraries for this, but this is acceptable if they are small and suitable for this issue.

The best way to store large set of objects with efficient update/append operations

What is my specific use case?
I have set of objects representing e. g. profiles. Objects can be modified (updated), deleted or added. Each object has several properties, but modification of single property value just marks the whole object as "modified" (so from persistence layer point of view, an object is atomic). There are no relations between the objects.
Size of such set is between 10 - 50000 (but theoretically there's no limit - user can append additional objects). Single object size is up to 500KB (but usually it will be smaller, about 60KB).
Objects should be read and updated as fast as possible. There's also one more key requirement: they should be persisted on hard disk with possibility to copy or move them. My app is written in Java and run on Windows 7-10 OS.
What was my initial approach?
I came to conclusion that each object can be easily represented as single JSON file. The problem lies in keeping such large set of files on a disk. Windows filesystem doesn't seem to be good at handling too many (even small) files.
Then I thought that my files can be stored in virtual filesystem. The first obvious solution was to pack them in ZIP archive in such way:
profiles.zip:
--- profile1.json
--- profile2.json
...
--- profile10000.json
It would be great solution in terms of portability and the read performance is also ok. BUT, it seems the new objects can't be appended to ZIP archive without copying all files stored in the archive... Or at least I didn't find a way to do it.
What should I do then...?
I've searched for other solutions. I consider using:
Fast relational database - but I feel it is like to take a sledgehammer to crack a nut. Especially I don't need to handle relations or transactions (I don't even need a server, it is only for one local user).
NoSQL object databases, e.g. MapDb or Nitrite - it sounds ok, but I couldn't find any reliable comparisons or popularity ratings. It is important for me to pick a credible solution.
Some other virtual filesystems that can be managed in Java? Maybe I missed something?
Could you provide any ideas or advices based on experience? I need fast read/update of whole objects in large datasets with portability (that can be achieved in Java and Windows OS).
It is very hard to answer the question unless we know the size of each object in memory. One suggestion I can give is to try hybrid frameworks which support in memory access as well as persistence to disk.
Ehcache is one of the frameworks which I think will work for you and it it easily supports 50000 objects in memory itself. Even Couchbase supports similar options and a flexibility of immediate or eventual persistence.

Practical: deployment of application with .sql files

I am developing an application that will make heavy use of .sql files. While I am just at the beginning of development, I want to make sure I am going in the right direction to avoid re-coding later. Much like java source code is not meant for the end user to be seen, neither are .sql files and commands. My main goal is to hide them from the end user. My approach is as follows, and I am seeking alternative approaches and suggestions:
Write a small program that loops through all .sql files in a directory and stores the contents into a java.util.map using bufferedInputStream. The Map will be constructed with = new HashMap(, ). (I believe this is correct syntax). The key will be the .sql file name and value will be the .sql file contents. Then, serialize the Map object into a single file (say "SQLBin.bin") using ObjectOutputStream. Place the SQLBin.bin file into the resources folder of the main project and then use .getResourceAsStream() to access it and recreate a Map object in the main application. This will then allow me to access the SQL commands by simply referring to the .sql file by name in the Map object.
PS: I am relatively new to java. So please be extra clear.
You have an interesting technique; however, it is not clear what problem you intend to solve.
If you want to hide the SQL from the end user, you don't need to do all of this; just embed the SQL into a statement "string array" in a class and be done with it. But even such a solution might not be desirable depending on the true problem you are attempting to solve.
Also, some places really want to look at your SQL, because a database server isn't like a JVM. Your SQL can impact the correct operation of other mission critical programs. SQL servers may require manual configuration to grant you access. SQL servers may be monitored 24 / 7 for conditions that lead to excessive memory consumption or excessive use of CPU cycles. Professionals might rewrite your statements or tune the server to better accommodate unforeseen issues.
With a JVM the resource is less of a shared resource, and thus there's less potential for damage, in the worst case, you kill the offending JVM process, which rarely impacts the other processes that weren't explicitly written to integrate with yours.

How to efficiently manage files on a filesystem in Java?

I am creating a few JAX-WS endpoints, for which I want to save the received and sent messages for later inspection. To do this, I am planning to save the messages (XML files) into filesystem, in some sensible hierarchy. There will be hundreds, even thousands of files per day. I also need to store metadata for each file.
I am considering to put the metadata (just a couple of fields) into database table, but the XML file content itself into files in a filesystem in order not to bloat the database with content data (that is seldomly read).
Is there some simple library that helps me in saving, loading, deleting etc. the files? It's not that tricky to implement it myself, but I wonder if there are existing solutions? Just a simple library that already provides easy access to filesystem (preferrably over different operating systems).
Or do I even need that, should I just go with raw/custom Java?
Is there some simple library that
helps me in saving, loading, deleting
etc. the files? It's not that tricky
to implement it myself, but I wonder
if there are existing solutions? Just
a simple library that already provides
easy access to filesystem (preferrably
over different operating systems).
Java API
Well, if what you need to do is really simple, you should be able to achieve your goal with java.io.File (delete, check existence, read, write, etc.) and a few stream manipulations with FileInputStream and FileOutputStream.
You can also throw in Apache commons-io and its handy FileUtils for a few more utility functions.
Java is independent of the OS. You just need to make sure you use File.pathSeparator, or use the constructor File(File parent, String child) so that you don't need to explicitly mention the separator.
The Java file API is relatively high-level to abstract the differences of the many OS. Most of the time it's sufficient. It has some shortcomings only if you need some relatively OS-specific feature which is not in the API, e.g. check the physical size of a file on the disk (not the the logical size), security rights on *nix, free space/quota of the hard drive, etc.
Most OS have an internal buffer for file writing/reading. Using FileOutputStream.write and FileOutputStream.flush ensure the data have been sent to the OS, but not necessary written on the disk. The Java API support also this low-level integration to manage these buffering issue (example here) for system such as database.
Also both file and directory are abstracted with File and you need to check with isDirectory. This can be confusing, for instance if you have one file x, and one directory /x (I don't remember exactly how to handle this issue, but there is a way).
Web service
The web service can use either xs:base64Binary to pass the data, or use MTOM (Message Transmission Optimization Mechanism) if files are large.
Transactions
Note that the database is transactional and the file system not. So you might have to add a few checks if operations fails and are re-tried.
You could go with a complicated design involving some form of distributed transaction (see this answer), or try to go with a simpler design that provides the level of robustness that you need. A possible design could be:
Update. If the user wants to overwrite a file, you actually create a new one. The level of indirection between the logical file name and the physical file is stored in database. This way you never overwrite a physical file once written, to ensure rollback is consistent.
Create. Same story when user want to create a file
Delete. If the user want to delete a file, you do it only in database first. A periodic job polls the file system to identify files which are not listed in database, and removes them. This two-phase deletes ensures that the delete operation can be rolled back.
This is not as robust as writting BLOB in real transactional database, but provide some robustness. You could otherwise have a look at commons-transaction, but I feel like the project is dead (2007).
There is DataNucleus, a Java persistence provider. It is little too heavy for this case, but it supports JPA and JDO java standards with different datastores (RDBMS, object storage, XML, JSON, Excel, etc.). If the product is already using JPA or JDO, it might be worth considering using NataNucleus, as saving data into different datastores should be transparent. I suppose DataNucleus supports splitting the data into several files, creating the sensible directory/file structure I wanted (in my question), but this is just a guess.
Support for XML and JSON seems to be experimental.

Are flat file databases any good? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Informed options needed about the merits of flat file database. I'm considering using a flat file database scheme to manage data for a custom blog. It would be deployed on Linux OS variant and written in Java.
What are the possible negatives or positives regarding performance for reading and writing of both articles and comments?
Would article retrieval crap out because of it being a flat file rather than a RDBMS if it were to get slash-doted? (Wishful thinking)
I'm not against using a RDBMS, just asking the community their opinion on the viability of such a software architecture scheme.
Follow Up:
In the case of this question I would see “Flat file == file system–based” For example each blog entry and its accompanying metadata would be in a single file. Making for many files organized by date structure of the file folders (blogs\testblog2\2008\12\01) == 12/01/2008
Flat file databases have their place and are quite workable for the right domain.
Mail servers and NNTP servers of the past really pushed the limits of how far you can really take these things (which is actually quite far -- files systems can have millions of files and directories).
Flat file DBs two biggest weaknesses are indexing and atomic updates, but if the domain is suitable these may not be an issue.
But you can, for example, with proper locking, do an "atomic" index update using basic file system commands, at least on Unix.
A simple case is having the indexing process running through the data to create the new index file under a temporary name. Then, when you are done, you simply rename (either the system call rename(2) or the shell mv command) the old file over the new file. Rename and mv are atomic operations on a Unix system (i.e. it either works or it doesn't and there's never a missing "in between state").
Same with creating new entries. Basically write the file fully to a temp file, then rename or mv it in to its final place. Then you never have an "intermediate" file in the "DB". Otherwise, you might have a race condition (such as a process reading a file that is still being written, and may get to the end before the writing process is complete -- ugly race condition).
If your primary indexing works well with directory names, then that works just fine. You can use a hashing scheme, for example, to create directories and subdirectories to locate new files.
Finding a file using the file name and directory structure is very fast as most filesystems today index their directories.
If you're putting a million files in a directory, there may well be tuning issues you'll want to look in to, but out of that box most will handle 10's of thousands easily. Just remember that if you need to SCAN the directory, there's going to be a lot of files to scan. Partitioning via directories helps prevent that.
But that all depends on your indexing and searching techniques.
Effectively, a stock off the shelf web server serving up static content is a large, flat file database, and the model works pretty good.
Finally, of course, you have the plethora of free Unix file system level tools at your disposal, but all them have issues with zillions of files (forking grep 1000000 times to find something in a file will have performance tradeoffs -- the overhead simply adds up).
If all of your files are on the same file system, then hard links also give you options (since they, too, are atomic) in terms of putting the same file in different places (basically for indexing).
For example, you could have a "today" directory, a "yesterday" directory, a "java" directory, and the actual message directory.
So, a post could be linked in the "today" directory, the "java" directory (because the post is tagged with "java", say), and in its final place (say /articles/2008/12/01/my_java_post.txt). Then, at midnight, you run two processes. The first one takes all files in the "today" directory, checks their create date to make sure they're not "today" (since the process can take several seconds and a new file might sneak in), and renames those files to "yesterday". Next, you do the same thing for the "yesterday" directory, only here you simply delete them if they're out of date.
Meanwhile, the file is still in the "java" and the ".../12/01" directory. Since you're using a Unix file system, and hard links, the "file" only exists once, these are all just pointers to the file. None of them are "the" file, they're all the same.
You can see that while each individual file move is atomic, the bulk is not. For example, while the "today" script is running, the "yesterday" directory can well contain files from both "yesterday" and "the day before" because the "yesterday" script had not yet run.
In a transactional DB, you would do that all at once.
But, simply, it is a tried and true method. Unix, in particular, works VERY well with that idiom, and the modern file systems can support it quite well as well.
(answer copied and modified from here)
I would advise against using a flat file for anything besides read-only access, because then you'd have to deal with concurrency issues like making sure only one process is writing to the file at once. Instead, I recommend SQLite, a fully functional SQL database that's stored in a file. SQLite already has built-in concurrency, so you don't have to worry about things like file locking, and it's really fast for reads.
If, however, you are doing lots of database changes, it's best to do them all at once inside a transaction. This will only write the changes to the file once, as opposed to every time an change query is issued. This dramatically increases the speed of doing multiple changes.
When a change query is issued, whether it's inside a tranasction or not, the whole database is locked until that query finishes. This means that extremely large transactions could adversely affect the performance of other processes because they must wait for the transaction to finish before they can access the database. In practice, I haven't found this to be that noticeable, but it's always good practice to try to minimize the number of database modifying queries you issue, and it's certainly faster then trying to use a flat file.
This has been done with asp.net with Dasblog. It uses file based storage.
A few details are listed on this older link.
http://www.hanselman.com/blog/UpcomingDasBlog19.aspx
You can also get more details on http://dasblog.info/Features.aspx
I've heard some mixed opinions on the performance. I'd suggest you research that a bit more to see if that type of system would work well for you. This is the closest thing I have heard about yet.
Writing your own engine in native code can outperform a general purpose database.
However, the quality of the engine and the feature level will never approach that. All the things that databases give you as core features - indexing, transactions, referential integrity - you would have to implement all them yourself.
There's nothing wrong than reinventing the wheel (after all, Linux was just that), but keep in mind your expectations and time commitment.
I'm answering this not to answer why flat file databases are good or bad, others have done an ample job at that.
However, some have been pointing at SQLite which does it's job just fine. Since you are using Java, your best option would be to use HSQLDB, which does precisely the same as SQLite, but is implemented in Java and embeds into your application.
Most of the time a flat file database is enough now. But you will thank your younger self if you start your project with a database. This could be SQLite, if you don't want to set up a whole database system like PostgreSQL.
Check this out http://jsondb.io a opensource Java based database has most of what you are looking for.
Saves data as flat .json files, Multithreading Support, Encryption Support, ORM support, Atomicity Support, XPATH based advanced query support.
Disclaimer: I created this database.
Horrible idea. Appending would involve seeking to the end of the file every time you want to add something. Updating would require rewriting the entire file each time. Reading involves a table scan (or maintaining a separate index, which would have the same problems with writing/updating). Just use a database unless, of course, you re-implement all the stuff that an RDBMS already provides to make your solution even moderately scalable.
They seem to work quite well for high-write, low-read, no-update databases, where new data is appended.
Web servers and their cousins rely on them heavily for log files.
DBMS software as well use them for logs.
If your design falls within these limits, you're in good company, it seems. You might want to keep metadata and pointers in a database, and set up some kind of fast asynchronous queue-writer to buffer the comments, but the filesystem is already pretty good at that level of buffering and write-locking.
Flat file databases are possible but consider the following.
Databases need to attain all the ACID elements (atomicity, consistency, isolation, durability) and, if you're going to ensure that's all done in a flat file (especially with concurrent access), you've basically written a full-blown DBMS.
So why not use a full-blown DBMS in the first place?
You'll save yourself the time and money involved with writing (and re-writing many times, I'll guarantee) if you just go with one of the free options (SQLite, MySQL, PostgresSQL, and so on).
You can use fiat file databases if it is small enough does not have lost of random access. Big file with lot of random access will be very slow. And no complex queries. No joins, no sum, group by etc. You also can not expect to fetch hierarchical data from flat file. XML format is much better for complex structures.

Categories