removed passing of node weight and internal node indicator when passing
[dyninst.git] / paradyn / h / dyninstRPC.I
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 /* $Id: dyninstRPC.I,v 1.89 2001/08/23 14:43:32 schendel Exp $
43  */
44
45 #define MetStyleEventCounter    0
46 #define MetStyleSampledFunction 1
47
48 #include "common/h/Types.h"
49 #include "paradyn/src/met/mdl.h"
50
51 $remote
52 struct batch_buffer_entry {
53    int mid;
54    double startTimeStamp;
55    double endTimeStamp;
56    double value;
57 $ignore
58    batch_buffer_entry &operator=(const batch_buffer_entry &src) {
59       mid = src.mid;
60       startTimeStamp = src.startTimeStamp;
61       endTimeStamp = src.endTimeStamp;
62       value = src.value;
63       return *this;
64    }
65 $ignore
66 };
67
68 // trace data streams
69 $remote
70 struct trace_batch_buffer_entry {
71    int mid;
72    u_int length;
73    byteArray traceRecord;
74
75 $ignore
76    trace_batch_buffer_entry &operator=(const trace_batch_buffer_entry &src) {
77       mid = src.mid;
78       length = src.length;
79       traceRecord = src.traceRecord;
80       return *this;
81    }
82 $ignore
83 };
84
85 /* used by paradynd to inform a change in the status of an application. */
86 // typedef enum { procPaused, procExited } processStatus_t;
87 #define procPaused 0
88 #define procExited 1
89 typedef u_int processStatus_t;
90
91 $remote
92 abstract class mdl_expr {
93 $ignore
94 public:
95   virtual ~mdl_expr();
96   virtual bool apply(mdl_var &ret) = 0;
97   virtual bool apply(AstNode*& ast) = 0;
98   virtual bool mk_list(vector<string> &funcs) = 0;
99 #ifdef NO_MDL_PRINT
100   virtual void print(ostream& os) = 0;
101 #endif
102 $ignore
103 };
104
105 $remote
106 class mdl_v_expr : mdl_expr {
107   u_int type_;
108   int int_literal_;
109   string str_literal_;
110   string var_;
111   u_int bin_op_;
112   u_int u_op_;
113   // these two are misnomer in cases other than MDL_RVAL_BINOP. when
114   // it's a unary expression or when there's only one arg expression,
115   // left_ is used and right_ is set to NULL, but in those cases,
116   // there's really no "left" or "right" expressions. --chun
117   mdl_expr *left_;
118   mdl_expr *right_;
119   vector<mdl_expr*> *args_;
120   vector<string> fields_;
121
122   // for fields. set in paradyn's mdl.C and used in paradynd's mdl.C
123   // --chun.
124   vector<u_int> type_walk;
125   bool do_type_walk_;
126
127   bool ok_;
128
129 $ignore
130 public:
131   mdl_v_expr(int int_literal);
132   mdl_v_expr(string a_str, bool is_literal);
133   mdl_v_expr(mdl_expr* expr, vector<string> fields);
134   mdl_v_expr(string func_name, vector<mdl_expr*> *args);
135   mdl_v_expr(u_int bin_op, mdl_expr *left, mdl_expr *right);
136   mdl_v_expr(string var, u_int assign_op, mdl_expr* expr);
137   mdl_v_expr(u_int u_op, mdl_expr *expr, bool is_preop);
138   mdl_v_expr(string var, mdl_expr *index_expr);
139   ~mdl_v_expr();
140   bool apply(mdl_var &ret); // non-code-gen version
141   bool apply(AstNode*& mn); // code-gen version
142   bool mk_list(vector<string> &funcs);
143 #ifdef NO_MDL_PRINT
144   virtual void print(ostream& os) 
145   {
146     os << "MDL_V_EXPR: var=" << var_ << " do_type_walk=" << do_type_walk_;
147     unsigned size = fields_.size(), index;
148     if (size) 
149     {
150       os << "Fields: ";
151       for (index=0; index<size; index++) 
152         os << fields_[index] << " ";
153       os << endl;
154     }
155   }
156 #endif
157
158 $ignore
159 };
160
161 $remote
162 class mdl_icode {
163   mdl_expr *if_expr_;
164   mdl_expr *expr_;
165
166 $ignore
167 public:
168   mdl_icode(mdl_expr *if_expr, mdl_expr *expr);
169   ~mdl_icode();
170   bool apply(AstNode *&mn, bool mn_initialized);
171 $ignore
172 };
173
174 $remote
175 abstract class mdl_stmt {
176 $ignore
177 public:
178   virtual ~mdl_stmt() { }
179   virtual bool apply(metricDefinitionNode *mn, vector<dataReqNode*>& flags) = 0;
180   virtual bool mk_list(vector<string> &funcs) = 0;
181 #ifdef NO_MDL_PRINT
182   virtual void print(ostream& os) = 0;
183 #endif
184 $ignore
185 };
186
187 $remote
188 class mdl_list_stmt : mdl_stmt {
189   u_int type_;
190   string id_;
191   vector<string> *elements_;
192   bool is_lib_;
193   vector<string> *flavor_;
194
195 $ignore
196 public:
197   mdl_list_stmt(u_int type, string ident, vector<string> *elems,
198                 bool is_lib, vector<string> *flavor);
199   virtual ~mdl_list_stmt();
200   virtual bool apply(metricDefinitionNode *mn, vector<dataReqNode*>& flags);
201   virtual bool mk_list(vector<string> &funcs);
202 #ifdef NO_MDL_PRINT
203   virtual void print(ostream&) { }
204 #endif
205
206 $ignore
207 };
208
209 $remote
210 class mdl_for_stmt : mdl_stmt {
211   mdl_stmt *for_body_;
212   string index_name_;
213   mdl_expr *list_expr_;
214
215 $ignore
216 public:
217   mdl_for_stmt(string index_name, mdl_expr *list_exp, mdl_stmt *body);
218   virtual ~mdl_for_stmt();
219   virtual bool apply(metricDefinitionNode *mn, vector<dataReqNode*>& flags);
220   virtual bool mk_list(vector<string> &funcs);
221 #ifdef NO_MDL_PRINT
222   virtual void print(ostream&) { }
223 #endif
224
225 $ignore
226 };
227
228 $remote
229 class mdl_if_stmt : mdl_stmt {
230   mdl_expr *expr_;
231   mdl_stmt *body_;
232
233 $ignore
234 public:
235   mdl_if_stmt(mdl_expr *expr, mdl_stmt *body);
236   virtual ~mdl_if_stmt();
237   virtual bool apply(metricDefinitionNode *mn, vector<dataReqNode*>& flags);
238   virtual bool mk_list(vector<string> &funcs);
239 #ifdef NO_MDL_PRINT
240   virtual void print(ostream&) { }
241 #endif
242
243 $ignore
244 };
245
246 $remote
247 class mdl_seq_stmt : mdl_stmt {
248   vector<mdl_stmt*> *stmts_;
249
250 $ignore
251 public:
252   mdl_seq_stmt(vector<mdl_stmt*> *stmts);
253   virtual ~mdl_seq_stmt();
254   virtual bool apply(metricDefinitionNode *mn, vector<dataReqNode*>& flags);
255   virtual bool mk_list(vector<string> &funcs);
256 #ifdef NO_MDL_PRINT
257   virtual void print(ostream&) { }
258 #endif
259
260 $ignore
261 };
262
263 $remote
264 class mdl_instr_stmt : mdl_stmt {
265   u_int position_; // append or prepend
266   mdl_expr *point_expr_; // e.g. $start.entry.  Can be a fn entry, exit, or call site.
267   vector<mdl_icode*> *icode_reqs_; // the instrumentation code itself
268   u_int where_instr_; // preInsn or postInsn
269   bool constrained_; // if not true, no constraints will be applied
270
271 $ignore
272 public:
273   mdl_instr_stmt(u_int pos, mdl_expr *point_expr, vector<mdl_icode*> *i_reqs,
274                  unsigned where_instr, bool constrained);
275   virtual ~mdl_instr_stmt();
276   virtual bool apply(metricDefinitionNode *mn, vector<dataReqNode*>& flags);
277   virtual bool mk_list(vector<string> &funcs);
278 #ifdef NO_MDL_PRINT
279   virtual void print(ostream& os) {
280     os << "MDL_INSTR_STMT: constrained=" << constrained_ << " ";
281     point_expr_->print(os);
282   }
283 #endif
284
285 $ignore
286 };
287
288 $remote 
289 class mdl_constraint {
290   string id_;
291   vector<string> *match_path_;
292   vector<mdl_stmt*> *stmts_;
293   bool replace_;
294   u_int data_type_; // type of this constraint: counter, timer, etc.
295   u_int hierarchy_;
296   u_int type_; // type of things constrained: module, procedure, int, etc.
297
298 $ignore
299 public:
300   mdl_constraint(string id, vector<string> *match_path,
301                  vector<mdl_stmt*> *stmts, bool replace, u_int d_type,
302                  bool& error);
303   ~mdl_constraint();
304   bool apply(metricDefinitionNode *mn, dataReqNode *&flag,
305              vector<string>& resource, process *proc, pdThread* thr,  bool computingCost);
306   bool mk_list(vector<string> &funcs);
307   bool replace();
308   string id();
309
310 #ifdef NO_MDL_PRINT
311    friend ostream& operator<< (ostream& os, const mdl_constraint& cons) {
312      os << "\nConstraint: " << cons.id_ << " ";
313      unsigned size, index;
314      if (cons.match_path_) {
315        size = cons.match_path_->size();
316        for (index=0; index<size; index++) os << (*cons.match_path_)[index] << "/";
317        os << endl;
318      }
319      os << "Replace=" << cons.replace_ << " Data_type=" << cons.data_type_ << " Hierarchy=" 
320        << cons.hierarchy_ << " Type=" << cons.type_ << endl;
321     if (cons.stmts_) {
322       size = cons.stmts_->size();
323       os << "Statements\n";
324       for (index=0; index<size; index++) {
325         (*cons.stmts_)[index]->print(os);
326         os << " ";
327       }
328     }
329     return os;
330    }
331 #endif
332
333 $ignore
334 };
335
336 $remote
337 class mdl_metric {
338   string id_;
339   string name_;
340   string units_;
341   u_int agg_op_; // avg, sum, min, or max
342   u_int style_;  // currently, always EventCounter
343   u_int type_;   // counter, processTimer, or wallTimer
344   vector<mdl_stmt*> *stmts_; // for "base is <type_> { ... }
345   vector<string> *flavors_; // which flavors this metric is valid for
346   vector<mdl_constraint*> *constraints_;
347   vector<string> *temp_ctr_; // temporary counters
348   bool developerMode_;
349   int unitstype_; // normalized, unnormalized, or sampled
350
351 $ignore
352 public:
353   mdl_metric(string id, string name, string units,
354              u_int agg, u_int style, u_int type,
355              vector<mdl_stmt*> *mv, vector<string> *flavs, 
356              vector<mdl_constraint*> *cons,
357              vector<string> *temp_c, bool developerMode,int unitstype);
358   ~mdl_metric();
359 #ifdef NO_MDL_PRINT
360   friend ostream& operator<< (ostream &os, const mdl_metric& met) {
361     os << "\nMetric: " << met.id_ << " " << met.name_ << " agg_op=" << met.agg_op_ << " style=" 
362       << met.style_ << " type=" << met.type_ << endl;
363     unsigned size, index;
364     if (met.stmts_) {
365       size = met.stmts_->size();
366       os << "Statements\n";
367       for (index=0; index<size; index++) {
368         (*met.stmts_)[index]->print(os);
369          os << " ";
370       }
371     }
372     if (met.constraints_) {
373       size = met.constraints_->size();
374       os << "Constraints\n";
375       for (index=0; index<size; index++) {
376         os << *((*met.constraints_)[index]) << " ";
377       }
378     }
379     return os;
380   }
381 #endif
382   metricDefinitionNode *apply(vector< vector<string> >&focus, 
383                               string& flat_name,
384                               vector<process *> procs,
385                               vector< vector<pdThread *> >& threadsVec,
386                               bool replace_components_if_present,
387                               bool computingCost);
388 $ignore
389 };
390
391 /* descriptive information about a metric */
392 $remote struct metricInfo { 
393     string name;
394     int style;
395     int aggregate;
396     string units;
397     bool developerMode;
398     int unitstype;
399     u_int handle;  // this is currently ignored by the daemons 
400 };
401
402 $remote struct focusStruct {
403   vector<u_int> focus;
404 };
405
406 $remote struct resourceInfoCallbackStruct {
407    u_int temporaryId;
408    vector<string> resource_name;
409    string abstraction;
410    u_int type;
411 };
412
413 /*
414  * Create a paradynd process.
415  *
416  */
417 int createDaemon(string machine,
418                  string login,
419                  string name,
420                  vector<string> argv);
421
422
423 $remote dynRPC {
424     $base 4000;
425     $version 58;
426
427     //
428     // Define a program to run. 
429     // argv: the command and arguments
430     // dir: working directory where program will run.
431     int addExecutable(vector<string> argv, string dir);
432
433     //
434     // Connect up with a running program (not possible on all platforms).
435     // 'path' gives the full path name to the executable, used only to read
436     // the symbol table.
437     // values for 'afterAttach': 1 --> pause, 2 --> run, 0 --> leave as is
438     //
439     bool attach(string path, int pid, int afterAttach);
440
441     //
442     // Start an application running (This starts the actual execution).
443     //
444     bool startProgram(int program);
445
446     //
447     //   Stop a process
448     //
449     bool pauseProgram(int program);
450
451     //
452     //   Stop all processes associted with the application.
453     //
454     bool pauseApplication();
455
456     //
457     // Continue a paused process
458     //
459     void continueProgram(int program);
460
461     //
462     // Continue all of the processes
463     //
464     void continueApplication();
465
466     //
467     // Disconnect the tool from the process.
468     //    pause - leave the process in a stopped state.
469     //
470     //
471     bool detachProgram(int program, bool pause);
472
473     //  
474     // Monitor the dynamic call sites contained in function <function_name>
475     //          
476     void MonitorDynamicCallSites(string function_name);
477
478     //
479     // Called by paradynd when a new process starts up.  Specifically, paradynd
480     // calls it when it detects that the new program has finished running
481     // its DYNINST().
482     //
483     // If the state of the appl as a whole is 'running' then we (paradyn) will
484     // issue an igen call to continue this new process; otherwise, we'll leave it
485     // paused.
486     //
487     $upcall $async void newProgramCallbackFunc( int pid, 
488                                                 vector<string> argv, 
489                                                 string machine,
490                                                 bool calledFromExec,
491                                                 bool wantToInitiallyRun);
492     //
493     // Message display with "error" visual characteristics
494     // and lookup in error database for explanation. This function
495     // calls showError function in UIM class
496     //
497     $upcall $async void showErrorCallback (int errCode,
498                                            string errString,
499                                            string hostName);
500
501    // batch the samples (paradynd-->paradyn) to get better performance
502    // the functionality is essentially the same as the 
503    // sampleDataCallbackFunc, which is now obsolete
504
505    $virtual $upcall $async
506    void batchSampleDataCallbackFunc(int program,
507                                     vector<batch_buffer_entry> theBatchBuffer);
508
509    // batch the traces (paradynd-->paradyn) to get better performance
510    // the functionality is essentially the same as the 
511    // batchSampleDataCallbackFunc, which is now obsolete
512
513    $virtual $upcall $async
514    void batchTraceDataCallbackFunc(int program,
515                                     vector<trace_batch_buffer_entry> theTraceBatchBuffer);
516
517    //
518    // XXXX - Hack this should be generalized into a vector.
519    //
520    $virtual $upcall $async void cpDataCallbackFunc(int program,
521                                                       double timeStamp,
522                                                       int context,
523                                                       double total,
524                                                       double share);
525
526    // 
527    // Handler that reports the initial time that the daemon started the
528    // the first process.  Called after DYNINSTinit completed.
529    // The earliest (absolute) initial time will become the base time (0)
530    //
531    $virtual $upcall $async void setDaemonStartTime(int program,
532                                                    double startTime);
533
534    // 
535    // Handler that reports the initial actual value the metric with id mid.
536    // Used to reconstruct the actual value of mid at any point.  Done
537    // by integrating across the change in sample values and then adding
538    // the initial actual value.
539    //
540    $virtual $upcall $async void setInitialActualValueFE(int mid,
541                                                         double initActualVal);
542
543
544     //
545     // Handler that gets called when a new resource is defined.
546     //
547     // temporaryId      - daemon generated resource id (it will become the 
548     //                          permanent id, unless there are conflicts
549     //                          with id's generated by another daemon)
550     // resource_name    - name of resource, divided into parts
551     // abstraction      - abstraction to which it belongs     
552     // type             - the MDL type for this resource (MDL_T_STRING, etc.)
553     // 
554     $virtual $upcall $async void resourceInfoCallback(u_int temporaryId, 
555                                              vector<string> resource_name,
556                                              string abstraction, u_int type);
557
558     $virtual $upcall $async void severalResourceInfoCallback(vector<resourceInfoCallbackStruct>);
559         
560     //
561     // Handlers that gets called in paradynd when a new call graph relationship
562     //  is defined....
563     // Names post-fixed w/ Callback to preserve convention that functions
564     //  names *Callback represent callbacks from paradynd TO paradyn....
565     //
566
567     //Notify the DM that a new executable file is being parsed, so it
568     //will be ready for the call graph relationships for this graph.
569     $virtual $upcall $async void CallGraphAddProgramCallback(string exe_name);
570
571     //Add resource to the call graph specified by "exe_name", 
572     $virtual $upcall $async void AddCallGraphNodeCallback(string exe_name, 
573                                                           string resource);
574
575     //Specify the children of a resource for CallGraph "exe_name"
576     $virtual $upcall $async void AddCallGraphStaticChildrenCallback(
577                                                       string exe_name, 
578                                                       string resource, 
579                                                       vector<string> children);
580     //Specify the root node if CallGraph "exe_name"
581     $virtual $upcall $async void CallGraphSetEntryFuncCallback(string exe_name,
582                                                             string entry_func);
583     
584     //Notify the DM that all static info for a given call graph has been
585     //reported.
586     $virtual $upcall $async void CallGraphFillDone(string exe_name);    
587
588     //Notify the call graph that function <parent> contains one or more
589     //dynamic call sites.
590     $virtual $upcall $async void CallGraphAddDynamicCallSiteCallback(string exe_name, 
591                                                              string parent);
592
593     //Notify the call graoh that function <parent> calls function <child>
594     //through a dynamic call site.
595     $virtual $upcall $async void AddCallGraphDynamicChildCallback(
596                                   string exe_name,string parent, string child);
597
598
599     // In case there are conflicts between the resource Id's generated by
600     // the daemons, paradyn generates a new Id and report it to the daemon.
601     $async void resourceInfoResponse(vector<u_int> temporaryIds,
602                                      vector<u_int>resourceIds);
603
604
605     $virtual $upcall $async void resourceBatchMode(bool);
606
607     //
608     // Handler that gets called when new mapping data is collected.
609     //
610     $upcall $async void mappingInfoCallback(int program, 
611                                             string abstraction, 
612                                             string type, 
613                                             string key,
614                                             string value);
615
616     // Upcall for a new metric being defined.
617     //
618     $upcall $async void newMetricCallback(metricInfo info); 
619
620     $async void setSampleRate(double sampleInterval);
621
622     //
623     // tell dyninst to ignore this resource for instrumentation.
624     //    Currently this only applies to programs, modules, and procedures.
625     //    False - suppress
626     //    True - enable
627     //
628     bool setTracking(u_int resource_id, bool);
629
630     //
631     // Routines to control data collection on a performanceStream.
632     //
633     // resourceList     - a list of resources
634     // metric   - what metric to collect data for
635     //
636     $async void enableDataCollection(vector<focusStruct> focus, 
637                                       vector<string> metric,
638                                       vector<u_int> mi_ids, 
639                                       u_int daemon_id,
640                                       u_int request_id);
641     //
642     // synchronous enable call, for propogating metrics
643     //
644     int enableDataCollection2(vector<u_int> focus, string metric, int id);
645
646     //
647     // Upcall to tell paradyn that all daemons are ready after a metric 
648     // enable request
649     //
650     $upcall $async void enableDataCallback(u_int daemon_id, 
651                                            vector<int> return_id,
652                                            vector<u_int> mi_ids,
653                                            u_int request_id);
654     //
655     // Upcall to tell paradyn that all daemons are ready after computing 
656     // the value for predicted data cost
657     //    id: an identifier for the request
658     //  client_id: an id passed by calling thread
659     //
660     $upcall $async void getPredictedDataCostCallback(u_int id,
661                                                      u_int req_id,
662                                                      float val,
663                                                      u_int clientID);
664
665     //
666     // stop collecting data for the named mi.
667     //     mi           - a metricInstance returned by enableDataCollection.
668     //
669     $async void disableDataCollection(int mi);
670
671     // 
672     // called by a daemon when there is no more data to be sent for a metric
673     // instance, because all processes have exited.
674     $virtual $upcall $async void endOfDataCollection(int mi);
675
676     //
677     // Return the expected cost of collecting performance data for a single
678     //    metric at a given focus.  The value returned is the fraction of
679     //    perturbation expected (i.e. 0.10 == 10% slow down expected).
680     //    id: an identifier for the request
681     //  client_id: an id passed by calling thread
682     //
683     $async void getPredictedDataCost(u_int id,
684                                      u_int req_id,
685                                      vector<u_int> focus, 
686                                      string metric,
687                                      u_int clientID);
688
689     //
690     // Get the static configuration information.
691     //
692     vector<metricInfo> getAvailableMetrics();
693
694     //
695     // Create a new resource.
696     //
697     void addResource(u_int parent, u_int id, string name, u_int type);
698
699     // should be removed for output redirection
700     // left untouched for paradynd log info use
701     //
702     // stdio or stderr from an application.
703     //
704     $upcall $async void applicationIO(int pid, int len, string line);
705
706     //
707     // stdio or stderr from an application.
708     //
709     $virtual $upcall $async void reportStatus(string line);
710
711     //
712     // Debugger style calls.
713     //
714     //
715     string getStatus(int pid);
716     void coreProcess(int pid);
717
718     //
719     // For paradynd's that may get started, but not by paradyn
720     // This allows them to report system information
721     // flavor = programming environment {"pvm", "cm5", ... }
722     $virtual $upcall $async void reportSelf(string machine, 
723                                             string program, 
724                                             int pid,
725                                             string flavor);
726
727     //
728     // this call is used by paradynd to inform paradyn of a change in
729     // the status of a process -- the process stops (due to a signal), 
730     // or the process exits
731     //
732     $virtual $upcall $async void processStatus(int pid, u_int procstat);
733
734     //
735     // For timing and other measurements of paradynd
736     //
737     void printStats();
738
739     // MDL methods
740     $async void send_metrics(vector<mdl_metric*> *);
741     $async void send_constraints(vector<mdl_constraint*>*);
742     $async void send_stmts(vector<mdl_stmt*> *);
743     $async void send_libs(vector<string>*);
744     $async void send_no_libs();
745
746     // get the current wall clock time of the daemon to adjust for clock differences
747     double getTime();
748 };