Jump to content











Photo
- - - - -

[Solved] Coding help needed


  • Please log in to reply
6 replies to this topic

#1 pscEx

pscEx

    Platinum Member

  • Team Reboot
  • 12688 posts
  • Location:Korschenbroich, Germany
  • Interests:What somebody else cannot do.
  •  
    European Union

Posted 05 October 2013 - 04:07 PM

In the Win7PE project on every build the old build's files are deleted in a first step.

 

This currently takes some time. And the build is waiting for completion of the delete.

On my system that takes about 45 seconds in average.

 

My idea was to start a background task which does the deletion.

 

I implemented for a windows host, and it works very well:

Average build time of a PE with standard components and internet access by M$ InternetExplorer takes about one minute!

 

I need the forum's help to code for Linux, Mac etc. My knowledge there is too small.

 

Here the current code:

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/*
    BackDelete "fast" deletes a directory including subdirectories
    First it renames the directory
    Second it starts an ansync process to delete the directory
    For the calling object there is the advantage that it has not to wait until deletion is finished
*/
public boolean BackDelete(File dirFile) {
    String OS = System.getProperty("os.name").toLowerCase();
    String dirPath = dirFile.getAbsolutePath();

    // to avoid troubles if the rename target exists, use an unique extention depending on time
    DateFormat formatter = new SimpleDateFormat(".HHmmss");
    String newExtention = formatter.format(new Date());

    String argRen;
    String argDel;
    if (OS.indexOf("win") >= 0) {
        String newName = dirFile.getName() + newExtention;
        argRen = "cmd /c ren \"" + dirPath + "\" \"" + newName + "\"";
        argDel = "cmd /c rmdir /S /Q \"" + dirPath + newExtention + "\"";
    } else if (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0 || OS.indexOf("aix") >= 0 ) {
        // ToDo
    } else if (OS.indexOf("mac") >= 0) {
        // ToDo
    } else if (OS.indexOf("sunos") >= 0) {
        // ToDo
    } 
    Runtime.getRuntime().exec(argRen);

    // give file system some time to recognize the change
    while (dirFile.exists()) {
        Thread.sleep(100);
    }

    Runtime.getRuntime().exec(argDel);
    return true;
}

I hope that some members can replace the ToDo-s

 

Peter :cheers:



#2 skyide

skyide

    Frequent Member

  • Advanced user
  • 218 posts
  •  
    Australia

Posted 06 October 2013 - 11:05 AM

post deleted by poster.



#3 Nuno Brito

Nuno Brito

    Platinum Member

  • Team Reboot
  • 10447 posts
  • Location:boot.wim
  • Interests:I'm just a quiet simple person with a very quiet simple life living one day at a time..
  •  
    European Union

Posted 06 October 2013 - 10:00 PM

Hi Peter,

 

Not a good practice to depend on exec() commands for anything. Winbuilder comes with a very nice Apache Commons library to handle files and folders, it is called through "FileUtils" inside the code. From what I understand, you want to:

1 - Rename the folder

2 - Delete it on the background

3 - Get a confirmation that the folder was renamed and deleted

 

 

I'm launching a thread to run the renaming and deleting the folder without any delays on its own thread. On the Win7PE scripts is possible to register a hook to react in case the folder is not deleted for some weird reason.

package build;

import definitions.is;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.io.FileUtils;

/**
 *
 * @author Nuno Brito, 6th of October 2013 in Darmstadt, Germany
 */
public class Test {

    public void BackDelete(final File dirFile) {

        // get a random value based on date
        DateFormat formatter = new SimpleDateFormat(".HHmmss");
        String newExtension = formatter.format(new Date());
        String newName = dirFile.getName() + newExtension;
        // create the new folder pointer
        final File newFolder = new File(dirFile.getParentFile(), newName);

        Thread thread = new Thread(){
            @Override
            public void run(){
                try {
                    // do the renaming
                    FileUtils.moveDirectoryToDirectory(dirFile, newFolder, true);
                    // delete the folder contents
                    FileUtils.forceDelete(newFolder);
                } catch (IOException ex) {
                    // something went wrong, output an error message
                    log.write(is.ERROR, "Failed to delete folder " +
                            "1% with error message %2",
                            newFolder.getAbsolutePath(), ex.getLocalizedMessage());
                    return;
                }
                // if the folder still exists, fail here
                if(dirFile.exists()){
                   log.write(is.ERROR, "Failed to delete folder " +
                            "1%", newFolder.getAbsolutePath());
                    return;
                }
                // signal to the world that everything went ok
                log.write(is.COMPLETED, "Deleted previous build " +
                        "folder at 1%", newFolder.getAbsolutePath());
            }
        };
        thread.start();

    }

}

Personally, I'd avoid creating folders based on time stamps.

 

If something went wrong and the folder with date stamp was not deleted, then the script should worry about cleaning it up or warning the user that he needs to manually delete this folder if wb is unable to do so. Otherwise you risk creating dozens of folders that just take up space for no good reason.

 

Hope this helps.

 

:cheers:



#4 skyide

skyide

    Frequent Member

  • Advanced user
  • 218 posts
  •  
    Australia

Posted 07 October 2013 - 08:31 AM

post deleted by poster.



#5 pscEx

pscEx

    Platinum Member

  • Team Reboot
  • 12688 posts
  • Location:Korschenbroich, Germany
  • Interests:What somebody else cannot do.
  •  
    European Union

Posted 07 October 2013 - 09:32 AM

Thanks, Nuno, for the thread suggestion :idea:

Code is now as follows:

I still use the "time" naming, because rename fails when the target name exists.

import java.text.SimpleDateFormat;
import java.util.Date;

/*
    BackDelete "fast" deletes a directory including subdirectories
    First it renames the directory
    Second it starts an ansync process to delete the directory
    For the calling object there is the advantage that it has not to wait until deletion is finished

    Thanks to Nuno Brito for the "thread" suggestion

    Return value is true, when the rename has been successfully performed
    There is no check about successful deleting
*/
public boolean BackDelete(File dirFile) {
    // to avoid troubles if the rename target exists, use an unique extention depending on time
    String newName = "deldir" + (new SimpleDateFormat(".HHmmss")).format(new Date());
    // create the new folder pointer
    File newFolder = new File(dirFile.getParentFile(), newName);
    try {
        // do the renaming
        FileUtils.moveDirectoryToDirectory(dirFile, newFolder, true);
    } catch (IOException ex) {
        // something went wrong, output an error message
        log.write(is.ERROR, "Failed to move folder " +
            "1% to %2 with error message %3",
            dirFile.getAbsolutePath(), newFolder.getAbsolutePath(), ex.getLocalizedMessage());
        false;
    }

    // give file system some time to recognize the change
    while (dirFile.exists()) {
        Thread.sleep(100);
    }

    Thread thread = new Thread() {
        public void run() {
            try {
                FileUtils.forceDelete(newFolder);
            } catch (IOException ex) {
                // something went wrong, output an error message
                log.write(is.ERROR, "Failed to delete folder " +
                    "%1 with error message %2",
                    newFolder.getAbsolutePath(), ex.getLocalizedMessage());
                return;
            }
            // signal to the world that everything went ok
            log.write(is.COMPLETED, "Asynchronously deleting files from previous build");
        }
    };

    thread.start();
    return true;
}

Peter



#6 Nuno Brito

Nuno Brito

    Platinum Member

  • Team Reboot
  • 10447 posts
  • Location:boot.wim
  • Interests:I'm just a quiet simple person with a very quiet simple life living one day at a time..
  •  
    European Union

Posted 07 October 2013 - 12:17 PM

My pleasure to help. :)

 

Just to see if I understood this part correctly:

// give file system some time to recognize the change
while (dirFile.exists()) {
Thread.sleep(100);
}

The goal here is to hold the build execution until the folder renaming/move is complete? If so, very good approach. I'd just recommend adding a counter to ensure that after a given number of loops it can say "this failed".

 

For example:

// give file system some time to recognize the change
int counter = 0;
while (dirFile.exists()) {
counter++;
Thread.sleep(100);
// 100 * 100 = 10 000ms (10 seconds)
if(counter > 100){
    // something went wrong, output an error message
    log.write(is.ERROR, "Failed to move folder ..............");
    return false;
 }
}

Hope this helps.

:cheers:



#7 pscEx

pscEx

    Platinum Member

  • Team Reboot
  • 12688 posts
  • Location:Korschenbroich, Germany
  • Interests:What somebody else cannot do.
  •  
    European Union

Posted 07 October 2013 - 12:24 PM

Yes, you understood correctly;

If that little sleep is not there, creating the output folder and subfolders falls into the file system's move and creates unpredictable results.

 

Very good Idea!

 

Usually just one sleep is sufficient. But your idea avoids endless waiting in case of some troubles.

 

Peter


  • Nuno Brito likes this




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users