PageRenderTime 24ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://gitlab.com/Blueprint-Marketing/hhvm
C++ | 309 lines | 255 code | 32 blank | 22 comment | 15 complexity | ecb22c57ecfef96603665eddbdd7feeb MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010-2014 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/server/server-stats.h"
  19. #include "hphp/runtime/ext/json/ext_json.h"
  20. #include "hphp/runtime/base/array-init.h"
  21. #include "hphp/runtime/base/builtin-functions.h"
  22. #include "hphp/runtime/base/runtime-option.h"
  23. #include "hphp/runtime/base/zend-url.h"
  24. #include "hphp/runtime/vm/jit/mc-generator.h"
  25. #include "hphp/runtime/vm/vm-regs.h"
  26. #include "hphp/system/constants.h"
  27. #include "hphp/util/hardware-counter.h"
  28. #include "hphp/util/lock.h"
  29. #include "hphp/util/logger.h"
  30. namespace HPHP {
  31. ///////////////////////////////////////////////////////////////////////////////
  32. const int64_t k_PHP_OUTPUT_HANDLER_CONT = 0;
  33. const int64_t k_PHP_OUTPUT_HANDLER_WRITE = 0;
  34. const int64_t k_PHP_OUTPUT_HANDLER_START = 1;
  35. const int64_t k_PHP_OUTPUT_HANDLER_CLEAN = 2;
  36. const int64_t k_PHP_OUTPUT_HANDLER_FLUSH = 4;
  37. const int64_t k_PHP_OUTPUT_HANDLER_END = 8;
  38. const int64_t k_PHP_OUTPUT_HANDLER_FINAL = 8;
  39. const int64_t k_PHP_OUTPUT_HANDLER_CLEANABLE = 16;
  40. const int64_t k_PHP_OUTPUT_HANDLER_FLUSHABLE = 32;
  41. const int64_t k_PHP_OUTPUT_HANDLER_REMOVABLE = 64;
  42. const int64_t k_PHP_OUTPUT_HANDLER_STDFLAGS =
  43. k_PHP_OUTPUT_HANDLER_CLEANABLE | k_PHP_OUTPUT_HANDLER_FLUSHABLE |
  44. k_PHP_OUTPUT_HANDLER_REMOVABLE;
  45. bool HHVM_FUNCTION(ob_start, const Variant& callback /* = null */,
  46. int chunk_size /* = 0 */,
  47. int flags /* = k_PHP_OUTPUT_HANDLER_STDFLAGS */) {
  48. // ignoring flags for now
  49. if (!callback.isNull()) {
  50. CallCtx ctx;
  51. vm_decode_function(callback, nullptr, false, ctx);
  52. if (!ctx.func) {
  53. return false;
  54. }
  55. }
  56. g_context->obStart(callback, chunk_size);
  57. return true;
  58. }
  59. void HHVM_FUNCTION(ob_clean) {
  60. // PHP_OUTPUT_HANDLER_START is included by PHP5
  61. g_context->obClean(k_PHP_OUTPUT_HANDLER_START | k_PHP_OUTPUT_HANDLER_CLEAN);
  62. }
  63. void HHVM_FUNCTION(ob_flush) {
  64. g_context->obFlush();
  65. }
  66. bool HHVM_FUNCTION(ob_end_clean) {
  67. g_context->obClean(k_PHP_OUTPUT_HANDLER_START |
  68. k_PHP_OUTPUT_HANDLER_CLEAN |
  69. k_PHP_OUTPUT_HANDLER_END);
  70. return g_context->obEnd();
  71. }
  72. bool HHVM_FUNCTION(ob_end_flush) {
  73. bool ret = g_context->obFlush();
  74. g_context->obEnd();
  75. return ret;
  76. }
  77. void HHVM_FUNCTION(flush) {
  78. g_context->flush();
  79. }
  80. Variant HHVM_FUNCTION(ob_get_contents) {
  81. if (HHVM_FN(ob_get_level)() == 0) {
  82. return false;
  83. }
  84. return g_context->obCopyContents();
  85. }
  86. Variant HHVM_FUNCTION(ob_get_clean) {
  87. String output = HHVM_FN(ob_get_contents)();
  88. if (!HHVM_FN(ob_end_clean)()) {
  89. return false;
  90. }
  91. return output;
  92. }
  93. Variant HHVM_FUNCTION(ob_get_flush) {
  94. String output = g_context->obCopyContents();
  95. if (!HHVM_FN(ob_end_flush)()) {
  96. return false;
  97. }
  98. return output;
  99. }
  100. int64_t HHVM_FUNCTION(ob_get_length) {
  101. return g_context->obGetContentLength();
  102. }
  103. int64_t HHVM_FUNCTION(ob_get_level) {
  104. return g_context->obGetLevel();
  105. }
  106. Array HHVM_FUNCTION(ob_get_status, bool full_status /* = false */) {
  107. return g_context->obGetStatus(full_status);
  108. }
  109. void HHVM_FUNCTION(ob_implicit_flush, bool flag /* = true */) {
  110. g_context->obSetImplicitFlush(flag);
  111. }
  112. Array HHVM_FUNCTION(ob_list_handlers) {
  113. return g_context->obGetHandlers();
  114. }
  115. bool HHVM_FUNCTION(output_add_rewrite_var, const String& name,
  116. const String& value) {
  117. throw_not_supported(__func__, "bad coding style");
  118. }
  119. bool HHVM_FUNCTION(output_reset_rewrite_vars) {
  120. throw_not_supported(__func__, "bad coding style");
  121. }
  122. void HHVM_FUNCTION(hphp_crash_log, const String& name, const String& value) {
  123. StackTraceNoHeap::AddExtraLogging(name.data(), value.data());
  124. }
  125. void HHVM_FUNCTION(hphp_stats, const String& name, int64_t value) {
  126. ServerStats::Log(name.data(), value);
  127. }
  128. int64_t HHVM_FUNCTION(hphp_get_stats, const String& name) {
  129. return ServerStats::Get(name.data());
  130. }
  131. Array HHVM_FUNCTION(hphp_get_status) {
  132. std::string out;
  133. ServerStats::ReportStatus(out, Writer::Format::JSON);
  134. return HHVM_FN(json_decode)(String(out)).toArray();
  135. }
  136. Array HHVM_FUNCTION(hphp_get_iostatus) {
  137. return ServerStats::GetThreadIOStatuses();
  138. }
  139. void HHVM_FUNCTION(hphp_set_iostatus_address, const String& name) {
  140. return ServerStats::SetThreadIOStatusAddress(name.c_str());
  141. }
  142. static double ts_float(const timespec &ts) {
  143. return (double)ts.tv_sec + (double)ts.tv_nsec / 1000000000;
  144. }
  145. static String ts_microtime(const timespec &ts) {
  146. char ret[100];
  147. snprintf(ret, 100, "%.8F %ld", (double)ts.tv_nsec / 1000000000, ts.tv_sec);
  148. return String(ret, CopyString);
  149. }
  150. const StaticString
  151. s_queue("queue"),
  152. s_process_wall("process-wall"),
  153. s_process_cpu("process-cpu"),
  154. s_process_inst("process-inst");
  155. const StaticString
  156. s_process_sleep_time("process-sleep-time"),
  157. s_process_usleep_time("process-usleep-time"),
  158. s_process_nsleep_time("process-nanosleep-time");
  159. Variant HHVM_FUNCTION(hphp_get_timers, bool get_as_float /* = true */) {
  160. Transport *transport = g_context->getTransport();
  161. if (transport == NULL) {
  162. return false;
  163. }
  164. const timespec &tsQueue = transport->getQueueTime();
  165. const timespec &tsWall = transport->getWallTime();
  166. const timespec &tsCpu = transport->getCpuTime();
  167. const int64_t &instStart = transport->getInstructions();
  168. const int64_t &usleep_time = transport->getuSleepTime();
  169. const int64_t &sleep_time = transport->getSleepTime();
  170. const int64_t &nsleep_time_s = transport->getnSleepTimeS();
  171. const int32_t &nsleep_time_n = transport->getnSleepTimeN();
  172. ArrayInit ret(7, ArrayInit::Map{});
  173. if (get_as_float) {
  174. ret.set(s_queue, ts_float(tsQueue));
  175. ret.set(s_process_wall, ts_float(tsWall));
  176. ret.set(s_process_cpu, ts_float(tsCpu));
  177. } else {
  178. ret.set(s_queue, ts_microtime(tsQueue));
  179. ret.set(s_process_wall, ts_microtime(tsWall));
  180. ret.set(s_process_cpu, ts_microtime(tsCpu));
  181. }
  182. ret.set(s_process_inst, instStart);
  183. ret.set(s_process_sleep_time, sleep_time);
  184. ret.set(s_process_usleep_time, (double)usleep_time/1000000);
  185. ret.set(s_process_nsleep_time, nsleep_time_s +
  186. (double)nsleep_time_n / 1000000000);
  187. return ret.toVariant();
  188. }
  189. Variant HHVM_FUNCTION(hphp_output_global_state, bool serialize /* = true */) {
  190. Array r = Array();
  191. if (serialize) {
  192. return f_serialize(r);
  193. } else {
  194. return r;
  195. }
  196. }
  197. int64_t HHVM_FUNCTION(hphp_instruction_counter) {
  198. return HardwareCounter::GetInstructionCount();
  199. }
  200. Variant HHVM_FUNCTION(hphp_get_hardware_counters) {
  201. Array ret;
  202. HardwareCounter::GetPerfEvents(
  203. [](const std::string& key, int64_t value, void* data) {
  204. Array& ret = *reinterpret_cast<Array*>(data);
  205. ret.set(String(key), value);
  206. },
  207. &ret);
  208. jit::mcg->getPerfCounters(ret);
  209. return ret;
  210. }
  211. bool HHVM_FUNCTION(hphp_set_hardware_events,
  212. const Variant& events /* = null */) {
  213. String ev = events.toString();
  214. ev = url_decode(ev.data(), ev.size());
  215. return HardwareCounter::SetPerfEvents(ev.slice());
  216. }
  217. void HHVM_FUNCTION(hphp_clear_hardware_events) {
  218. HardwareCounter::ClearPerfEvents();
  219. }
  220. // __SystemLib\print_hashbang
  221. void HHVM_FUNCTION(SystemLib_print_hashbang, const String& hashbang) {
  222. CallerFrame cf;
  223. auto ar = cf();
  224. if (ar->m_func->name()->empty() && RuntimeOption::ClientExecutionMode()) {
  225. // If run in cli mode, print nothing in the lowest pseudomain
  226. if (!g_context->getPrevFunc(ar)) return;
  227. }
  228. g_context->write(hashbang);
  229. }
  230. ///////////////////////////////////////////////////////////////////////////////
  231. void StandardExtension::initOutput() {
  232. HHVM_FE(ob_start);
  233. HHVM_FE(ob_clean);
  234. HHVM_FE(ob_flush);
  235. HHVM_FE(ob_end_clean);
  236. HHVM_FE(ob_end_flush);
  237. HHVM_FE(flush);
  238. HHVM_FE(ob_get_contents);
  239. HHVM_FE(ob_get_clean);
  240. HHVM_FE(ob_get_flush);
  241. HHVM_FE(ob_get_length);
  242. HHVM_FE(ob_get_level);
  243. HHVM_FE(ob_get_status);
  244. HHVM_FE(ob_implicit_flush);
  245. HHVM_FE(ob_list_handlers);
  246. HHVM_FE(output_add_rewrite_var);
  247. HHVM_FE(output_reset_rewrite_vars);
  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_FALIAS(__SystemLib\\print_hashbang, SystemLib_print_hashbang);
  261. #define INTCONST(v) Native::registerConstant<KindOfInt64> \
  262. (makeStaticString(#v), k_##v);
  263. INTCONST(PHP_OUTPUT_HANDLER_CONT);
  264. INTCONST(PHP_OUTPUT_HANDLER_WRITE);
  265. INTCONST(PHP_OUTPUT_HANDLER_START);
  266. INTCONST(PHP_OUTPUT_HANDLER_CLEAN);
  267. INTCONST(PHP_OUTPUT_HANDLER_FLUSH);
  268. INTCONST(PHP_OUTPUT_HANDLER_END);
  269. INTCONST(PHP_OUTPUT_HANDLER_FINAL);
  270. INTCONST(PHP_OUTPUT_HANDLER_CLEANABLE);
  271. INTCONST(PHP_OUTPUT_HANDLER_FLUSHABLE);
  272. INTCONST(PHP_OUTPUT_HANDLER_REMOVABLE);
  273. INTCONST(PHP_OUTPUT_HANDLER_STDFLAGS);
  274. #undef INTCONST
  275. loadSystemlib("std_output");
  276. }
  277. }