4

I'm writing a small program which is supposed to update Firmware on Servers. The way I currently do this is by issuing a command via the ProcessBuilder, executing it and using exitCode = process.waitFor(); to wait until the command is finished.

Some of these Firmware updates can take a few minutes, so when setting up multiple Systems, these Firmware updates can take hours, if done separately.

I have tried creating Threads, while using CyclicBarrier, to ensure that all Firmware Updates are started at the same time. (See: Stackoverflow-Question: How to start two threads at “exactly” the same time

The problem I have spotted with this however, that my program will continue as usual after starting all the threads - which in this case would be to reboot all the systems, which might break them if they are still in the process of updating Firmware.

How could I ensure that all Firmware Updates are done before continuing? I have thought about letting the program sleep for 10-15 minutes, but would like a more reliable approach.

Ravindra Ranwala
  • 20,744
  • 6
  • 45
  • 63
Korlimann
  • 147
  • 14
  • 1
    Do you have to wait for all servers to complete their firmware update before rebooting? Or can you reboot a single server as soon as its firmware update has completed? If the latter, then the thread that performs the firmware update can also perform the reboot. Also, why do all the firmware updates need to start at the same time? – Abra Aug 31 '21 at 10:19
  • @Abra both restart options are possible. The reason why I want them to start at the same time is the following: 1 FW Update takes 5-10 minutes on average on any given server. 20 FW Updates (testing this right now) are still not done after around 2 hours. The goal of the software is to not only make the setup process easier, but also faster, and while the current solution makes it easier, it doesn't make it faster at all. Doing these steps by hand would take us around half an hour for 20 systems, compared to the 2+ hours we're looking at right now – Korlimann Aug 31 '21 at 10:25
  • @Abra althought the suggestion you had might actually work very well. I'll try it out, thank you! – Korlimann Aug 31 '21 at 10:26
  • Launch a separate thread for each server. The threads don't all have to start at the same time. Each thread updates the firmware of a single server. Each thread waits until its server's firmware update has completed and the the same thread performs a reboot of its server. I assume all the servers are independent, i.e. each one can be updated and rebooted independently of all other servers. Hence no need for the threads to be coordinated with each other in any way. – Abra Aug 31 '21 at 10:33
  • @Abra assuming that the servers still need to perform other FW updates after that, and no updates should be done while another update is running, would your approach still work? How would my program know that all servers are done updating, before continuing onto the next step? – Korlimann Aug 31 '21 at 10:38
  • I have closed this question as a duplicate, and recommend using `invokeAll()` as described in my answer there. If you feel your circumstances are different, please distinguish your question and we can re-open this. – erickson Aug 31 '21 at 19:56

2 Answers2

3

You may use a CountDownLatch in addition to the barrier. Pass the CountDownLatch to each of the thread, once the firmware update is completed, just call the count-down on the latch. In your main thread, after starting all the threads, you may wait by calling latch.await and it will wail till all the other threads finish. You may find a sample here.

You can even use a CountDownLatch with 1 as the count for the starting gun in your case, which precludes the use of the CyclicBarrier.

Ravindra Ranwala
  • 20,744
  • 6
  • 45
  • 63
2

You need Thread.join() method. Take a look at the example:

public static void main(String[] args) throws InterruptedException {
        Runnable sleepTwoSeconds = () -> {
            try {
                Thread.sleep(2000);
                System.out.println("Sleeping finished");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        Thread t1 = new Thread(sleepTwoSeconds);
        t1.start();
        Thread t2 = new Thread(sleepTwoSeconds);
        t2.start();
        t1.join();
        t2.join();
        System.out.println("Main thread continue.");

    }

"How could I ensure that all Firmware Updates are done before continuing?" Main thread will not continue until t1 and t2 are done.

Spasoje Petronijević
  • 1,476
  • 3
  • 13
  • 27
  • From what I read about Thread.join() (https://www.geeksforgeeks.org/joining-threads-in-java/) it seems like this method only waits until the Thread is done before continuing with the next Thread. I want all threads to start around the same time though. – Korlimann Aug 31 '21 at 10:42
  • 1
    Not sure if we are on the same page. Take a look at the edited answer. The main thread will not proceed until t1 and t2 are not done. Is that what you are looking for? – Spasoje Petronijević Aug 31 '21 at 15:55
  • My apologies, I think I misunderstood the usage of the .join() method. Thanks for your help! – Korlimann Sep 01 '21 at 11:14