-
Notifications
You must be signed in to change notification settings - Fork 0
05 SampleProgram
SampleProgram is a windows console application project that builds and integrates the features of this solution.
SampleProgram consists of main, ripper, progress_tracker and RAII_physical_lock. main is the main program and entrypoint that uses ripper to create an ISO 9660 image of any CDROM/DVD media found in the drive.
ripper demonstrates RAII paradigm by locking the cdrom tray door, and unlocking it on all return paths (but in this case there is a design limitation that is discussed below).
progress_tracker is an example of task based threading - an object (with state) is created, and its functor () is used as the target of a std::async call in main(). std::async returns a std::future which can be used to block the launching main thread, and to await and interrogate the eventual task outcome. Notice that such a task is easy to set-up, launch and synchronize. It can also log without restrictions, and throw exceptions, which may (optionally) be off-loaded for exception handling in the invoking thread. This may seem to be just what you would expect, and to value and appreciate this richness, simplicity and ease of use, you probably need to have experienced some of the history of cooperative, pre-emptive, multi-tasking in the preceding years.
The object instance created in main for this purpose is called 'tracker' and its state includes a reference to a std::atomic 'progress'. The same reference has been added to parameter frames of the constructors (Ripper, CdromDevice) which track (maintain the progress value) in the main thread. This approach provides (thread safe) passing of the progress indication to the progress tracker thread, which is responsible for informing the operator.
-
The main program makes fixed hard coded selection of the first physical cdrom drive found in the system at runtime. It logs to a fixed hard coded log file called "ripper.log", and creates an iso image file in the fixed hard coded location "cdrom_image.iso".
-
The main program now shows a progress indication during the rip/read operation, because this typically takes some minutes to complete. However, the design of this feature favours simplicity over accuracy, and has the known limitations that it will not be a reliable progress indication if an out of resource exception occurs.
The actual maintenance of the progress indicator has been added by modifying the behaviour of cd_rom_device::get_image(). Here the implementation class used to issue a single large blocking synchronous read operation to the underlying kernel device, and had some built-in out-of-resource exception handling. That handling falls back to use ever more granular (cylinder, track, and sector sized) reads whenever memory is scarce.
While a single big read approach is optimal for efficiency, that choice offers ZERO opportunity to maintain a progress tracking value. The read is synchronous, and writing to disk is done by the device itself, writing into a buffer that happens to be provided by a memory mapped file. That file size is reserved at create time, so there really is no way to know how far a single read has progressed until it completes (only the device driver knows - and its not telling).
As a work-around to this problem, a static method simulate_resource_limitation() has been inserted to circumvent the first big read in get_image(), and to trick the out-of-resource exception handling into performing multiple 'cylinder size' reads. Here in a function read_blocks() it is very easy to track %progress over the rip assuming cylinder sized reads. Unfortunately, because all reads are off loaded to a read_blocks() function, the progress bar will behave erratically if a real read resource limitation occurs during the rip.
Theoretically this approach means that in the event of memory limits, the progress indication would run quickly up to 100% and be reset back to zero, multiple times, for the (unspecified and not indicated) number of track and/or sector sized reads needed to finish the rip. Fixing this isn't difficult but would obscure the example code with unnecesary complexity. In practice I have never yet seen any out of memory resource problems in real world scenarios, so I am satisfied with this limitation.
-
Large dvd images can exceed the virtual address space available to the 32-bit build binaries. In these circumstances an exception will be reported (to the console).
-
Image files ripped from cd's that are not ISO 9660 format, obviously won't be ISO 9660 compliant, and the fixed .iso extension of the image file will then be a falsehood. Windows will advise you that such a file is 'corrupt'. On Windows 10 Home 1803 edition the file won't be mountable, and if you try, you will need to eject the failed new volume (visible in the left panel of the file explorer), before the backing file can be accessed or deleted. With all of Windows 7-10 you'll see something similar to this.
-
Signalled program termination (Eg ctrl+break ctrl+c) demonstrate an important limitation of RAII. Destructors are not invoked if a process is signalled to stop. A terminated process releases its resources more brutally. This means that system state cannot be reliably restored using RAII techniques alone, and that fact compromises the design (that I naïvely selected to use). In fact, while I am passing this off here as a 'limitation', it is in all honesty a BUG. If the program is terminated in this way during reading (when the CDROM tray door is locked) then the door will remain in the locked state. This could pose a real practical difficulty because the kernel device may refuse an unlock request coming from a different process from the one that locked it, and you might need to reboot to get your disk back! This whole effect will only be visible if your hardware supports tray door locking. Fix: A signal handler has been added, which issues a preventative speculative unlock whenever the program is signalled to stop.
-
There is no housekeeping done with log files which could expand indefinitely to consume all disk space.