An ability to synchronize commands not only with already running onces, BLD200301200100
authormentlicher@netbeans.org
Thu, 16 Jan 2003 16:59:49 +0000
changeset 3021e55d60400730
parent 3020 9c662bda57fc
child 3022 61f6a84cac0b
An ability to synchronize commands not only with already running onces,
but also with pending, that are waiting to be executed.
The EXEC_SERIAL_WITH_PENDING flag was added into VcsCommand
for that purpose.
UserCommandTask then remembers the list of pending tasks
and manage the synchronization accordingly.
This is necessary for recursive add, so that we're sure, that the
add on a child folder can not be executed before add on the parent folder.
This is a fix of issue #29264.
vcscore/src/org/netbeans/modules/vcscore/cmdline/UserCommandTask.java
vcscore/src/org/netbeans/modules/vcscore/commands/VcsCommand.java
     1.1 --- a/vcscore/src/org/netbeans/modules/vcscore/cmdline/UserCommandTask.java	Thu Jan 16 16:35:57 2003 +0000
     1.2 +++ b/vcscore/src/org/netbeans/modules/vcscore/cmdline/UserCommandTask.java	Thu Jan 16 16:59:49 2003 +0000
     1.3 @@ -20,6 +20,8 @@
     1.4  import java.util.HashSet;
     1.5  import java.util.Hashtable;
     1.6  import java.util.Iterator;
     1.7 +import java.util.LinkedList;
     1.8 +import java.util.List;
     1.9  import java.util.Map;
    1.10  import java.util.Set;
    1.11  
    1.12 @@ -80,6 +82,12 @@
    1.13       */
    1.14      private static Set runningTasks = new HashSet();
    1.15      
    1.16 +    /**
    1.17 +     * The list of pending tasks, preserving the order in which they were scheduled.
    1.18 +     * This list is necessary for tasks synchronization.
    1.19 +     */
    1.20 +    private static List pendingTasks = new LinkedList();
    1.21 +    
    1.22      /** Creates a new instance of UserCommandTask */
    1.23      public UserCommandTask(UserCommandSupport cmdSupport, VcsDescribedCommand cmd) {//, VcsCommandExecutor executor) {
    1.24          super(cmdSupport, cmd);
    1.25 @@ -309,10 +317,15 @@
    1.26      protected int execute() {
    1.27          int status = STATUS_SUCCEEDED;
    1.28          try {
    1.29 -            runningTasks.add(this);//, Thread.currentThread());
    1.30 +            //runningTasks.add(this);//, Thread.currentThread());
    1.31 +            // Task is added as running when canRun() returns true. It's too late to do it here!
    1.32 +            // canRun() can be called quickly one after another and excute() in a lazy thread later.
    1.33              status = super.execute();
    1.34          } finally {
    1.35 -            runningTasks.remove(this);
    1.36 +            synchronized (runningTasks) {
    1.37 +                runningTasks.remove(this);
    1.38 +                //System.out.println("RUNNING TASK REMOVED: "+this);
    1.39 +            }
    1.40              if (visualizer != null) {
    1.41                  visualizer.setExitStatus(executor.getExitStatus());
    1.42              }
    1.43 @@ -466,6 +479,10 @@
    1.44       * @return true if the command can be run in the current monitor lock, false otherwise.
    1.45       */
    1.46      private boolean canRun(UserCommandTask task) {
    1.47 +        if (!pendingTasks.contains(task)) {
    1.48 +            pendingTasks.add(task);
    1.49 +            //System.out.println("PENDING TASK ADDED: "+task);
    1.50 +        }
    1.51          VcsCommandExecutor vce = task.getExecutor();
    1.52          VcsCommand cmd = vce.getCommand();
    1.53          //System.out.println("canRun("+cmd.getName()+")");
    1.54 @@ -475,82 +492,106 @@
    1.55                              VcsCommand.PROPERTY_CONCURRENT_EXECUTION);
    1.56          String concurrencyWith = (String) cmd.getProperty(VcsCommand.PROPERTY_CONCURRENT_EXECUTION_WITH);
    1.57          //System.out.println("  concurrency = "+concurrency+", concurrencyWith = "+concurrencyWith);
    1.58 -        if ((concurrency == VcsCommand.EXEC_CONCURRENT_ALL
    1.59 -             && concurrencyWith == null)
    1.60 -            || concurrency == VcsCommand.EXEC_SERIAL_INERT) return true;
    1.61 -        HashMap concurrencyMap = createConcurrencyMap(concurrencyWith);
    1.62 -        String name = cmd.getName();
    1.63          boolean haveToWait = false;
    1.64 -        boolean serialOnFile = (concurrency & VcsCommand.EXEC_SERIAL_ON_FILE) != 0;
    1.65 -        boolean serialOnPackage = (concurrency & VcsCommand.EXEC_SERIAL_ON_PACKAGE) != 0;
    1.66 -        boolean serialWithParent = (concurrency & VcsCommand.EXEC_SERIAL_WITH_PARENT) != 0;
    1.67 -        boolean serialOfCommand = (concurrency & VcsCommand.EXEC_SERIAL_OF_COMMAND) != 0;
    1.68 -        boolean serialOfAll = (concurrency & VcsCommand.EXEC_SERIAL_ALL) != 0;
    1.69 -        boolean matchOnFile = false;
    1.70 -        boolean matchOnPackage = false;
    1.71 -        boolean matchWithParent = false;
    1.72 -        boolean matchOfCommand = false;
    1.73 -        //System.out.println("  serialOnFile = "+serialOnFile);
    1.74 -        //System.out.println("  serialOnPackage = "+serialOnPackage);
    1.75 -        //System.out.println("  serialWithParent = "+serialWithParent);
    1.76 -        //System.out.println("  serialOfCommand = "+serialOfCommand);
    1.77 -        //System.out.println("  serialOfAll = "+serialOfAll);
    1.78 -        //System.out.println("  commandsToTestAgainst = "+commandsToTestAgainst);
    1.79 -        //if (serialOfAll && commandsToTestAgainst.size() > 0) return false;
    1.80 -        //commandsToTestAgainst.addAll(commandsToRun);
    1.81 -        //commandsToTestAgainst.addAll(commandsWaitQueue);
    1.82 -        //commandsToTestAgainst.remove(vce);
    1.83 -        for(Iterator iter = runningTasks.iterator(); iter.hasNext(); ) {
    1.84 -            UserCommandTask cwTest = (UserCommandTask) iter.next();
    1.85 -            VcsCommandExecutor ec = cwTest.getExecutor();
    1.86 -            Collection cmdFiles = ec.getFiles();
    1.87 -            VcsCommand uc = ec.getCommand();
    1.88 -            //System.out.println("  testing with cmd = "+uc.getName());
    1.89 -            int cmdConcurrency = VcsCommandIO.getIntegerPropertyAssumeZero(uc, VcsCommand.PROPERTY_CONCURRENT_EXECUTION);
    1.90 -            //System.out.println("  cmdConcurrency = "+cmdConcurrency);
    1.91 -            if (VcsCommand.EXEC_SERIAL_INERT == cmdConcurrency) continue;
    1.92 -            if (serialOfAll) {
    1.93 -                haveToWait = true;
    1.94 -                break;
    1.95 +        if ((concurrency != VcsCommand.EXEC_CONCURRENT_ALL || concurrencyWith != null)
    1.96 +            && concurrency != VcsCommand.EXEC_SERIAL_INERT) {
    1.97 +            
    1.98 +            HashMap concurrencyMap = createConcurrencyMap(concurrencyWith);
    1.99 +            String name = cmd.getName();
   1.100 +            boolean serialOnFile = (concurrency & VcsCommand.EXEC_SERIAL_ON_FILE) != 0;
   1.101 +            boolean serialOnPackage = (concurrency & VcsCommand.EXEC_SERIAL_ON_PACKAGE) != 0;
   1.102 +            boolean serialWithParent = (concurrency & VcsCommand.EXEC_SERIAL_WITH_PARENT) != 0;
   1.103 +            boolean serialOfCommand = (concurrency & VcsCommand.EXEC_SERIAL_OF_COMMAND) != 0;
   1.104 +            boolean serialOfAll = (concurrency & VcsCommand.EXEC_SERIAL_ALL) != 0;
   1.105 +            boolean matchOnFile = false;
   1.106 +            boolean matchOnPackage = false;
   1.107 +            boolean matchWithParent = false;
   1.108 +            boolean matchOfCommand = false;
   1.109 +            //System.out.println("  serialOnFile = "+serialOnFile);
   1.110 +            //System.out.println("  serialOnPackage = "+serialOnPackage);
   1.111 +            //System.out.println("  serialWithParent = "+serialWithParent);
   1.112 +            //System.out.println("  serialOfCommand = "+serialOfCommand);
   1.113 +            //System.out.println("  serialOfAll = "+serialOfAll);
   1.114 +            //System.out.println("  commandsToTestAgainst = "+commandsToTestAgainst);
   1.115 +            //if (serialOfAll && commandsToTestAgainst.size() > 0) return false;
   1.116 +            //commandsToTestAgainst.addAll(commandsToRun);
   1.117 +            //commandsToTestAgainst.addAll(commandsWaitQueue);
   1.118 +            //commandsToTestAgainst.remove(vce);
   1.119 +            Set tasksToTest;
   1.120 +            synchronized (runningTasks) {
   1.121 +                tasksToTest = new HashSet(runningTasks);
   1.122              }
   1.123 -            String cmdName = uc.getName();
   1.124 -            if (serialOnFile) {
   1.125 -                for(Iterator it = files.iterator(); it.hasNext(); ) {
   1.126 -                    String file = (String) it.next();
   1.127 -                    if (cmdFiles.contains(file)) {
   1.128 -                        matchOnFile = true;
   1.129 +            if ((concurrency & VcsCommand.EXEC_SERIAL_WITH_PENDING) != 0) {
   1.130 +                //tasksToTest = new HashSet(runningTasks);
   1.131 +                for (Iterator pendingIt = pendingTasks.iterator(); pendingIt.hasNext(); ) {
   1.132 +                    UserCommandTask pendingTask = (UserCommandTask) pendingIt.next();
   1.133 +                    if (pendingTask != task) {
   1.134 +                        tasksToTest.add(pendingTask);
   1.135 +                    } else {
   1.136                          break;
   1.137                      }
   1.138                  }
   1.139              }
   1.140 -            if (serialOnPackage) {
   1.141 -                if (areFilesInSamePackage(files, cmdFiles)) {
   1.142 -                    matchOnPackage = true;
   1.143 -                }
   1.144 -            }
   1.145 -            if (serialWithParent) {
   1.146 -                if (isParentFolder(files, cmdFiles)) {
   1.147 -                    matchWithParent = true;
   1.148 -                }
   1.149 -            }
   1.150 -            if (serialOfCommand) {
   1.151 -                matchOfCommand = name.equals(cmdName);
   1.152 -            }
   1.153 -            // if (serialOfCommand && !matchOfCommand) do not wait
   1.154 -            if ((!serialOfCommand || matchOfCommand) && (matchOnFile || matchOnPackage || matchWithParent || matchOfCommand)) {
   1.155 -                //System.out.println("  matchOnFile = "+matchOnFile+", matchOnPackage = "+matchOnPackage+", matchWithParent = "+matchWithParent+", matchOfCommand = "+matchOfCommand);
   1.156 -                haveToWait = true;
   1.157 -                break;
   1.158 -            }
   1.159 -            Integer concurrencyWithNum = (Integer) concurrencyMap.get(cmdName);
   1.160 -            if (concurrencyWithNum != null) {
   1.161 -                if (haveToWaitFor(files, cmdFiles, concurrencyWithNum.intValue())) {
   1.162 +            for(Iterator iter = tasksToTest.iterator(); iter.hasNext(); ) {
   1.163 +                UserCommandTask cwTest = (UserCommandTask) iter.next();
   1.164 +                VcsCommandExecutor ec = cwTest.getExecutor();
   1.165 +                Collection cmdFiles = ec.getFiles();
   1.166 +                VcsCommand uc = ec.getCommand();
   1.167 +                //System.out.println("  testing with cmd = "+uc.getName()+", cmdFiles = "+cmdFiles+", TASK = "+cwTest);
   1.168 +                int cmdConcurrency = VcsCommandIO.getIntegerPropertyAssumeZero(uc, VcsCommand.PROPERTY_CONCURRENT_EXECUTION);
   1.169 +                //System.out.println("  cmdConcurrency = "+cmdConcurrency);
   1.170 +                if (VcsCommand.EXEC_SERIAL_INERT == cmdConcurrency) continue;
   1.171 +                if (serialOfAll) {
   1.172                      haveToWait = true;
   1.173                      break;
   1.174                  }
   1.175 +                String cmdName = uc.getName();
   1.176 +                if (serialOnFile) {
   1.177 +                    for(Iterator it = files.iterator(); it.hasNext(); ) {
   1.178 +                        String file = (String) it.next();
   1.179 +                        if (cmdFiles.contains(file)) {
   1.180 +                            matchOnFile = true;
   1.181 +                            break;
   1.182 +                        }
   1.183 +                    }
   1.184 +                }
   1.185 +                if (serialOnPackage) {
   1.186 +                    if (areFilesInSamePackage(files, cmdFiles)) {
   1.187 +                        matchOnPackage = true;
   1.188 +                    }
   1.189 +                }
   1.190 +                if (serialWithParent) {
   1.191 +                    if (isParentFolder(files, cmdFiles)) {
   1.192 +                        matchWithParent = true;
   1.193 +                    }
   1.194 +                }
   1.195 +                if (serialOfCommand) {
   1.196 +                    matchOfCommand = name.equals(cmdName);
   1.197 +                }
   1.198 +                // if (serialOfCommand && !matchOfCommand) do not wait
   1.199 +                if ((!serialOfCommand || matchOfCommand) && (matchOnFile || matchOnPackage || matchWithParent || matchOfCommand)) {
   1.200 +                    //System.out.println("  matchOnFile = "+matchOnFile+", matchOnPackage = "+matchOnPackage+", matchWithParent = "+matchWithParent+", matchOfCommand = "+matchOfCommand);
   1.201 +                    haveToWait = true;
   1.202 +                    break;
   1.203 +                }
   1.204 +                Integer concurrencyWithNum = (Integer) concurrencyMap.get(cmdName);
   1.205 +                if (concurrencyWithNum != null) {
   1.206 +                    if (haveToWaitFor(files, cmdFiles, concurrencyWithNum.intValue())) {
   1.207 +                        haveToWait = true;
   1.208 +                        break;
   1.209 +                    }
   1.210 +                }
   1.211              }
   1.212          }
   1.213          //System.out.println("haveToWait = "+haveToWait);
   1.214 +        if (!haveToWait) {
   1.215 +            synchronized (runningTasks) {
   1.216 +                runningTasks.add(task);
   1.217 +                //System.out.println("RUNNING TASK ADDED: "+task);
   1.218 +            }
   1.219 +            pendingTasks.remove(task);
   1.220 +            //System.out.println("PENDING TASK REMOVED: "+task);
   1.221 +        }
   1.222          return !haveToWait;
   1.223      }
   1.224      
     2.1 --- a/vcscore/src/org/netbeans/modules/vcscore/commands/VcsCommand.java	Thu Jan 16 16:35:57 2003 +0000
     2.2 +++ b/vcscore/src/org/netbeans/modules/vcscore/commands/VcsCommand.java	Thu Jan 16 16:59:49 2003 +0000
     2.3 @@ -383,6 +383,12 @@
     2.4       * command is already running.
     2.5       */
     2.6      public static final int EXEC_SERIAL_ALL = 16;
     2.7 +    /** Serial execution even with respect to the pending commands, that are waiting
     2.8 +     * for the actual execution. This flag cause, that all pending commands are
     2.9 +     * considered in addition to the already running commands when evaluating
    2.10 +     * of whether the command can be executed or not.
    2.11 +     */
    2.12 +    public static final int EXEC_SERIAL_WITH_PENDING = 32;
    2.13      /** This command is inert with all other commands. When other commands are
    2.14       * considered whether they can be executed, commands with inert concurrent
    2.15       * execution property are ignored. This can be used for meta commands,