Changeset 14547
- Timestamp:
- 10/31/12 14:30:01 (12 years ago)
- Location:
- trunk/FACT++/src
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/FACT++/src/InterpreterV8.cc
r14540 r14547 21 21 bool InterpreterV8::ReportException(TryCatch* try_catch) 22 22 { 23 if (!try_catch->CanContinue()) 24 return false; 25 23 26 const HandleScope handle_scope; 24 27 … … 27 30 if (*exception && string(*exception)=="exit") 28 31 return true; 32 if (*exception && string(*exception)=="null") 33 return false; 29 34 30 35 const Handle<Message> message = try_catch->Message(); 36 if (message.IsEmpty()) 37 return false; 31 38 32 39 // Print (filename):(line number): (message). … … 36 43 37 44 if (*filename) 38 out << *filename; 39 if (!message.IsEmpty()) 40 out << ": l." << message->GetLineNumber(); 45 out << *filename << ": "; 46 out << "l." << message->GetLineNumber(); 41 47 if (*exception) 42 48 out << ": " << *exception; 43 49 44 50 JsException(out.str()); 45 46 if (message.IsEmpty())47 return false;48 51 49 52 // Print line of source code. … … 103 106 const bool rc = ExecuteStringNT(code, file); 104 107 105 if (!exception.CanContinue()) 106 return false; 108 // Check if this is a termination exception 109 //if (!exception.CanContinue()) 110 // return false; 107 111 108 112 if (exception.HasCaught()) … … 115 119 { 116 120 return ExecuteCode(String::New(code.c_str(), code.size()), 117 121 String::New(file.c_str())); 118 122 } 119 123 … … 148 152 return ThrowException(String::New("Argument 1 not a string.")); 149 153 150 if (!args[1]->IsInt32() )151 return ThrowException(String::New("Argument 2 not an int32 ."));154 if (!args[1]->IsInt32() && !args[1]->IsString()) 155 return ThrowException(String::New("Argument 2 not an int32 and not a string.")); 152 156 153 157 if (args.Length()==3 && !args[2]->IsUint32()) 154 158 return ThrowException(String::New("Argument 3 not an uint32.")); 155 159 160 // Using a Javascript function has the advantage that it is fully 161 // interruptable without the need of C++ code 162 163 const string index = args[1]->IsInt32() ? "s.index" : "s.name"; 164 const bool timeout = args.Length()==3; 165 const string arg0 = *String::Utf8Value(args[0]); 166 const string state = args[1]->IsString() ? *String::Utf8Value(args[1]) : ""; 167 const string arg1 = args[1]->IsString() ? ("\""+state+"\"") : to_string(args[1]->Int32Value()); 168 169 if (arg0.find_first_of("\"'")!=string::npos) 170 return ThrowException(String::New("Server name must not contain quotation marks.")); 171 172 if (args[1]->IsString()) 173 if (state.find_first_of("\"'")!=string::npos) 174 return ThrowException(String::New("State name must not contain quotation marks.")); 175 176 string code = "(function(name,state,ms)" 177 "{"; 178 if (timeout) 179 code += "var t = new Date();"; 180 code += "while (1)" 181 "{" 182 "var s = dim.state(name);" 183 "if(!"+index+")throw 'Waitig for state "+arg1+" of server "+arg0+" failed.';" 184 "if(state=="+index+")return true;"; 185 if (timeout) 186 code += "if((new Date()-t)>ms)return false;"; 187 188 code += "dim.sleep();" 189 "}" 190 "})('"+arg0+"',"+arg1; 191 if (timeout) 192 code += "," + to_string(args[2]->Int32Value()); 193 code += ");"; 194 195 const HandleScope handle_scope; 196 197 // It is not strictly necessary to catch the exception, instead 198 // script->Run() could just be returned, but catching the 199 // exception allow to print the position in the file in 200 // the exception handler instead of just the posiiton in the script. 201 TryCatch exception; 202 203 const Handle<Script> script = Script::Compile(String::New(code.c_str())); 204 const Handle<Value> result = script->Run(); 205 206 return exception.HasCaught() ? exception.ReThrow() : result; 207 208 /* 156 209 const string server = *String::Utf8Value(args[0]); 157 210 const int32_t state = args[1]->Int32Value(); … … 164 217 165 218 return ThrowException(String::New(("Waitig for state "+to_string(state)+" of server '"+server+"' failed.").c_str())); 219 */ 166 220 } 167 221 … … 193 247 if (args.Length()==0) 194 248 { 195 JsSleep(1); 249 // Theoretically, the CPU usage can be reduced by maybe a factor 250 // of four using a larger value, but this also means that the 251 // JavaScript is locked for a longer time. 252 usleep(1000); 196 253 return Undefined(); 197 254 } … … 203 260 return ThrowException(String::New("Argument 1 must be an uint32.")); 204 261 205 JsSleep(args[0]->Int32Value()); 206 207 return Undefined(); 262 // Using a Javascript function has the advantage that it is fully 263 // interruptable without the need of C++ code 264 265 const string code = 266 "(function(){" 267 "var t=new Date();" 268 "while ((new Date()-t)<"+to_string(args[0]->Int32Value())+") dim.sleep();" 269 "})();"; 270 271 const HandleScope handle_scope; 272 273 const Handle<Script> script = Script::Compile(String::New(code.c_str())); 274 return script->Run(); 275 276 //JsSleep(args[0]->Int32Value()); 277 //return Undefined(); 208 278 } 209 279 … … 218 288 // Return state.name/state.index 219 289 220 HandleScope handle_scope;221 222 290 const String::Utf8Value str(args[0]); 223 291 … … 227 295 // return Undefined(); 228 296 297 HandleScope handle_scope; 298 299 // It is important to catch the exception thrown 300 // by Date::New in case of thread termination! 301 Local<Value> date; 302 { 303 TryCatch exception; 304 date = Date::New(rc.time.JavaDate()); 305 if (exception.HasCaught()) 306 return exception.ReThrow(); 307 } 308 229 309 Handle<ObjectTemplate> obj = ObjectTemplate::New(); 230 310 obj->Set(String::New("time"), date); 231 311 obj->Set(String::New("index"), rc.index<=-256?Undefined():Integer::New(rc.index), ReadOnly); 232 312 obj->Set(String::New("name"), rc.index<=-256?Undefined():String::New(rc.name.c_str()), ReadOnly); 233 obj->Set(String::New("time"), Date::New(rc.time.JavaDate()), ReadOnly);234 313 //obj->Set(String::New("toString"), String::New(("[Object state "+string(*str)+":"+to_string(rc.index)+"]").c_str())); 235 314 … … 239 318 Handle<Value> InterpreterV8::FuncExit(const Arguments &) 240 319 { 241 v8::V8::TerminateExecution(fThreadId);320 V8::TerminateExecution(fThreadId); 242 321 return ThrowException(String::New("exit")); 243 322 /* … … 306 385 Handle<Value> InterpreterV8::FuncInclude(const Arguments& args) 307 386 { 308 for (int i =0; i<args.Length(); i++)387 for (int i=0; i<args.Length(); i++) 309 388 { 310 389 const HandleScope handle_scope; … … 329 408 HandleScope handle_scope; 330 409 331 void *ptr = Local<External>::Cast(args.This()->GetInternalField(0))->Value();410 void *ptr = Handle<External>::Cast(args.This()->GetInternalField(0))->Value(); 332 411 if (!ptr) 333 412 return Boolean::New(false); … … 354 433 HandleScope handle_scope; 355 434 356 void *ptr = Local<External>::Cast(args.This()->GetInternalField(0))->Value();435 void *ptr = Handle<External>::Cast(args.This()->GetInternalField(0))->Value(); 357 436 if (!ptr) 358 437 return Undefined(); … … 452 531 } 453 532 533 time_t date = 0; 454 534 if (sql_type.find("TIMESTAMP")!=string::npos) 535 date = mysqlpp::Time((*it)[i]); 536 537 if (sql_type.find("DATETIME")!=string::npos) 538 date = mysqlpp::DateTime((*it)[i]); 539 540 if (sql_type.find(" DATE ")!=string::npos) 541 date = mysqlpp::Date((*it)[i]); 542 543 if (date>0) 455 544 { 456 row->Set(name, Date::New(time_t(mysqlpp::Time((*it)[i]))*1000), ReadOnly); 457 continue; 545 // It is important to catch the exception thrown 546 // by Date::New in case of thread termination! 547 TryCatch exception; 548 Local<Value> val = Date::New(date*1000); 549 if (exception.HasCaught()) 550 return exception.ReThrow(); 551 //if (V8::IsExecutionTerminating()) 552 // return Undefined(); 553 554 row->Set(name, val, ReadOnly); 458 555 } 459 460 if (sql_type.find("DATETIME")!=string::npos)461 {462 row->Set(name, Date::New(time_t(mysqlpp::DateTime((*it)[i]))*1000), ReadOnly);463 continue;464 }465 466 if (sql_type.find(" DATE ")!=string::npos)467 {468 row->Set(name, Date::New(time_t((mysqlpp::Date)(*it)[i])*1000), ReadOnly);469 continue;470 }471 472 556 } 473 557 … … 562 646 Handle<Value> InterpreterV8::FuncClose(const Arguments &args) 563 647 { 564 HandleScope handle_scope;565 566 //const void *ptr = Local<External>::Cast( info.This()->GetInternalField(0))->Value();648 const HandleScope handle_scope; 649 650 //const void *ptr = Local<External>::Cast(args.Holder()->GetInternalField(0))->Value(); 567 651 568 652 const String::Utf8Value str(args.Holder()->Get(String::New("name"))); 653 654 const auto it = fReverseMap.find(*str); 655 if (it!=fReverseMap.end()) 656 { 657 it->second.Dispose(); 658 fReverseMap.erase(it); 659 } 660 569 661 return Boolean::New(JsUnsubscribe(*str)); 570 662 } 571 663 572 Handle<Value> InterpreterV8::FuncGetData(const Arguments &args) 573 { 574 HandleScope handle_scope; 575 576 const String::Utf8Value str(args.Holder()->Get(String::New("name"))); 577 578 const pair<uint64_t, EventImp *> p = JsGetEvent(*str); 579 580 const EventImp *evt = p.second; 581 if (!evt) 582 return Undefined(); 583 584 //if (counter==cnt) 585 // return info.Holder();//Holder()->Get(String::New("data")); 586 587 const vector<Description> vec = JsDescription(*str); 664 Handle<Value> InterpreterV8::ConvertEvent(const EventImp *evt, uint64_t counter, const char *str) 665 { 666 Local<Value> date; 667 668 // It is important to catch the exception thrown 669 // by Date::New in case of thread termination! 670 { 671 TryCatch exception; 672 date = Date::New(evt->GetJavaDate()); 673 if (exception.HasCaught()) 674 return exception.ReThrow(); 675 } 676 677 const vector<Description> vec = JsDescription(str); 588 678 589 679 Handle<Array> ret = Array::New(); 680 ret->Set(String::New("name"), String::New(str), ReadOnly); 590 681 ret->Set(String::New("format"), String::New(evt->GetFormat().c_str()), ReadOnly); 591 ret->Set(String::New("named"), Boolean::New(vec.size()>0), ReadOnly); 592 ret->Set(String::New("counter"), Integer::New(p.first), ReadOnly); 593 ret->Set(String::New("time"), Date::New(evt->GetJavaDate()), ReadOnly); 682 ret->Set(String::New("named"), Boolean::New(vec.size()>0), ReadOnly); 594 683 ret->Set(String::New("qos"), Integer::New(evt->GetQoS()), ReadOnly); 595 684 ret->Set(String::New("size"), Integer::New(evt->GetSize()), ReadOnly); 685 ret->Set(String::New("counter"), Integer::New(counter), ReadOnly); 686 ret->Set(String::New("time"), date, ReadOnly); 596 687 597 688 typedef boost::char_separator<char> separator; … … 609 700 { 610 701 if (ptr>=evt->GetText()) 611 return handle_scope.Close(ret);702 return ret; 612 703 613 704 char type = (*it)[0]; … … 618 709 619 710 if (it==tok.end() && type!=':') 620 return ThrowException(String::New(("Format string invalid '"+evt->GetFormat()+"'").c_str()));711 return Exception::Error(String::New(("Format string invalid '"+evt->GetFormat()+"'").c_str())); 621 712 622 713 string name = pos<vec.size() ? vec[pos].name : ""; … … 652 743 ret->Set(String::New("data"), obj, ReadOnly); 653 744 654 return handle_scope.Close(ret);745 return ret; 655 746 } 656 747 catch (...) 657 748 { 658 return ThrowException(String::New(("Format string conversion '"+evt->GetFormat()+"' failed.").c_str())); 659 } 749 return Exception::Error(String::New(("Format string conversion '"+evt->GetFormat()+"' failed.").c_str())); 750 } 751 } 752 753 Handle<Value> InterpreterV8::FuncGetData(const Arguments &args) 754 { 755 HandleScope handle_scope; 756 757 const String::Utf8Value str(args.Holder()->Get(String::New("name"))); 758 759 const pair<uint64_t, EventImp *> p = JsGetEvent(*str); 760 761 const EventImp *evt = p.second; 762 if (!evt) 763 return Undefined(); 764 765 //if (counter==cnt) 766 // return info.Holder();//Holder()->Get(String::New("data")); 767 768 Handle<Value> ret = ConvertEvent(evt, p.first, *str); 769 return ret->IsNativeError() ? ThrowException(ret) : handle_scope.Close(ret); 770 } 771 772 // This is a callback from the RemoteControl piping event handling 773 // to the java script ---> in test phase! 774 void InterpreterV8::JsHandleEvent(const EventImp &evt, uint64_t cnt, const string &service) 775 { 776 if (fThreadId<0) 777 return; 778 779 const auto it = fReverseMap.find(service); 780 if (it==fReverseMap.end()) 781 return; 782 783 Locker locker; 784 785 const HandleScope handle_scope; 786 787 Handle<Object> obj = it->second; 788 if (obj.IsEmpty()) 789 return; 790 791 const Handle<String> onchange = String::New("onchange"); 792 if (!obj->Has(onchange)) 793 return; 794 795 const Handle<Value> val = obj->Get(onchange); 796 if (!val->IsFunction()) 797 return; 798 799 // ------------------------------------------------------------------- 800 // We are not in a context... we need to get into one for Array::New 801 802 Persistent<Context> context = Context::New(); 803 if (context.IsEmpty()) 804 return; 805 806 const Context::Scope scope(context); 807 808 // ------------------------------------------------------------------- 809 810 TryCatch exception; 811 812 Handle<Value> ret = ConvertEvent(&evt, cnt, service.c_str()); 813 if (ret->IsArray()) 814 { 815 Handle<Array> data = Handle<Array>::Cast(ret); 816 Handle<Value> args[] = { data }; 817 818 Handle<Function>::Cast(val)->Call(obj, 1, args); 819 } 820 821 if (exception.HasCaught()) 822 ReportException(&exception); 823 824 if (ret->IsNativeError()) 825 JsException(service+".onchange callback - "+*String::Utf8Value(ret)); 826 827 context.Dispose(); 828 829 if (ret->IsUndefined() || ret->IsNativeError() || exception.HasCaught()) 830 V8::TerminateExecution(fThreadId); 660 831 } 661 832 … … 695 866 obj->SetInternalField(0, External::New(ptr)); 696 867 868 fReverseMap[*str] = Persistent<Object>::New(obj); 869 697 870 return handle_scope.Close(obj); 698 871 … … 704 877 bool InterpreterV8::JsRun(const string &filename, const map<string, string> &map) 705 878 { 706 v8::Locker locker;879 Locker locker; 707 880 fThreadId = V8::GetCurrentThreadId(); 708 881 … … 737 910 } 738 911 739 v8::Context::Scope scope(context);740 741 Local<Array> args = Array::New(map.size());912 Context::Scope scope(context); 913 914 Handle<Array> args = Array::New(map.size()); 742 915 for (auto it=map.begin(); it!=map.end(); it++) 743 916 args->Set(String::New(it->first.c_str()), String::New(it->second.c_str())); … … 748 921 749 922 //context->Enter(); 750 v8::Locker::StartPreemption(10);923 Locker::StartPreemption(10); 751 924 const bool rc = ExecuteFile(filename); 752 925 … … 763 936 // } 764 937 765 v8::Locker::StopPreemption();938 Locker::StopPreemption(); 766 939 //context->Exit(); 940 941 for (auto it=fReverseMap.begin(); it!=fReverseMap.end(); it++) 942 it->second.Dispose(); 943 fReverseMap.clear(); 767 944 768 945 context.Dispose(); … … 774 951 #endif 775 952 776 777 953 JsEnd(filename); 778 954 … … 783 959 { 784 960 Locker locker; 961 785 962 //cout << "Terminate " << fThreadId << endl; 786 963 if (This->fThreadId>=0) 787 964 V8::TerminateExecution(This->fThreadId); 788 965 //cout << "Terminate " << fThreadId << endl; 789 Unlocker unlocker; 966 967 //Unlocker unlocker; 790 968 } 791 969 792 970 #endif 793 971 972 /* 973 #0 0x00007ffff5ae0e62 in ?? () from /usr/lib/libv8.so.3.7.12.22 974 #1 0x00007ffff5ae1969 in ?? () from /usr/lib/libv8.so.3.7.12.22 975 #2 0x00007ffff5af1976 in v8::V8::Dispose() () from /usr/lib/libv8.so.3.7.12.22 976 #3 0x0000000000426459 in RemoteControl<Console>::~RemoteControl() () 977 #4 0x00007ffff51e9901 in __run_exit_handlers (status=3, listp=0x7ffff5566688, run_list_atexi 978 #5 0x00007ffff51e9985 in __GI_exit (status=<optimized out>) at exit.c:100 979 #6 0x00000000004374db in DimErrorRedirecter::exitHandler(int) () 980 #7 0x00007ffff66bce72 in exit_user_routine () from /home/fact/FACT++.in-run-fad-loss/.libs/l 981 #8 0x00007ffff6477387 in recv_dns_dis_rout () from /home/fact/FACT++.in-run-fad-loss/.libs/l 982 #9 0x00007ffff647b79f in ast_read_h () from /home/fact/FACT++.in-run-fad-loss/.libs/libDim.s 983 #10 0x00007ffff647f388 in do_read () from /home/fact/FACT++.in-run-fad-loss/.libs/libDim.so 984 #11 0x00007ffff647ff32 in tcpip_task () from /home/fact/FACT++.in-run-fad-loss/.libs/libDim.s 985 #12 0x00007ffff6482c57 in dim_tcpip_thread () from /home/fact/FACT++.in-run-fad-loss/.libs/li 986 #13 0x00007ffff7bc4e9a in start_thread (arg=0x7ffff13be700) at pthread_create.c:308 987 #14 0x00007ffff52a1cbd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 988 */ -
trunk/FACT++/src/InterpreterV8.h
r14540 r14547 20 20 static InterpreterV8 *This; 21 21 22 // The main thread id, needed to be able to terminate 23 // the thread forcefully from 'the outside' 22 24 int fThreadId; 25 26 // A loookup table which allows to indentify the 27 // the JavaScript object corrsponding to the 28 // service name (for checking of an .onchange 29 // subscription exists for that object) 30 std::map<std::string, v8::Persistent<v8::Object>> fReverseMap; 23 31 24 32 #ifdef HAVE_SQL … … 69 77 70 78 static v8::Handle<v8::Value> Convert(char type, const char* &ptr); 79 v8::Handle<v8::Value> ConvertEvent(const EventImp *evt, uint64_t, const char *str); 71 80 #endif 72 81 … … 93 102 virtual void JsException(const std::string &) { } 94 103 virtual bool JsSend(const std::string &) { return true; } 95 virtual void JsSleep(uint32_t) { }96 virtual int JsWait(const std::string &, int32_t, uint32_t) { return -1; };104 //virtual void JsSleep(uint32_t) { } 105 //virtual int JsWait(const std::string &, int32_t, uint32_t) { return -1; }; 97 106 virtual State JsState(const std::string &) { return State(); }; 98 107 virtual void *JsSubscribe(const std::string &) { return 0; }; … … 100 109 virtual std::vector<Description> JsDescription(const std::string &) { return std::vector<Description>(); }; 101 110 virtual std::pair<uint64_t, EventImp *> JsGetEvent(const std::string &) { return std::make_pair(0, (EventImp*)0); }; 111 112 void JsHandleEvent(const EventImp &, uint64_t, const std::string &); 102 113 103 114 bool JsRun(const std::string &, const std::map<std::string,std::string> & = std::map<std::string,std::string>());
Note:
See TracChangeset
for help on using the changeset viewer.