PageRenderTime 53ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/hphp/runtime/ext/std/ext_std_output.cpp

https://github.com/soitun/hiphop-php
C++ | 303 lines | 253 code | 30 blank | 20 comment | 18 complexity | fc5cd68d5f575f3e894a5bd895eab0bb MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
  6. | Copyright (c) 1997-2010 The PHP Group |
  7. +----------------------------------------------------------------------+
  8. | This source file is subject to version 3.01 of the PHP license, |
  9. | that is bundled with this package in the file LICENSE, and is |
  10. | available through the world-wide-web at the following url: |
  11. | http://www.php.net/license/3_01.txt |
  12. | If you did not receive a copy of the PHP license and are unable to |
  13. | obtain it through the world-wide-web, please send a note to |
  14. | license@php.net so we can mail you a copy immediately. |
  15. +----------------------------------------------------------------------+
  16. */
  17. #include "hphp/runtime/ext/std/ext_std_output.h"
  18. #include "hphp/runtime/base/array-init.h"
  19. #include "hphp/runtime/base/builtin-functions.h"
  20. #include "hphp/runtime/base/runtime-option.h"
  21. #include "hphp/runtime/base/zend-url.h"
  22. #include "hphp/runtime/vm/vm-regs.h"
  23. #include "hphp/runtime/vm/jit/perf-counters.h"
  24. #include "hphp/runtime/ext/json/ext_json.h"
  25. #include "hphp/runtime/server/cli-server.h"
  26. #include "hphp/runtime/server/server-stats.h"
  27. #include "hphp/util/hardware-counter.h"
  28. #include "hphp/util/lock.h"
  29. #include "hphp/util/logger.h"
  30. #include "hphp/util/stack-trace.h"
  31. namespace HPHP {
  32. ///////////////////////////////////////////////////////////////////////////////
  33. const int64_t k_PHP_OUTPUT_HANDLER_CONT = 0;
  34. const int64_t k_PHP_OUTPUT_HANDLER_WRITE = 0;
  35. const int64_t k_PHP_OUTPUT_HANDLER_START = 1;
  36. const int64_t k_PHP_OUTPUT_HANDLER_CLEAN = 2;
  37. const int64_t k_PHP_OUTPUT_HANDLER_FLUSH = 4;
  38. const int64_t k_PHP_OUTPUT_HANDLER_END = 8;
  39. const int64_t k_PHP_OUTPUT_HANDLER_FINAL = 8;
  40. const int64_t k_PHP_OUTPUT_HANDLER_CLEANABLE = 16;
  41. const int64_t k_PHP_OUTPUT_HANDLER_FLUSHABLE = 32;
  42. const int64_t k_PHP_OUTPUT_HANDLER_REMOVABLE = 64;
  43. const int64_t k_PHP_OUTPUT_HANDLER_STDFLAGS =
  44. k_PHP_OUTPUT_HANDLER_CLEANABLE | k_PHP_OUTPUT_HANDLER_FLUSHABLE |
  45. k_PHP_OUTPUT_HANDLER_REMOVABLE;
  46. bool HHVM_FUNCTION(ob_start, const Variant& callback /* = null */,
  47. int64_t chunk_size /* = 0 */,
  48. int64_t flags /* = k_PHP_OUTPUT_HANDLER_STDFLAGS */) {
  49. // Note: the only flag which is implemented is FLUSHABLE
  50. if (!callback.isNull()) {
  51. CallCtx ctx;
  52. vm_decode_function(callback, ctx);
  53. if (!ctx.func) {
  54. return false;
  55. }
  56. }
  57. OBFlags f = OBFlags::None;
  58. if (flags & k_PHP_OUTPUT_HANDLER_CLEANABLE) f |= OBFlags::Cleanable;
  59. if (flags & k_PHP_OUTPUT_HANDLER_FLUSHABLE) f |= OBFlags::Flushable;
  60. if (flags & k_PHP_OUTPUT_HANDLER_REMOVABLE) f |= OBFlags::Removable;
  61. g_context->obStart(callback, chunk_size, f);
  62. return true;
  63. }
  64. void HHVM_FUNCTION(ob_clean) {
  65. // PHP_OUTPUT_HANDLER_START is included by PHP5
  66. g_context->obClean(k_PHP_OUTPUT_HANDLER_START | k_PHP_OUTPUT_HANDLER_CLEAN);
  67. }
  68. bool HHVM_FUNCTION(ob_flush) {
  69. int level = g_context->obGetLevel();
  70. if (level == 0) {
  71. raise_notice("failed to flush buffer. No buffer to flush");
  72. return false;
  73. }
  74. if (!g_context->obFlush()) {
  75. raise_notice("failed to flush buffer of %s (%d)",
  76. g_context->obGetBufferName().c_str(), level);
  77. return false;
  78. }
  79. return true;
  80. }
  81. bool HHVM_FUNCTION(ob_end_clean) {
  82. g_context->obClean(k_PHP_OUTPUT_HANDLER_START |
  83. k_PHP_OUTPUT_HANDLER_CLEAN |
  84. k_PHP_OUTPUT_HANDLER_END);
  85. return g_context->obEnd();
  86. }
  87. bool HHVM_FUNCTION(ob_end_flush) {
  88. bool ret = g_context->obFlush(true);
  89. g_context->obEnd();
  90. return ret;
  91. }
  92. void HHVM_FUNCTION(flush) {
  93. g_context->flush();
  94. }
  95. Variant HHVM_FUNCTION(ob_get_contents) {
  96. if (HHVM_FN(ob_get_level)() == 0) {
  97. return false;
  98. }
  99. return g_context->obCopyContents();
  100. }
  101. Variant HHVM_FUNCTION(ob_get_clean) {
  102. auto output = HHVM_FN(ob_get_contents)();
  103. if (!HHVM_FN(ob_end_clean)()) {
  104. return false;
  105. }
  106. return output;
  107. }
  108. Variant HHVM_FUNCTION(ob_get_flush) {
  109. String output = g_context->obCopyContents();
  110. if (!HHVM_FN(ob_end_flush)()) {
  111. return false;
  112. }
  113. return output;
  114. }
  115. int64_t HHVM_FUNCTION(ob_get_length) {
  116. return g_context->obGetContentLength();
  117. }
  118. int64_t HHVM_FUNCTION(ob_get_level) {
  119. return g_context->obGetLevel();
  120. }
  121. Variant HHVM_FUNCTION(ob_get_status, bool full_status /* = false */) {
  122. return g_context->obGetStatus(full_status);
  123. }
  124. void HHVM_FUNCTION(ob_implicit_flush, bool flag /* = true */) {
  125. g_context->obSetImplicitFlush(flag);
  126. }
  127. Array HHVM_FUNCTION(ob_list_handlers) {
  128. return g_context->obGetHandlers();
  129. }
  130. void HHVM_FUNCTION(hphp_crash_log, const String& name, const String& value) {
  131. StackTraceNoHeap::AddExtraLogging(name.data(), value.data());
  132. }
  133. void HHVM_FUNCTION(hphp_stats, const String& name, int64_t value) {
  134. ServerStats::Log(name.data(), value);
  135. }
  136. int64_t HHVM_FUNCTION(hphp_get_stats, const String& name) {
  137. return ServerStats::Get(name.data());
  138. }
  139. Array HHVM_FUNCTION(hphp_get_status) {
  140. auto const out = ServerStats::ReportStatus(Writer::Format::JSON);
  141. auto result = HHVM_FN(json_decode)(
  142. String(out),
  143. false,
  144. 512,
  145. HPHP::k_JSON_FB_DARRAYS_AND_VARRAYS);
  146. return Variant::attach(result).toArray().toDict();
  147. }
  148. Array HHVM_FUNCTION(hphp_get_iostatus) {
  149. return ServerStats::GetThreadIOStatuses();
  150. }
  151. void HHVM_FUNCTION(hphp_set_iostatus_address, const String& name) {
  152. }
  153. static double ts_float(const timespec &ts) {
  154. return (double)ts.tv_sec + (double)ts.tv_nsec / 1000000000;
  155. }
  156. static String ts_microtime(const timespec &ts) {
  157. char ret[100];
  158. snprintf(ret, 100, "%.8F %ld", (double)ts.tv_nsec / 1000000000, ts.tv_sec);
  159. return String(ret, CopyString);
  160. }
  161. const StaticString
  162. s_queue("queue"),
  163. s_process_wall("process-wall"),
  164. s_process_cpu("process-cpu"),
  165. s_process_inst("process-inst");
  166. const StaticString
  167. s_process_sleep_time("process-sleep-time"),
  168. s_process_usleep_time("process-usleep-time"),
  169. s_process_nsleep_time("process-nanosleep-time");
  170. Variant HHVM_FUNCTION(hphp_get_timers, bool get_as_float /* = true */) {
  171. Transport *transport = g_context->getTransport();
  172. if (transport == NULL) {
  173. return false;
  174. }
  175. const timespec &tsQueue = transport->getQueueTime();
  176. const timespec &tsWall = transport->getWallTime();
  177. const timespec &tsCpu = transport->getCpuTime();
  178. const int64_t &instStart = transport->getInstructions();
  179. const int64_t &usleep_time = transport->getuSleepTime();
  180. const int64_t &sleep_time = transport->getSleepTime();
  181. const int64_t &nsleep_time_s = transport->getnSleepTimeS();
  182. const int32_t &nsleep_time_n = transport->getnSleepTimeN();
  183. DictInit ret(7);
  184. if (get_as_float) {
  185. ret.set(s_queue, ts_float(tsQueue));
  186. ret.set(s_process_wall, ts_float(tsWall));
  187. ret.set(s_process_cpu, ts_float(tsCpu));
  188. } else {
  189. ret.set(s_queue, ts_microtime(tsQueue));
  190. ret.set(s_process_wall, ts_microtime(tsWall));
  191. ret.set(s_process_cpu, ts_microtime(tsCpu));
  192. }
  193. ret.set(s_process_inst, instStart);
  194. ret.set(s_process_sleep_time, sleep_time);
  195. ret.set(s_process_usleep_time, (double)usleep_time/1000000);
  196. ret.set(s_process_nsleep_time, nsleep_time_s +
  197. (double)nsleep_time_n / 1000000000);
  198. return ret.toVariant();
  199. }
  200. Variant HHVM_FUNCTION(hphp_output_global_state, bool serialize /* = true */) {
  201. Array r = Array();
  202. if (serialize) {
  203. return f_serialize(r);
  204. } else {
  205. return r;
  206. }
  207. }
  208. int64_t HHVM_FUNCTION(hphp_instruction_counter) {
  209. return HardwareCounter::GetInstructionCount();
  210. }
  211. Variant HHVM_FUNCTION(hphp_get_hardware_counters) {
  212. Array ret = Array::CreateDict();
  213. HardwareCounter::GetPerfEvents(
  214. [] (const std::string& key, int64_t value, void* data) {
  215. Array& ret = *reinterpret_cast<Array*>(data);
  216. ret.set(String(key), value);
  217. },
  218. &ret
  219. );
  220. jit::getPerfCounters(ret);
  221. return ret.empty() ? init_null() : ret;
  222. }
  223. bool HHVM_FUNCTION(hphp_set_hardware_events,
  224. const Variant& events /* = null */) {
  225. auto ev = events.toString();
  226. ev = url_decode(ev.data(), ev.size());
  227. return HardwareCounter::SetPerfEvents(ev.slice());
  228. }
  229. void HHVM_FUNCTION(hphp_clear_hardware_events) {
  230. HardwareCounter::ClearPerfEvents();
  231. }
  232. ///////////////////////////////////////////////////////////////////////////////
  233. void StandardExtension::initOutput() {
  234. HHVM_FE(ob_start);
  235. HHVM_FE(ob_clean);
  236. HHVM_FE(ob_flush);
  237. HHVM_FE(ob_end_clean);
  238. HHVM_FE(ob_end_flush);
  239. HHVM_FE(flush);
  240. HHVM_FE(ob_get_contents);
  241. HHVM_FE(ob_get_clean);
  242. HHVM_FE(ob_get_flush);
  243. HHVM_FE(ob_get_length);
  244. HHVM_FE(ob_get_level);
  245. HHVM_FE(ob_get_status);
  246. HHVM_FE(ob_implicit_flush);
  247. HHVM_FE(ob_list_handlers);
  248. HHVM_FE(hphp_crash_log);
  249. HHVM_FE(hphp_stats);
  250. HHVM_FE(hphp_get_stats);
  251. HHVM_FE(hphp_get_status);
  252. HHVM_FE(hphp_get_iostatus);
  253. HHVM_FE(hphp_set_iostatus_address);
  254. HHVM_FE(hphp_get_timers);
  255. HHVM_FE(hphp_output_global_state);
  256. HHVM_FE(hphp_instruction_counter);
  257. HHVM_FE(hphp_get_hardware_counters);
  258. HHVM_FE(hphp_set_hardware_events);
  259. HHVM_FE(hphp_clear_hardware_events);
  260. HHVM_RC_INT(PHP_OUTPUT_HANDLER_CONT, k_PHP_OUTPUT_HANDLER_CONT);
  261. HHVM_RC_INT(PHP_OUTPUT_HANDLER_WRITE, k_PHP_OUTPUT_HANDLER_WRITE);
  262. HHVM_RC_INT(PHP_OUTPUT_HANDLER_START, k_PHP_OUTPUT_HANDLER_START);
  263. HHVM_RC_INT(PHP_OUTPUT_HANDLER_CLEAN, k_PHP_OUTPUT_HANDLER_CLEAN);
  264. HHVM_RC_INT(PHP_OUTPUT_HANDLER_FLUSH, k_PHP_OUTPUT_HANDLER_FLUSH);
  265. HHVM_RC_INT(PHP_OUTPUT_HANDLER_END, k_PHP_OUTPUT_HANDLER_END);
  266. HHVM_RC_INT(PHP_OUTPUT_HANDLER_FINAL, k_PHP_OUTPUT_HANDLER_FINAL);
  267. HHVM_RC_INT(PHP_OUTPUT_HANDLER_CLEANABLE, k_PHP_OUTPUT_HANDLER_CLEANABLE);
  268. HHVM_RC_INT(PHP_OUTPUT_HANDLER_FLUSHABLE, k_PHP_OUTPUT_HANDLER_FLUSHABLE);
  269. HHVM_RC_INT(PHP_OUTPUT_HANDLER_REMOVABLE, k_PHP_OUTPUT_HANDLER_REMOVABLE);
  270. HHVM_RC_INT(PHP_OUTPUT_HANDLER_STDFLAGS, k_PHP_OUTPUT_HANDLER_STDFLAGS);
  271. loadSystemlib("std_output");
  272. }
  273. }