CTS Framework Parsing (4)-Adding tasks

Source: Internet
Author: User
Tags arrays flush
Debug



The entrance to debug is in the Ctsconsole class, so we put the first breakpoint on line 249:


Console console = new Ctsconsole ();


Press F6 and press F5 to enter the Console.startconsole method.




Press F5 to enter the Globalconfiguration.createglobalconfiguration method.




In this method, the main is to read the global configuration file and set the Iglobalconfiguration interface object sinstance. The main method is to read the Getglobalconfigpath () of the file for 95 rows:


private static String Getglobalconfigpath () throws ConfigurationException {        
String path = system.getenv (global_config_variable);         if (path! = null) {            //Don ' t actually check for accessibility here, since the variable             //m Ight be specifying             //a Java resource rather than a filename. Even so, this can help             //The user figure out     
        //which global config (if any) is picked up by TF.             system.err           
           .format ("Attempting to use global config \"%s\ "from Variable $%s.\n",                             path,
global_config_variable);
            return path;         }         file file = new file (global_config_
FILENAME);         if (file.exists ()) {            
Path = File.getpath ();             system.err.format (                      "Attempting to use auto Detected global config \"%s\ ". \ n", &nbsp
;                   path);
            system.err.flush ();
            return path;         }         //Fixme:search in tradefed.sh launch Dir (or classpath?)
        return null;     }

first determine whether the global configuration file system variables are set, if not set, then directly in the current file directory to find the Tf_global_config.xml file。 Obviously, this program has none of these, so the result of the method return should be null. Back to the Createglobalconfiguration (string[] args) method:


if (Globalconfigpath! = null) {
				//Found a global config file; attempt to parse and use it
				sinstance = Configfacto Ry.createglobalconfigurationfromargs (
						Arrayutil.buildarray (new string[] {Globalconfigpath},
								args), Nonglobalargs);
				System.err.format ("Success!  Using global config \ "%s\" \ n ",
						Globalconfigpath);
			} else {
				//Use Default global config
				sinstance = new Globalconfiguration ();
				Nonglobalargs = Arrays.aslist (args);
			}
			return Nonglobalargs;

Because the returned path is NULL, it jumps directly into the Else statement block, new, and does not have any properties set. Finally, the command-line arguments are encapsulated in the list, and then the console sets the parameters, eventually starting the thread to perform the task. So the second breakpoint should be hit in the console's Run method, then press F8 to enter the Run method.




The Run method first makes some arguments, if it is empty, start the Commandscheduler thread, the inside will go from the execution queue to take out the first element, if the obtained queue is empty will end.

If the parameter is not empty, other actions are performed in addition to starting the Commandscheduler thread, as follows:


public void Run () {list<string> Arrrgs = Mmainargs; Fallback, in case this isn ' t set already if (Mscheduler = = null) {Mscheduler = new Commandschedule
        R ();
            } try {//Check System.Console () since JLine doesn ' t seem to consistently know whether or not
            The console is functional. if (!isconsolefunctional ()) {if (Arrrgs.isempty ()) {PrintLine ("No commands for Non-i Nteractive mode;
                    Exiting. "); 
                    Fixme:need to run the scheduler this things blocking on it//Fixme:will be released.
                    Mscheduler.start ();
                    Mscheduler.await ();
                Return
                    } else {printline ("non-interactive mode:running initial command then exiting.");
                Mshouldexit = true; }}//Wait for the Commandscheduler to start. It'll hold the JVM open (since the Console//thread was a Daemon thread), and also we require it to having STA
            rted So, we can//start processing user input.
            Mscheduler.start ();

            Mscheduler.await ();
            String input = "";
            Capturelist groups = new Capturelist ();

            String[] tokens;  Note:since Console is a daemon thread, the JVM could exit without us actually leaving//this read loop.
            This was by design.

                    do {if (Arrrgs.isempty ()) {input = Getconsoleinput (); if (input = = null) {//Usually the result of getting EOF on the console p
                        Rintline (""); PrintLine ("Received EOF;
                        Quitting ... ");
                        Mshouldexit = true;
                    Break } tokens = nulL
                    try {tokens = Quotationawaretokenizer.tokenizeline (input);
                        } catch (IllegalArgumentException e) {printline (String.Format ("Invalid input:%s.", input));
                    Continue
                    } if (tokens = = NULL | | tokens.length = = 0) {continue; }} else {PrintLine (String.Format ("Using commandline arguments as starting command:%
                    S ", Arrrgs)); 
                        if (Mconsolereader! = null) {//ADD the starting command as the first item in the console history
                        Fixme:this won't properly escape commands that were properly escaped  Fixme:on the commandline.
                  That said, it'll still is more convenient//Fixme:than copying by hand.      Final String cmd = Arrayutil.join ("", Arrrgs);
                    Mconsolereader.gethistory (). addtohistory (CMD);
                    } tokens = Arrrgs.toarray (new string[0]);
                Empty Arrrgs = Collections.emptylist ();
                } Runnable command = Mcommandtrie.retrieve (groups, tokens);
                if (command! = null) {executecmdrunnable (command, groups);  } else {PrintLine (String.Format ("Unable to handle command '%s ').
                Enter ' help ' for help. ", Tokens[0]));
            } runutil.getdefault (). Sleep (100);
        } while (!mshouldexit); } catch (Exception e) {printline ("Console received an unexpected Exception (shown below);
            Shutting down TF. ");
        E.printstacktrace ();
            } finally {Mscheduler.shutdown (); Make sure that we Don ' t quit with messages still in the buffers System.err.flush ();
        System.out.flush (); }
    }

The above code mainly looks at about 846 lines of

Executecmdrunnable (command, groups);


Let's look at the implementation of this method:


/**
     * Execute a command.
     * <p/>
     * Exposed for unit testing
     *
    /@SuppressWarnings ("unchecked")
    void Executecmdrunnable ( Runnable command, capturelist groups) {
        if (command instanceof argrunnable) {
            //fixme:verify that command Implem Ents argrunnable<capturelist> instead
            //fixme:of just argrunnable
            ((argrunnable<capturelist>) command). Run (groups);
        } else {
            command.run ();
        }
    }

You will find that the program jumps to


((argrunnable<capturelist>) command). Run (groups);

And then press F5 to jump not go in, this time the program into the




So make a breakpoint in this place, restart Debug, and you'll get into this place. The method calls the Commandscheduler.addcommand method and enters the method


/** * {@inheritDoc} */@Override public boolean AddCommand (string[] args, long totalexectime) {
            try {//Get information about CTS configuration file iconfiguration config = getconfigfactory (). Createconfigurationfromargs (args); Print help information, print only the option information for the importance type if (Config.getcommandoptions (). Ishelpmode ()) {GE
                Tconfigfactory (). Printhelpforconfig (args, true, System.out);
                System.out.flush (); Print all option information} else if (Config.getcommandoptions (). Isfullhelpmode ()) {getconfigfactory (). pr
            Inthelpforconfig (args, false, System.out); } else if (Config.getcommandoptions (). Isdryrunmode ()) {if (Config.getcommandoptions (). Isnoisydryrunmode ()
                {Clog.loganddisplay (Loglevel.debug, "DRY RUN:%s", arrays.tostring (args)); } else {clog.d ("Dry run mode;
    Skipping adding command:%s ", arrays.tostring (args));            }} else {config.validateoptions ();
                if (Config.getcommandoptions (). Runonalldevices ()) {addcommandforalldevices (totalexectime, args);
                    } else {Commandtracker cmdtracker = Createcommandtracker (args);
                    Cmdtracker.incrementexectime (Totalexectime);
                    Executablecommand cmdinstance = Createexecutablecommand (cmdtracker, config, false);
                Addexeccommandtoqueue (cmdinstance, 0);
            } return true;
            }} catch (ConfigurationException e) {e.printstacktrace ();  Fixme:do this with JLine somehow-ANSI support//Note:make-Sure not-log (aka record) this line, as
            (args) may contain passwords.
            System.out.println (String.Format ("Error while processing args:%s", arrays.tostring (args)); System.out.println (E.GetMessage ());
        System.out.println ();
    } return false;
 }

Let's look at the first line of code:


iconfiguration config = getconfigfactory (). Createconfigurationfromargs (args);

The method will find the XML file under the Config directory according to the second parameter in the parameter, read the contents, and then configure the 9 large components of the CTS framework (this is put in the next article). When the Config object is obtained, it is determined whether the whole device is running or a single device is running, by default the whole device is running. If a single device is running, you need to specify the SN number of the device, and the framework finds the device based on the SN number. Finally, the execution plan is put into the queue.




The addition to this task is complete. The task queue is constantly accepting new tasks, and then there is a loop in the Commandscheduler run method, each time taking the first task to execute.


 try {//Notify other threads that we ' re running.
            
            Mrunlatch.countdown ();
            Idevicemanager manager = Getdevicemanager ();
                while (!isshutdown ()) {Executablecommand cmd = Dequeueconfigcommand ();
                    if (cmd! = null) {ideviceselection options = Cmd.getconfiguration (). getdevicerequirements ();
                    Itestdevice device = Manager.allocatedevice (0, options); if (device! = NULL) {//Spawn off a thread to perform the invocation Invo
                        Cationthread Invthread = startinvocation (manager, device, CMD);
                        Addinvocationthread (Invthread);
                        if (Cmd.isloopmode ()) {Addnewexeccommandtoqueue (Cmd.getcommandtracker ());
      }} else {//no device available for command, put the back in queue                  Increment exec time to ensure fair scheduling among commands when devices//
                        is scarce Cmd.getcommandtracker (). Incrementexectime (1);
                        Addexeccommandtoqueue (cmd, no_device_delay_time);
                    Clog.loganddisplay (Loglevel.error,string.format ("Can ' t find device%s.", Options.getserials ()));
            }}} mcommandtimer.shutdown ();
            CLOG.I ("Waiting for invocation threads-complete");
            List<invocationthread> threadlistcopy;
                Synchronized (this) {threadlistcopy = new arraylist<invocationthread> (Minvocationthreads.size ());
            Threadlistcopy.addall (minvocationthreads);
            } for (thread thread:threadlistcopy) {waitforthread (thread);
            } closeremoteclient ();
 if (Mremotemanager! = null) {               Mremotemanager.cancel ();
            } exit (manager);
            CleanUp ();
        Clog.loganddisplay (Loglevel.info, "all done"); 
            } finally {//Make sure that we don ' t quit with messages still in the buffers System.err.flush ();
        System.out.flush (); }

To add to this task even if finished, the next article resolves how to parse the configuration file.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.