Ubuntu 9.04 & openSUSE 11.1
I am and for a very long time already have been a die-hard SUSE user. However, most Linux people in my workplace are using Ubuntu.
Now that the Ubuntu 9.04, Jaunty Jackalope was released and my friend updated his laptop with it, I was excited to also try it out as it looked really good. The Gnome that comes with openSUSE somehow did not look that good...
Over the time I've almost always used KDE. I feel quite the same as Linus has once said - Gnome has taken the wrong turn in over simplifying its user interface. Over simplifying to the extent of removing also most of the necessary power-user stuff.
Unfortunately, nowadays the KDE 4 has also taken this bad route of over-simplifying the UI and probably for that cause, the KDE 4 team has re-written from the scratch many of the major KDE tools, such as Kate and KWrite, KDialog, Gwenview, Konsole, Amarok and many others. The new versions of the KDE 4 apps look, feel and are as useful as the namesakes of them at the time the KDE 2 started - raw and lacking many important features that I have grown accustomed to, plus introducing horde of bugs which should not be there at this point - an example would be KDialog, the new version of which does not return the correct response if you used only keyboard for selecting the button - with mouse it works, but not with keyboard. The old KDE 3.5 version, of course, works like a charm no matter how you use it.
One thing I found unbelievable in 64bit Ubuntu is the total lack of 32bit binary execution support out of the box. No 32bit ELF binary will run - bash, for example, says that the file you are trying to execute is not even there!
According to AMD64FirefoxAndPlugins page, in order to get the 32bit support you have to install several additional packages by hand and in order to run any 32bit binary you (apparently) need to modify some environment variables as well (better make a script). Additionally, for 32bit Firefox to be able to resolve names, you need some more installations to do.
Why on earth did the Ubuntu distro managers not create a normal dual architecture environment like openSUSE has - general 32bit support is given out of the box without any library path fiddling and only in case of more specific applications you need to select also the 32bit versions of any libraries they need.
Out of the box, there is one area where Ubuntu fares better than openSUSE - printers. I have two USB printers attached - an Epson Stylus Photo R220 and HP LaserJet 1020. Ubuntu noticed both of them, installing the Epson printer automatically with zero questions and for HP LaserJet only asking permission to install proprietary plugin direct from HP. Both work normally and to my biggest surprise, you can configure a ton of things for both printers including the CD printing capabilities of my Epson printer.
Right from the start I decided that I can not and will not use only Gnome tools and apps - I need at least Krusader, Gwenview, K3B, Konsole and KWrite. And I need the KDE 3.5 version of these apps - the ones that work as I've gotten used to. Again, out of the box there is no way to get KDE 3.5 apps. Fortunately there is the Pearson Computing KDE3.5 Repository for Ubuntu Intrepid and Above, which has a repository enabling the installation of KDE 3.5.10 environment and applications.
Another area where Ubuntu surprised me positively was the fact that KDE trash location was the same as the Gnome trash location. Deleting a file into trash from Krusader made it appear in Gnome's Trashcan... freedesktop.org has done a great job in unifying these two rivals making life easier for users of both.
So far so good, the system seems stable, printers work, audio works, my 32bit work environment (Java 6, Eclipse 3.4, Flex Builder, Firefox with Flash) is also working... so I guess I'll continue this experiment for a while longer.
Trying to spread knowledge about IT technology, Linux, programming (Java and Adobe Flex) and similar topics.
Saturday, May 30, 2009
Monday, May 25, 2009
How to make KPrinter work with Firefox 3?
openSUSE 11.1
In the recent past there have been several new software updates and upgrades which have almost infuriated me and forced me to revert to using old versions. The top two of these new things are:
The first of these items, however, is solved now, and here are the steps I took to make kprinter work with Firefox 3 (inspired by a post from this thread):
And that's it - Firefox 3 now prints directly to kprinter.
NB! The only quirk I've found is that you cannot cancel the kprinter dialog - or it will hang Firefox 3 for some reason.
EDIT: After some testing, however, this way of printing seems to be very buggy - most pictures do not print at all and those that do end up on the printed page are heavily compressed with visible compression artifacts, the text is uneven and looks ugly.
It seems that the LPR printing uses the lowest possible resolution with no known way to fix this higher.
I've switched back to Firefox 2.0.0.20 for now until the Firefox 3 will play nice within KDE!
In the recent past there have been several new software updates and upgrades which have almost infuriated me and forced me to revert to using old versions. The top two of these new things are:
- Firefox 3 which cannot be persuaded to use kprinter anymore the way Firefox 2 was persuaded.
- KDE 4 and its applications which totally and absolutely ignore the KDE 3 configuration with no apparent way to migrate the configuration either. Fortunately openSUSE still carries KDE 3.5 which I'm using currently.
The first of these items, however, is solved now, and here are the steps I took to make kprinter work with Firefox 3 (inspired by a post from this thread):
- The first step is to edit the file
/etc/gtk-2.0/gtkrcand add the following line to the end:gtk-print-backends = "lpr,file"
This will make the lpr target appear in the Firefox 3 print dialog. - The second step is to switch the lpr command for kprinter command by executing:
cd ~/bin
ln -s `which kprinter` lpr - And the third and final step is to get rid of the Firefox 3 print dialog by opening the URL
about:configand creating there the following new Boolean option:print.always_print_silent = true
And that's it - Firefox 3 now prints directly to kprinter.
NB! The only quirk I've found is that you cannot cancel the kprinter dialog - or it will hang Firefox 3 for some reason.
EDIT: After some testing, however, this way of printing seems to be very buggy - most pictures do not print at all and those that do end up on the printed page are heavily compressed with visible compression artifacts, the text is uneven and looks ugly.
It seems that the LPR printing uses the lowest possible resolution with no known way to fix this higher.
I've switched back to Firefox 2.0.0.20 for now until the Firefox 3 will play nice within KDE!
Wednesday, January 21, 2009
How to stop ComboBox from resizing itself automatically...
Adobe Flex 3
One of the many grievances I have with the otherwise wonderful Adobe Flex is the way the ComboBox component with percentage width resizes itself to accommodate the data which is loaded into it. There seems to be no switch to disable this behavior and yet retain the scalability of the ComboBox control itself.
The problem manifests itself best when you have, for example, two adjacent ComboBox widgets both set to be 50% width and you assign to the first a list of rows with short names and to the other a list of rows with long names - both widgets will resize themselves to a different width to accommodate their respective contents.
After searching for and failing to find a solution to this, I decided to try and write a workaround myself. I needed to fixate the width of the comboboxes right after they were first displayed and before they got their data. There was no need for the combobox to be resized later. In order to do this, I extended the original ComboBox and added the following code to it:
First I added a property via which you can turn on or off the new functionality:
Second, to the constructor of the combobox, I added an event listener:
Finally, I added the event handler method:
The idea here is to capture the event which is dispatched after the ComboBox size has been determined, right before the combobox is drawn on screen. Each ComboBox can have its width specified either explicitly in pixels or as a percentage of the containers width. When the width of the ComboBox is set as a percentage, I now assign its actual pixel width to the explicitWidth property. This will fixate the width and also stop the ComboBox from automatically resizing itself.
That solved the situation for me - the ComboBox retained its size after the initial layout.
One of the many grievances I have with the otherwise wonderful Adobe Flex is the way the ComboBox component with percentage width resizes itself to accommodate the data which is loaded into it. There seems to be no switch to disable this behavior and yet retain the scalability of the ComboBox control itself.
The problem manifests itself best when you have, for example, two adjacent ComboBox widgets both set to be 50% width and you assign to the first a list of rows with short names and to the other a list of rows with long names - both widgets will resize themselves to a different width to accommodate their respective contents.
After searching for and failing to find a solution to this, I decided to try and write a workaround myself. I needed to fixate the width of the comboboxes right after they were first displayed and before they got their data. There was no need for the combobox to be resized later. In order to do this, I extended the original ComboBox and added the following code to it:
First I added a property via which you can turn on or off the new functionality:
/**
* Property indicating if the initially measured width of the combobox will be
* fixed as soon as the combobox has been layed out.
* Only applies to combobox'es which have their width specified as a percentage.
*/
[Inspectable(category="General", enumeration="true,false", defaultValue="false")]
public var fixPercentWidthAfterInitialMeasurement:Boolean = false;
Second, to the constructor of the combobox, I added an event listener:
public function AComboBox()
{
super();
this.addEventListener(FlexEvent.UPDATE_COMPLETE, handleUpdateComplete);
}
Finally, I added the event handler method:
/**
* This eventhandler is called right before the widget is drawn on screen - it's size has already been calculated,
* but it has not yet received its contents, therefore now it is good time to convert its percentage width into
* an explicit width, so that future data loaded into the combobox would not resize the compobox causing scrolling.
*/
private function handleUpdateComplete(event:FlexEvent):void
{
if (this.fixPercentWidthAfterInitialMeasurement &&
(!isNaN(this.percentWidth))) this.explicitWidth = this.width;
}
The idea here is to capture the event which is dispatched after the ComboBox size has been determined, right before the combobox is drawn on screen. Each ComboBox can have its width specified either explicitly in pixels or as a percentage of the containers width. When the width of the ComboBox is set as a percentage, I now assign its actual pixel width to the explicitWidth property. This will fixate the width and also stop the ComboBox from automatically resizing itself.
That solved the situation for me - the ComboBox retained its size after the initial layout.
Friday, January 9, 2009
A RAID success - with a Linux of course!
This is a continuation of my struggle to create a viable RAID-5 array for my sensitive data, started in this post and continued in this post
This saga continues in here.
The first tries at setting up Linux RAID system were failures for yet unknown reason. As suggested somewhere I created 20GiB partitions on each disk for /root filesystem to be RAID-1 (mirror) array and into the rest of the space I created partitions for /home filesystem in RAID-5. I tried this with both openSuSE 11.0 and the newest openSuSE 11.1, but in both cases the system was unable to boot, complaining about missing root filesystem. Sometimes the system would boot if I gave it the obvious
After some more experimenting I finally gave up trying to make the system totally redundant and resolved the situation by putting 10GiB on each of the four disks aside for /root, /swap, /usr and /tmp, accordingly, and using the rest of the space on disks as a RAID-5 /home partition. This worked as a charm of course.
I did extensive testing on the redundancy of the drive and found it to be rock solid. When one of the drive was disconnected, the MD reported an active RAID-5 system having with 3 out of 4 drives working... and that's it. Coping, moving and changing the content did not even seem to be any slower than before.
After some testing I re-attached the fourth drive and booted the system up again. This time the boot messages reported that the fourth drive of the array was rejected as not being fresh. Checking the mdadm command for any clues how to make the array complete again showed that the correct command was
after that, the rebuilding of the fourth drive commenced in the background (it took a few hours) and the system was again working at peak efficiency.
Later I have been thinking what did I do wrong in the first two attempts and there are some things I can think of, but these must be verified first:
I call that a success story!
This saga continues in here.
The first tries at setting up Linux RAID system were failures for yet unknown reason. As suggested somewhere I created 20GiB partitions on each disk for /root filesystem to be RAID-1 (mirror) array and into the rest of the space I created partitions for /home filesystem in RAID-5. I tried this with both openSuSE 11.0 and the newest openSuSE 11.1, but in both cases the system was unable to boot, complaining about missing root filesystem. Sometimes the system would boot if I gave it the obvious
root=/dev/md0 as the kernel parameter, other times even that did not help.After some more experimenting I finally gave up trying to make the system totally redundant and resolved the situation by putting 10GiB on each of the four disks aside for /root, /swap, /usr and /tmp, accordingly, and using the rest of the space on disks as a RAID-5 /home partition. This worked as a charm of course.
I did extensive testing on the redundancy of the drive and found it to be rock solid. When one of the drive was disconnected, the MD reported an active RAID-5 system having with 3 out of 4 drives working... and that's it. Coping, moving and changing the content did not even seem to be any slower than before.
After some testing I re-attached the fourth drive and booted the system up again. This time the boot messages reported that the fourth drive of the array was rejected as not being fresh. Checking the mdadm command for any clues how to make the array complete again showed that the correct command was
mdadm --manage /dev/md0 --add /dev/sdd2after that, the rebuilding of the fourth drive commenced in the background (it took a few hours) and the system was again working at peak efficiency.
Later I have been thinking what did I do wrong in the first two attempts and there are some things I can think of, but these must be verified first:
- I used partition type Linux-RAID when creating partitions to be set up as RAID-1 later for the /root file system. Maybe I should have used the normal Linux partition type instead?
- After creating the first 20GiB partition, I used the rest of the drive for the second partition on each drive. Since the drives were not identical, I probably should have created the second partition by specifying the size by hand, keeping it some gigs smaller than the rest of the space to insure the equality on all drives?
I call that a success story!
Monday, January 5, 2009
More RAID rant
This post is an update to my previous post about my RAID-5 experience. Also see the continuation of this saga.
I found some disturbing problems with the nForce semi-software RAID-5 fault tolerance - without the fourth drive, the array seemed to work normally, but any modifications to the drive contents seemed to corrupt data on the drive. For example, in order to back up the data, after I had copied a few folders of data, I started to verify the copied data and delete it as I moved on. I always do it this way - first copy the data over, then run byte-per-byte verify (or MD5 hash verify) to see if the copy process worked and only after successful verify I will delete the data at the source.
Now, however, after I had verified and deleted the first folder of data from the RAID-5 array, the next folder showed an error in couple of files. Since they were picture files I was able to visually check the difference and the result was puzzling - the copied data seemed to be OK, but the source data on RAID-5 was corrupted. I tried a reboot, but the source file contents were still corrupted. I dismissed this as random happening and deleted the source (after all the errors were in the source data). Now the next folder showed even more corruptions and again the corrupted data was at the source.
A RAID-5 array with N drives saves actual data on N-1 of the drives and calculates a parity information to the remaining one drive. The data is saved in rotating stripes, so that the parity information of each next stripe is always on a different disk.
In case of reading data, if any one of the drives have failed, then N-1 times out of N, the the failed part of the data for each stripe is constructed by using the parity.
For example, when a stripe has parity on the drive 4, but drive 2 has failed, then the contents of drive 1 and 3 as well as the drive 4 with parity info is read and the contents of the failed drive 2 is constructed from the three other drives. Only in case the drive 2 held the parity data, is the reconstruction not needed.
The writing, however, is much more difficult. Assuming the above scenario, if the data is updated in the drive 1 region, then in addition to updating data on drive 1, the contents of drives 3 and 4 are read, the contents of drive 2 is temporarily reconstructed and new parity data is generated, which is updated on drive 4. If the data is updated in the failed drive 2 region, then similarly the data from drives 1, 3 and 4 are read, the original data of drive 2 is reconstructed, updated in memory and new parity is created and updated on drive 4.
Since the corruption was only few dozen bytes at a time and with no detectable pattern of changed bits I dismissed any further drive failure and assumed that one of the SATA cables could be faulty. I bought full set of new cables and tried again, recreated new RAID-5 array, copied a few dozen gigabytes of data on it. Made a copy of the data and then another copy of the same data. While the second copy was in progress, I disconnected one of the drives. At first, everything seemed to work normally. The array was in degraded mode and the copy was finished normally. Then I started to verify the copies of the data. At first things looked good, but then one of the bigger files had a few kilobytes of data totally differing in the middle of the file.
At this point I decided to power off the system, re-attach the drive I removed earlier and try the rebuilding. However, the nForce RAID BIOS reported error for the fourth drive and did not integrate it to the array. Booting Windows was also broken. After several attempts, somehow, I was able to boot and log into Windows at which point most things I tried to run either crashed, reported access violations or did not run at all.
For me, all this means that I will never trust the chipset semi-software RAID anymore. It could well be, that it is my motherboard that is at fault here, or the BIOS version... But still, having the RAID array is all about the ability to save important data on it without the need to worry if it will still be available after something happens to one of the drives. When the RAID array starts to corrupt data while in degraded mode then there really is no point in having a redundant RAID array.
If anyone has had a success using a chipset provided BIOS RAID array where a drive has failed in the middle of using it, please let me know the type and model of your motherboard.
Next I will try the software RAID offered by Linux. I'll try to do the same kind of trick - power down one of the disks while in use and see if and how much data I'll lose.
I found some disturbing problems with the nForce semi-software RAID-5 fault tolerance - without the fourth drive, the array seemed to work normally, but any modifications to the drive contents seemed to corrupt data on the drive. For example, in order to back up the data, after I had copied a few folders of data, I started to verify the copied data and delete it as I moved on. I always do it this way - first copy the data over, then run byte-per-byte verify (or MD5 hash verify) to see if the copy process worked and only after successful verify I will delete the data at the source.
Now, however, after I had verified and deleted the first folder of data from the RAID-5 array, the next folder showed an error in couple of files. Since they were picture files I was able to visually check the difference and the result was puzzling - the copied data seemed to be OK, but the source data on RAID-5 was corrupted. I tried a reboot, but the source file contents were still corrupted. I dismissed this as random happening and deleted the source (after all the errors were in the source data). Now the next folder showed even more corruptions and again the corrupted data was at the source.
A RAID-5 array with N drives saves actual data on N-1 of the drives and calculates a parity information to the remaining one drive. The data is saved in rotating stripes, so that the parity information of each next stripe is always on a different disk.
In case of reading data, if any one of the drives have failed, then N-1 times out of N, the the failed part of the data for each stripe is constructed by using the parity.
For example, when a stripe has parity on the drive 4, but drive 2 has failed, then the contents of drive 1 and 3 as well as the drive 4 with parity info is read and the contents of the failed drive 2 is constructed from the three other drives. Only in case the drive 2 held the parity data, is the reconstruction not needed.
The writing, however, is much more difficult. Assuming the above scenario, if the data is updated in the drive 1 region, then in addition to updating data on drive 1, the contents of drives 3 and 4 are read, the contents of drive 2 is temporarily reconstructed and new parity data is generated, which is updated on drive 4. If the data is updated in the failed drive 2 region, then similarly the data from drives 1, 3 and 4 are read, the original data of drive 2 is reconstructed, updated in memory and new parity is created and updated on drive 4.
Since the corruption was only few dozen bytes at a time and with no detectable pattern of changed bits I dismissed any further drive failure and assumed that one of the SATA cables could be faulty. I bought full set of new cables and tried again, recreated new RAID-5 array, copied a few dozen gigabytes of data on it. Made a copy of the data and then another copy of the same data. While the second copy was in progress, I disconnected one of the drives. At first, everything seemed to work normally. The array was in degraded mode and the copy was finished normally. Then I started to verify the copies of the data. At first things looked good, but then one of the bigger files had a few kilobytes of data totally differing in the middle of the file.
At this point I decided to power off the system, re-attach the drive I removed earlier and try the rebuilding. However, the nForce RAID BIOS reported error for the fourth drive and did not integrate it to the array. Booting Windows was also broken. After several attempts, somehow, I was able to boot and log into Windows at which point most things I tried to run either crashed, reported access violations or did not run at all.
For me, all this means that I will never trust the chipset semi-software RAID anymore. It could well be, that it is my motherboard that is at fault here, or the BIOS version... But still, having the RAID array is all about the ability to save important data on it without the need to worry if it will still be available after something happens to one of the drives. When the RAID array starts to corrupt data while in degraded mode then there really is no point in having a redundant RAID array.
If anyone has had a success using a chipset provided BIOS RAID array where a drive has failed in the middle of using it, please let me know the type and model of your motherboard.
Next I will try the software RAID offered by Linux. I'll try to do the same kind of trick - power down one of the disks while in use and see if and how much data I'll lose.
Wednesday, December 31, 2008
A lesson in setting up RAID array.
See also my followup post.
One of the computers I have at home is designated as a 'Library computer'. I wanted to be sure that the data that is put in there would survive a hard drive failure, so I was using a RAID-5 array with four 320GB hard drives, totaling in about 960GB or 894GiB (gibibytes). All but two of the hard drives were different models.
About a month ago, the nForce chipset started to show red message on bootup screen saying that the array is in "Degraded" mode, as one of the drives had failed a SMART test and was rejected. I sent the drive to be switched under RMA and got now a new one. The manufacturer of the new drive was the same (Samsung), but the model was different. The old drive was a Spinpoint F1, the new drive is Spinpoint T166. Otherwise the units seemed to be identical -- both had 320GB capacity, 7200rpm, 16MiB cache and SATA-II interface.
I plugged the drive in and booted the computer up, only to find that the array was still in Degraded mode and the new drive was also rejected. I rebooted into RAID BIOS and tried to manually engage the Rebuild option, but that failed complaining that the new drive was too small?
After inspecting the actual size of the drives, things started to clear up. While all of the drives were noted to be 320GB (or 298.02GiB in binary system), the actual capacity of the drives varied between different manufacturers and even between different models of the same manufacturer. The RAID uses the actual size of the smallest drive in an array. In my case, the original array used 298.09GiB as that size. The new drive however registered 298.08GiB as its actual size - this is 0.01GiB, or about 10 megabytes smaller. As such it was not possible to use this drive.
The lesson here is simple -- never allow the maximum size of the currently smallest drive to be the size that is used to make up the array. Take a good 0.1GiB off of it. You'll only lose a few hundred megabytes, but when it's time to swap out a failed drive, the capacity of the new drive might be less than what the old one had and you'll end up coping the whole array to a separate large hard drive and redo the whole setup (just as I had to do).
One of the computers I have at home is designated as a 'Library computer'. I wanted to be sure that the data that is put in there would survive a hard drive failure, so I was using a RAID-5 array with four 320GB hard drives, totaling in about 960GB or 894GiB (gibibytes). All but two of the hard drives were different models.
About a month ago, the nForce chipset started to show red message on bootup screen saying that the array is in "Degraded" mode, as one of the drives had failed a SMART test and was rejected. I sent the drive to be switched under RMA and got now a new one. The manufacturer of the new drive was the same (Samsung), but the model was different. The old drive was a Spinpoint F1, the new drive is Spinpoint T166. Otherwise the units seemed to be identical -- both had 320GB capacity, 7200rpm, 16MiB cache and SATA-II interface.
I plugged the drive in and booted the computer up, only to find that the array was still in Degraded mode and the new drive was also rejected. I rebooted into RAID BIOS and tried to manually engage the Rebuild option, but that failed complaining that the new drive was too small?
After inspecting the actual size of the drives, things started to clear up. While all of the drives were noted to be 320GB (or 298.02GiB in binary system), the actual capacity of the drives varied between different manufacturers and even between different models of the same manufacturer. The RAID uses the actual size of the smallest drive in an array. In my case, the original array used 298.09GiB as that size. The new drive however registered 298.08GiB as its actual size - this is 0.01GiB, or about 10 megabytes smaller. As such it was not possible to use this drive.
The lesson here is simple -- never allow the maximum size of the currently smallest drive to be the size that is used to make up the array. Take a good 0.1GiB off of it. You'll only lose a few hundred megabytes, but when it's time to swap out a failed drive, the capacity of the new drive might be less than what the old one had and you'll end up coping the whole array to a separate large hard drive and redo the whole setup (just as I had to do).
Tuesday, December 2, 2008
How to release software...
Today, in our team, we had an argument about how to manage the software quality.
I've previously worked for another organization where the releasing was done very differently. In there, the software was released file-by-file as opposed to by package. When you needed to make some changes to already existing piece of software, you checked out the relevant file(s), modified it (them) and committed the change(s) back, noting what revision did the new file(s) get. After that you created a change document and filled it with the name(s) of the file(s) which were changed, the new revision and the reason for the change. The software releasing team got the change document, checked out the necessary revisions you had written in the document, compiled them and released them.
In my current organization, the releasing is done monthly (sometimes even less frequently) in one big package. In addition to that, our Flex application is submitted also as a package, which we compile ourselves (the resulting SWF is released).
The problem we are facing has to do with release quality. Since the software is released as a package, it becomes vitally important to track which changes to the individual Flex source files get to go into the package and which must be left out, since they are not yet complete. Still, in development environment we need the latest state there is (so called nightly build). The question is - how to track the changes? How to differentiate the changes of the future from the immediate changes scheduled to be released next?
Normally, the development environment is compiled from the HEAD of the CVS - with all the latest changes. Up until recently the same HEAD build was also released. Since we now are doing more and more future developments that do not need to get in anytime soon, that started to create problems for us. For example, in order to demonstrate my new development, I had to commit the changes, so that the nightly build process would build it into the development environment. But this can no longer be the version that goes out as a release version, since my new development should not be released yet... How to solve this?
Some parts of our organization are using extensive branching. Any bugfixing to production code is performed on a branch which is later merged with the HEAD code... this is a very difficult process with lots of errors which we hoped to avoid.
My suggestion was to use a special tag to track the revisions of the source files which are used to compile the release SWF. The tag name might be anything, for example "GO". This tag is given to all the files that are scheduled to go out next - the release build process will only check out files with the "GO" tag (as opposed to the nightly build process, which checks out HEAD).
If there are any future changes which should not go into the next release, then those files are not to be tagged with the "GO" tag, so that tag will remain on the older revision of these files. Hence the release build process will ignore the future changes, while the nightly build process will compile them into the development environment.
In case there are any production bugfixing changes, which must go into the next release, then the new (fixed) revisions of these files should be given the "GO" tag - the release build process will then pick these changes up and compile them for the release SWF.
A more difficult situation is when there are future changes and immediate bugfixes to be performed on the same files. In such situation, branching might be the only answer, though I would do things differently:
The result in CVS might look like this:
This however is complicated if the future changes encompass more than one file, in which case the "GO" revision contents must be restored for all the files involved. In order to make this easier, first tag the future changes with some other tag, such as "NEW", so you'll know which files to restore after you've done bugfixing.
Thats it. I don't know if the above made any sense at all, but this is how I would tackle this code quality issue while keeping a grip on my senses at the same time...
I've previously worked for another organization where the releasing was done very differently. In there, the software was released file-by-file as opposed to by package. When you needed to make some changes to already existing piece of software, you checked out the relevant file(s), modified it (them) and committed the change(s) back, noting what revision did the new file(s) get. After that you created a change document and filled it with the name(s) of the file(s) which were changed, the new revision and the reason for the change. The software releasing team got the change document, checked out the necessary revisions you had written in the document, compiled them and released them.
In my current organization, the releasing is done monthly (sometimes even less frequently) in one big package. In addition to that, our Flex application is submitted also as a package, which we compile ourselves (the resulting SWF is released).
The problem we are facing has to do with release quality. Since the software is released as a package, it becomes vitally important to track which changes to the individual Flex source files get to go into the package and which must be left out, since they are not yet complete. Still, in development environment we need the latest state there is (so called nightly build). The question is - how to track the changes? How to differentiate the changes of the future from the immediate changes scheduled to be released next?
Normally, the development environment is compiled from the HEAD of the CVS - with all the latest changes. Up until recently the same HEAD build was also released. Since we now are doing more and more future developments that do not need to get in anytime soon, that started to create problems for us. For example, in order to demonstrate my new development, I had to commit the changes, so that the nightly build process would build it into the development environment. But this can no longer be the version that goes out as a release version, since my new development should not be released yet... How to solve this?
Some parts of our organization are using extensive branching. Any bugfixing to production code is performed on a branch which is later merged with the HEAD code... this is a very difficult process with lots of errors which we hoped to avoid.
My suggestion was to use a special tag to track the revisions of the source files which are used to compile the release SWF. The tag name might be anything, for example "GO". This tag is given to all the files that are scheduled to go out next - the release build process will only check out files with the "GO" tag (as opposed to the nightly build process, which checks out HEAD).
If there are any future changes which should not go into the next release, then those files are not to be tagged with the "GO" tag, so that tag will remain on the older revision of these files. Hence the release build process will ignore the future changes, while the nightly build process will compile them into the development environment.
In case there are any production bugfixing changes, which must go into the next release, then the new (fixed) revisions of these files should be given the "GO" tag - the release build process will then pick these changes up and compile them for the release SWF.
A more difficult situation is when there are future changes and immediate bugfixes to be performed on the same files. In such situation, branching might be the only answer, though I would do things differently:
- commit any uncommitted future changes (if any) to CVS;
- get the contents of the file revision with the "GO" tag into the current file;
- perform the bugfixing on that code, test the bugfix;
- commit the changes and move the "GO" tag to the new revison you just committed;
- now get the contents of the previous HEAD revision (before the commit in 4 above);
- perform the same bugfixing in this version and commit the changes back to the HEAD.
The result in CVS might look like this:
- r1.4 - the old "GO" revision of the file
- r1.5 - future changes without a tag
- r1.6 - some more future changes without a tag
- r1.7 - the r1.4 revision with the bugfix and with "GO" tag
- r1.8 - the r1.6 revision with the bugfix, with the latest future changes, but without a tag
This however is complicated if the future changes encompass more than one file, in which case the "GO" revision contents must be restored for all the files involved. In order to make this easier, first tag the future changes with some other tag, such as "NEW", so you'll know which files to restore after you've done bugfixing.
Thats it. I don't know if the above made any sense at all, but this is how I would tackle this code quality issue while keeping a grip on my senses at the same time...
Subscribe to:
Posts (Atom)