| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "bin/vmstats_impl.h" | 5 #include "bin/vmstats_impl.h" |
| 6 | 6 |
| 7 #include <sstream> | 7 #include <sstream> |
| 8 | 8 |
| 9 #include "bin/file.h" | 9 #include "bin/file.h" |
| 10 #include "bin/log.h" | 10 #include "bin/log.h" |
| 11 #include "bin/platform.h" | 11 #include "bin/platform.h" |
| 12 #include "bin/socket.h" | 12 #include "bin/socket.h" |
| 13 #include "bin/thread.h" | 13 #include "bin/thread.h" |
| 14 #include "bin/utils.h" | 14 #include "bin/utils.h" |
| 15 #include "include/dart_debugger_api.h" | 15 #include "include/dart_debugger_api.h" |
| 16 #include "platform/json.h" | 16 #include "platform/json.h" |
| 17 | 17 |
| 18 #define BUFSIZE 8192 | 18 #define BUFSIZE 8192 |
| 19 #define RETRY_PAUSE 100 // milliseconds | 19 #define RETRY_PAUSE 100 // milliseconds |
| 20 | 20 |
| 21 static const char* INDEX_HTML = "index.html"; | 21 static const char* INDEX_HTML = "index.html"; |
| 22 static const char* VMSTATS_HTML = "vmstats.html"; | 22 static const char* VMSTATS_HTML = "vmstats.html"; |
| 23 static const char* DEFAULT_HOST = "localhost"; | 23 static const char* DEFAULT_HOST = "localhost"; |
| 24 | 24 |
| 25 // Global static pointer used to ensure a single instance of the class. | 25 // Global static pointer used to ensure a single instance of the class. |
| 26 VmStats* VmStats::instance_ = NULL; | 26 VmStats* VmStats::instance_ = NULL; |
| 27 dart::Monitor VmStats::instance_monitor_; | 27 dart::Monitor* VmStats::instance_monitor_; |
| 28 dart::Mutex VmStatusService::mutex_; | 28 dart::Mutex* VmStatusService::mutex_; |
| 29 | 29 |
| 30 | 30 |
| 31 void VmStats::Start(int port, const char* root_dir) { | 31 void VmStats::Start(int port, const char* root_dir) { |
| 32 if (instance_ != NULL) { | 32 if (instance_ != NULL) { |
| 33 FATAL("VmStats already started."); | 33 FATAL("VmStats already started."); |
| 34 } | 34 } |
| 35 MonitorLocker ml(&instance_monitor_); | |
| 36 instance_ = new VmStats(); | 35 instance_ = new VmStats(); |
| 36 instance_monitor_ = new dart::Monitor(); |
| 37 VmStatusService::InitOnce(); | 37 VmStatusService::InitOnce(); |
| 38 Socket::Initialize(); | 38 Socket::Initialize(); |
| 39 | 39 |
| 40 if (root_dir != NULL) { | 40 if (root_dir != NULL) { |
| 41 instance_->root_directory_ = root_dir; | 41 instance_->root_directory_ = root_dir; |
| 42 } | 42 } |
| 43 | 43 |
| 44 // TODO(tball): allow host to be specified. | 44 // TODO(tball): allow host to be specified. |
| 45 char* host = const_cast<char*>(DEFAULT_HOST); | 45 char* host = const_cast<char*>(DEFAULT_HOST); |
| 46 OSError* os_error; | 46 OSError* os_error; |
| 47 const char* host_ip = Socket::LookupIPv4Address(host, &os_error); | 47 const char* host_ip = Socket::LookupIPv4Address(host, &os_error); |
| 48 if (host_ip == NULL) { | 48 if (host_ip == NULL) { |
| 49 Log::PrintErr("Failed IP lookup of VmStats host %s: %s\n", | 49 Log::PrintErr("Failed IP lookup of VmStats host %s: %s\n", |
| 50 host, os_error->message()); | 50 host, os_error->message()); |
| 51 return; | 51 return; |
| 52 } | 52 } |
| 53 | 53 |
| 54 const intptr_t BACKLOG = 128; // Default value from HttpServer.dart | 54 const intptr_t BACKLOG = 128; // Default value from HttpServer.dart |
| 55 int64_t address = ServerSocket::CreateBindListen(host_ip, port, BACKLOG); | 55 int64_t address = ServerSocket::CreateBindListen(host_ip, port, BACKLOG); |
| 56 if (address < 0) { | 56 if (address < 0) { |
| 57 Log::PrintErr("Failed binding VmStats socket: %s:%d\n", host, port); | 57 Log::PrintErr("Failed binding VmStats socket: %s:%d\n", host, port); |
| 58 return; | 58 return; |
| 59 } | 59 } |
| 60 instance_->bind_address_ = address; | 60 instance_->bind_address_ = address; |
| 61 Log::Print("VmStats URL: http://%s:%"Pd"/\n", host, Socket::GetPort(address)); | 61 Log::Print("VmStats URL: http://%s:%"Pd"/\n", host, Socket::GetPort(address)); |
| 62 | 62 |
| 63 MonitorLocker ml(instance_monitor_); |
| 63 instance_->running_ = true; | 64 instance_->running_ = true; |
| 64 int err = dart::Thread::Start(WebServer, address); | 65 int err = dart::Thread::Start(WebServer, address); |
| 65 if (err != 0) { | 66 if (err != 0) { |
| 66 Log::PrintErr("Failed starting VmStats thread: %d\n", err); | 67 Log::PrintErr("Failed starting VmStats thread: %d\n", err); |
| 67 Shutdown(); | 68 Shutdown(); |
| 68 } | 69 } |
| 69 } | 70 } |
| 70 | 71 |
| 71 | 72 |
| 72 void VmStats::Stop() { | 73 void VmStats::Stop() { |
| 73 MonitorLocker ml(&instance_monitor_); | 74 ASSERT(instance_ != NULL); |
| 74 if (instance_ != NULL) { | 75 MonitorLocker ml(instance_monitor_); |
| 75 instance_->running_ = false; | 76 instance_->running_ = false; |
| 76 } | |
| 77 } | 77 } |
| 78 | 78 |
| 79 | 79 |
| 80 void VmStats::Shutdown() { | 80 void VmStats::Shutdown() { |
| 81 MonitorLocker ml(&instance_monitor_); | 81 ASSERT(instance_ != NULL); |
| 82 MonitorLocker ml(instance_monitor_); |
| 82 Socket::Close(instance_->bind_address_); | 83 Socket::Close(instance_->bind_address_); |
| 83 delete instance_; | 84 delete instance_; |
| 84 instance_ = NULL; | 85 instance_ = NULL; |
| 85 } | 86 } |
| 86 | 87 |
| 87 | 88 |
| 88 void VmStats::AddIsolate(IsolateData* isolate_data, | 89 void VmStats::AddIsolate(IsolateData* isolate_data, |
| 89 Dart_Isolate isolate) { | 90 Dart_Isolate isolate) { |
| 90 MonitorLocker ml(&instance_monitor_); | |
| 91 if (instance_ != NULL) { | 91 if (instance_ != NULL) { |
| 92 MonitorLocker ml(instance_monitor_); |
| 92 instance_->isolate_table_[isolate_data] = isolate; | 93 instance_->isolate_table_[isolate_data] = isolate; |
| 93 } | 94 } |
| 94 } | 95 } |
| 95 | 96 |
| 96 | 97 |
| 97 void VmStats::RemoveIsolate(IsolateData* isolate_data) { | 98 void VmStats::RemoveIsolate(IsolateData* isolate_data) { |
| 98 MonitorLocker ml(&instance_monitor_); | |
| 99 if (instance_ != NULL) { | 99 if (instance_ != NULL) { |
| 100 MonitorLocker ml(instance_monitor_); |
| 100 instance_->isolate_table_.erase(isolate_data); | 101 instance_->isolate_table_.erase(isolate_data); |
| 101 } | 102 } |
| 102 } | 103 } |
| 103 | 104 |
| 104 | 105 |
| 105 static const char* ContentType(const char* url) { | 106 static const char* ContentType(const char* url) { |
| 106 const char* suffix = strrchr(url, '.'); | 107 const char* suffix = strrchr(url, '.'); |
| 107 if (suffix != NULL) { | 108 if (suffix != NULL) { |
| 108 if (!strcmp(suffix, ".html")) { | 109 if (!strcmp(suffix, ".html")) { |
| 109 return "text/html; charset=UTF-8"; | 110 return "text/html; charset=UTF-8"; |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 } | 288 } |
| 288 | 289 |
| 289 | 290 |
| 290 // Global static pointer used to ensure a single instance of the class. | 291 // Global static pointer used to ensure a single instance of the class. |
| 291 VmStatusService* VmStatusService::instance_ = NULL; | 292 VmStatusService* VmStatusService::instance_ = NULL; |
| 292 | 293 |
| 293 | 294 |
| 294 void VmStatusService::InitOnce() { | 295 void VmStatusService::InitOnce() { |
| 295 ASSERT(VmStatusService::instance_ == NULL); | 296 ASSERT(VmStatusService::instance_ == NULL); |
| 296 VmStatusService::instance_ = new VmStatusService(); | 297 VmStatusService::instance_ = new VmStatusService(); |
| 298 VmStatusService::mutex_ = new dart::Mutex(); |
| 297 | 299 |
| 298 // Register built-in status plug-ins. RegisterPlugin is not used because | 300 // Register built-in status plug-ins. RegisterPlugin is not used because |
| 299 // this isn't called within an isolate, and because parameter checking | 301 // this isn't called within an isolate, and because parameter checking |
| 300 // isn't necessary. | 302 // isn't necessary. |
| 301 instance_->RegisterPlugin(&Dart_GetVmStatus); | 303 instance_->RegisterPlugin(&Dart_GetVmStatus); |
| 302 | 304 |
| 303 // TODO(tball): dynamically load any additional plug-ins. | 305 // TODO(tball): dynamically load any additional plug-ins. |
| 304 } | 306 } |
| 305 | 307 |
| 306 | 308 |
| 307 int VmStatusService::RegisterPlugin(Dart_VmStatusCallback callback) { | 309 int VmStatusService::RegisterPlugin(Dart_VmStatusCallback callback) { |
| 308 MutexLocker ml(&mutex_); | 310 MutexLocker ml(mutex_); |
| 309 if (callback == NULL) { | 311 if (callback == NULL) { |
| 310 return -1; | 312 return -1; |
| 311 } | 313 } |
| 312 VmStatusPlugin* plugin = new VmStatusPlugin(callback); | 314 VmStatusPlugin* plugin = new VmStatusPlugin(callback); |
| 313 VmStatusPlugin* list = instance_->registered_plugin_list_; | 315 VmStatusPlugin* list = instance_->registered_plugin_list_; |
| 314 if (list == NULL) { | 316 if (list == NULL) { |
| 315 instance_->registered_plugin_list_ = plugin; | 317 instance_->registered_plugin_list_ = plugin; |
| 316 } else { | 318 } else { |
| 317 list->Append(plugin); | 319 list->Append(plugin); |
| 318 } | 320 } |
| 319 return 0; | 321 return 0; |
| 320 } | 322 } |
| 321 | 323 |
| 322 | 324 |
| 323 char* VmStatusService::GetVmStatus(const char* request) { | 325 char* VmStatusService::GetVmStatus(const char* request) { |
| 324 VmStatusPlugin* plugin = instance_->registered_plugin_list_; | 326 VmStatusPlugin* plugin = instance_->registered_plugin_list_; |
| 325 while (plugin != NULL) { | 327 while (plugin != NULL) { |
| 326 char* result = (plugin->callback())(request); | 328 char* result = (plugin->callback())(request); |
| 327 if (result != NULL) { | 329 if (result != NULL) { |
| 328 return result; | 330 return result; |
| 329 } | 331 } |
| 330 plugin = plugin->next(); | 332 plugin = plugin->next(); |
| 331 } | 333 } |
| 332 return NULL; | 334 return NULL; |
| 333 } | 335 } |
| OLD | NEW |