diff --git a/CMakeLists.txt b/CMakeLists.txt index e07a035..d5e6118 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,10 +13,13 @@ add_definitions(-D__NO_MATH_INLINES) link_directories(${NODE_ROOT}/lib) include_directories(${NODE_ROOT}/include/node) +include_directories(${NODE_ROOT}/src) +include_directories(${NODE_ROOT}/deps/v8/include) include_directories( "${CMAKE_CURRENT_SOURCE_DIR}" ${PROJECT_SOURCE_DIR}/nwrfcsdk/include + ${PROJECT_SOURCE_DIR}/node_modules/nan ) link_directories( @@ -25,7 +28,10 @@ link_directories( set(Sources src/binding.cc +src/current_function.hpp src/Common.h +src/Loggable.h +src/Loggable.cc src/Connection.h src/Connection.cc src/Function.h diff --git a/binding.gyp b/binding.gyp index 0572604..09b2ffc 100644 --- a/binding.gyp +++ b/binding.gyp @@ -9,7 +9,10 @@ 'targets': [{ 'sources': [ 'src/binding.cc', + 'src/current_function.hpp', 'src/Common.h', + 'src/Loggable.h', + 'src/Loggable.cc', 'src/Connection.h', 'src/Connection.cc', 'src/Function.h', @@ -44,6 +47,7 @@ '_CRT_NON_CONFORMING_SWPRINTFS', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE', + 'NOMINMAX', 'SAPonNT', 'UNICODE', '_UNICODE' diff --git a/package.json b/package.json index f9f6f81..c4ddd32 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ }, "dependencies": { "bindings": ">=0.3.0", - "nan": "^2.1.0" + "nan": "^2.2.0" }, "devDependencies": { "gulp": "^3.9.0", diff --git a/sapnwrfc.js b/sapnwrfc.js index 46d5887..2de166e 100644 --- a/sapnwrfc.js +++ b/sapnwrfc.js @@ -1,2 +1,25 @@ var majMinVersion = process.versions.node.match(/^[0-9]+.[0-9]+/)[0] || ''; -module.exports = require('bindings')({ bindings: 'sapnwrfc', version: majMinVersion }); \ No newline at end of file +var sapnwrfc = require('bindings')({bindings: 'sapnwrfc', version: majMinVersion}); + +var _logger; + +sapnwrfc.configure = function(options) { + if(options) { + _logger = options.logger; + } +} + +function _log(level, message, meta) { + if(_logger) { + if(meta) { + _logger.log(level, message, meta); + } else { + _logger.log(level, message); + } + } +}; + +sapnwrfc.Connection.prototype._log = _log; +sapnwrfc.Function.prototype._log = _log; + +module.exports = sapnwrfc; diff --git a/src/Connection.cc b/src/Connection.cc index 0b79dd9..5e8c32d 100644 --- a/src/Connection.cc +++ b/src/Connection.cc @@ -60,6 +60,8 @@ NAN_METHOD(Connection::New) Connection *self = new Connection(); self->Wrap(info.This()); + self->log(Levels::SILLY, "Connection object created"); + info.GetReturnValue().Set(info.This()); } @@ -103,6 +105,8 @@ NAN_METHOD(Connection::Open) { Connection *self = node::ObjectWrap::Unwrap(info.This()); + self->log(Levels::VERBOSE, "opening new SAP connection"); + if (info.Length() < 2) { Nan::ThrowError("Function expects 2 arguments"); return; @@ -124,6 +128,8 @@ NAN_METHOD(Connection::Open) memset(self->loginParams, 0, self->loginParamsSize * sizeof(RFC_CONNECTION_PARAMETER)); memset(&self->errorInfo, 0, sizeof(RFC_ERROR_INFO)); + self->log(Levels::DBG, "Connection params", optionsObj); + for (unsigned int i = 0; i < self->loginParamsSize; i++) { v8::Local name = props->Get(i); v8::Local value = optionsObj->Get(name->ToString()); @@ -153,12 +159,12 @@ void Connection::EIO_Open(uv_work_t *req) Connection *self = static_cast(req->data); self->connectionHandle = RfcOpenConnection(self->loginParams, self->loginParamsSize, &self->errorInfo); + DEFER_LOG_API(self, "RfcOpenConnection"); } void Connection::EIO_AfterOpen(uv_work_t *req) { Nan::HandleScope scope; - RFC_ERROR_INFO errorInfo; int isValid; Connection *self = static_cast(req->data); @@ -166,23 +172,31 @@ void Connection::EIO_AfterOpen(uv_work_t *req) argv[0] = Nan::Null(); if (self->connectionHandle == nullptr) { + self->log(Levels::DBG, "Connection handle is NULL, connection failed"); argv[0] = RfcError(self->errorInfo); } else { - RfcIsConnectionHandleValid(self->connectionHandle, &isValid, &errorInfo); + RfcIsConnectionHandleValid(self->connectionHandle, &isValid, &self->errorInfo); + LOG_API(self, "RfcIsConnectionHandleValid"); if (!isValid) { - argv[0] = RfcError(errorInfo); + self->log(Levels::SILLY, "Connection not valid"); + argv[0] = RfcError(self->errorInfo); + } else { + self->log(Levels::SILLY, "Connection still valid"); } } Nan::TryCatch try_catch; + self->log(Levels::SILLY, "EIO_AfterOpen: About to call the callback"); assert(!self->cbOpen->IsEmpty()); self->cbOpen->Call(1, argv); delete self->cbOpen; self->cbOpen = nullptr; self->Unref(); + self->log(Levels::SILLY, "EIO_AfterOpen: Finished callback"); if (try_catch.HasCaught()) { + self->log(Levels::ERR, "EIO_AfterOpen: Exception thrown in callback. Abort."); Nan::FatalException(try_catch); } } @@ -190,6 +204,7 @@ void Connection::EIO_AfterOpen(uv_work_t *req) NAN_METHOD(Connection::Close) { Connection *self = node::ObjectWrap::Unwrap(info.This()); + self->log(Levels::SILLY, "Connection::Close"); info.GetReturnValue().Set(self->CloseConnection()); } @@ -197,11 +212,14 @@ v8::Local Connection::CloseConnection(void) { Nan::EscapableHandleScope scope; RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; + + log(Levels::SILLY, "Connection::CloseConnection"); if (this->connectionHandle != nullptr) { rc = RfcCloseConnection(this->connectionHandle, &errorInfo); + LOG_API(this, "RfcCloseConnection"); if (rc != RFC_OK) { + log(Levels::DBG, "Connection::CloseConnection: Error closing connection"); scope.Escape(RfcError(errorInfo)); } } @@ -228,11 +246,20 @@ NAN_METHOD(Connection::IsOpen) { Connection *self = node::ObjectWrap::Unwrap(info.This()); RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; int isValid; - rc = RfcIsConnectionHandleValid(self->connectionHandle, &isValid, &errorInfo); - info.GetReturnValue().Set(isValid ? Nan::True() : Nan::False()); + self->log(Levels::SILLY, "Connection::IsOpen"); + + rc = RfcIsConnectionHandleValid(self->connectionHandle, &isValid, &self->errorInfo); + LOG_API(self, "RfcIsConnectionHandleValid"); + if(!isValid) { + self->log(Levels::SILLY, "Connection::IsOpen: RfcIsConnectionHandleValid returned false"); + info.GetReturnValue().Set(Nan::False()); + } else { + self->log(Levels::SILLY, "Connection::IsOpen: RfcIsConnectionHandleValid returned true"); + info.GetReturnValue().Set(Nan::True()); + } + } /** @@ -243,16 +270,18 @@ NAN_METHOD(Connection::Ping) { Connection *self = node::ObjectWrap::Unwrap(info.This()); RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; + + self->log(Levels::SILLY, "Connection::IsOpen"); if (info.Length() > 0) { Nan::ThrowError("No arguments expected"); return; } - rc = RfcPing(self->connectionHandle, &errorInfo); + rc = RfcPing(self->connectionHandle, &self->errorInfo); + LOG_API(self, "RfcPing"); if (rc != RFC_OK) { - RETURN_RFC_ERROR(errorInfo); + RETURN_RFC_ERROR(self->errorInfo); } info.GetReturnValue().Set(Nan::True()); @@ -264,12 +293,12 @@ NAN_METHOD(Connection::Ping) */ NAN_METHOD(Connection::Lookup) { - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; int isValid; Connection *self = node::ObjectWrap::Unwrap(info.This()); + self->log(Levels::SILLY, "Connection::Lookup"); + if (info.Length() != 1) { Nan::ThrowError("Function expects 1 argument"); return; @@ -279,13 +308,21 @@ NAN_METHOD(Connection::Lookup) return; } - rc = RfcIsConnectionHandleValid(self->connectionHandle, &isValid, &errorInfo); + RfcIsConnectionHandleValid(self->connectionHandle, &isValid, &self->errorInfo); + LOG_API(self, "RfcIsConnectionHandleValid"); if (!isValid) { - Nan::ThrowError(RfcError(errorInfo)); + self->log(Levels::SILLY, "Connection::Lookup: RfcIsConnectionHandleValid returned false"); + Nan::ThrowError(RfcError(self->errorInfo)); return; + } else { + self->log(Levels::SILLY, "Connection::Lookup: RfcIsConnectionHandleValid returned true"); } + self->log(Levels::SILLY, "Connection::Lookup: About to create function instance"); v8::Local f = Function::NewInstance(*self, info); + if( IsException(f)) { + self->log(Levels::DBG, "Connection::Lookup: Unable to create function instance"); + } info.GetReturnValue().Set(f); } @@ -295,11 +332,10 @@ NAN_METHOD(Connection::Lookup) */ NAN_METHOD(Connection::SetIniPath) { - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; - Connection *self = node::ObjectWrap::Unwrap(info.This()); + self->log(Levels::SILLY, "Connection::SetIniPath"); + if (info.Length() != 1) { Nan::ThrowError("Function expects 1 argument"); return; @@ -311,9 +347,11 @@ NAN_METHOD(Connection::SetIniPath) v8::Local iniPath = info[0]->ToString(); - rc = RfcSetIniPath(convertToSAPUC(iniPath), &errorInfo); - if (rc) { - Nan::ThrowError(RfcError(errorInfo)); + RfcSetIniPath(convertToSAPUC(iniPath), &self->errorInfo); + LOG_API(self, "RfcSetIniPath"); + if (self->errorInfo.code) { + self->log(Levels::DBG, "Connection::SetIniPath: RfcSetIniPath failed"); + Nan::ThrowError(RfcError(self->errorInfo)); return; } diff --git a/src/Connection.h b/src/Connection.h index 436a3e1..e97662f 100644 --- a/src/Connection.h +++ b/src/Connection.h @@ -25,15 +25,12 @@ SOFTWARE. #ifndef CONNECTION_H_ #define CONNECTION_H_ -#include "Common.h" -#include -#include -#include +#include "Loggable.h" #include #include #include -class Connection : public node::ObjectWrap +class Connection : public Loggable { friend class Function; diff --git a/src/Function.cc b/src/Function.cc index 5b04562..51e1197 100644 --- a/src/Function.cc +++ b/src/Function.cc @@ -25,7 +25,8 @@ SOFTWARE. #include "Function.h" #include #include -#include +#include +#include Nan::Persistent Function::ctor; @@ -47,47 +48,49 @@ NAN_MODULE_INIT(Function::Init) Nan::SetPrototypeMethod(ctorTemplate, "MetaData", MetaData); ctor.Reset(ctorTemplate->GetFunction()); + Nan::Set(target, Nan::New("Function").ToLocalChecked(), ctorTemplate->GetFunction()); } v8::Local Function::NewInstance(Connection &connection, const Nan::NAN_METHOD_ARGS_TYPE args) { Nan::EscapableHandleScope scope; unsigned int parmCount; - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; v8::Local func = Nan::New(ctor)->NewInstance(); Function *self = node::ObjectWrap::Unwrap(func); + self->log(Levels::SILLY, "Function::NewInstance"); + // Save connection assert(self != nullptr); self->connection = &connection; // Lookup function interface v8::String::Value functionName(args[0]); - self->functionDescHandle = RfcGetFunctionDesc(connection.GetConnectionHandle(), (const SAP_UC*)*functionName, &errorInfo); -#ifndef NDEBUG - if (errorInfo.code == RFC_INVALID_HANDLE) { - assert(0); - } -#endif + self->functionDescHandle = RfcGetFunctionDesc(connection.GetConnectionHandle(), (const SAP_UC*)*functionName, &self->errorInfo); + LOG_API(self, "RfcGetFunctionDesc"); + assert(self->errorInfo.code != RFC_INVALID_HANDLE); if (self->functionDescHandle == nullptr) { - return scope.Escape(RfcError(errorInfo)); + self->log(Levels::DBG, "Function::NewInstance: Function description handle is NULL."); + return scope.Escape(RfcError(self->errorInfo)); } - rc = RfcGetParameterCount(self->functionDescHandle, &parmCount, &errorInfo); - if (rc != RFC_OK) { - return scope.Escape(RfcError(errorInfo)); + RfcGetParameterCount(self->functionDescHandle, &parmCount, &self->errorInfo); + LOG_API(self, "RfcGetParameterCount"); + if (self->errorInfo.code != RFC_OK) { + self->log(Levels::DBG, "Function::NewInstance: RfcGetParameterCount unsuccessful"); + return scope.Escape(RfcError(self->errorInfo)); } // Dynamically add parameters to JS object for (unsigned int i = 0; i < parmCount; i++) { RFC_PARAMETER_DESC parmDesc; - rc = RfcGetParameterDescByIndex(self->functionDescHandle, i, &parmDesc, &errorInfo); - if (rc != RFC_OK) { - return scope.Escape(RfcError(errorInfo)); + RfcGetParameterDescByIndex(self->functionDescHandle, i, &parmDesc, &self->errorInfo); + if (self->errorInfo.code != RFC_OK) { + self->log(Levels::DBG, "Function::NewInstance: RfcGetParameterDescByIndex unsuccessful"); + return scope.Escape(RfcError(self->errorInfo)); } func->Set(Nan::New((const uint16_t*)(parmDesc.name)).ToLocalChecked(), Nan::Null()); } @@ -104,6 +107,7 @@ NAN_METHOD(Function::New) Function *self = new Function(); self->Wrap(info.This()); + self->log(Levels::SILLY, "Function::New: Function instance constructed"); info.GetReturnValue().Set(info.This()); } @@ -111,12 +115,11 @@ NAN_METHOD(Function::New) NAN_METHOD(Function::Invoke) { - RFC_RC rc = RFC_OK; unsigned int parmCount; - RFC_ERROR_INFO errorInfo; Function *self = node::ObjectWrap::Unwrap(info.This()); assert(self != nullptr); + self->log(Levels::SILLY, "Function::Invoke"); if (info.Length() < 1) { Nan::ThrowError("Function expects 2 arguments"); @@ -139,16 +142,20 @@ NAN_METHOD(Function::Invoke) // Store callback baton->cbInvoke = new Nan::Callback(info[1].As()); - baton->functionHandle = RfcCreateFunction(self->functionDescHandle, &errorInfo); + baton->functionHandle = RfcCreateFunction(self->functionDescHandle, &self->errorInfo); + LOG_API(self, "RfcCreateFunction"); if (baton->functionHandle == nullptr) { delete baton; - RETURN_RFC_ERROR(errorInfo); + self->log(Levels::DBG, "Function::Invoke: RfcCreateFunction finished with error"); + RETURN_RFC_ERROR(self->errorInfo); } - rc = RfcGetParameterCount(self->functionDescHandle, &parmCount, &errorInfo); - if (rc != RFC_OK) { + RfcGetParameterCount(self->functionDescHandle, &parmCount, &self->errorInfo); + LOG_API(self, "RfcGetParameterCount"); + if (self->errorInfo.code != RFC_OK) { delete baton; - RETURN_RFC_ERROR(errorInfo); + self->log(Levels::DBG, "Function::Invoke: RfcGetParameterCount returned with error"); + RETURN_RFC_ERROR(self->errorInfo); } v8::Local inputParm = info[0]->ToObject(); @@ -156,10 +163,12 @@ NAN_METHOD(Function::Invoke) for (unsigned int i = 0; i < parmCount; i++) { RFC_PARAMETER_DESC parmDesc; - rc = RfcGetParameterDescByIndex(self->functionDescHandle, i, &parmDesc, &errorInfo); - if (rc != RFC_OK) { + RfcGetParameterDescByIndex(self->functionDescHandle, i, &parmDesc, &self->errorInfo); + LOG_API(self, "RfcGetParameterDescByIndex"); + if (self->errorInfo.code != RFC_OK) { delete baton; - RETURN_RFC_ERROR(errorInfo); + self->log(Levels::DBG, "Function::Invoke: RfcGetParameterDescByIndex finished with error"); + RETURN_RFC_ERROR(self->errorInfo); } v8::Local parmName = Nan::New((const uint16_t*)(parmDesc.name)).ToLocalChecked(); @@ -183,9 +192,11 @@ NAN_METHOD(Function::Invoke) argv[1] = Nan::Null(); Nan::TryCatch try_catch; + self->log(Levels::SILLY, "Function::Invoke: About call callback with error."); baton->cbInvoke->Call(Nan::GetCurrentContext()->Global(), 2, argv); delete baton; if (try_catch.HasCaught()) { + self->log(Levels::ERR, "Function::Invoke: Callback has thrown. Aborting."); Nan::FatalException(try_catch); } info.GetReturnValue().SetUndefined(); @@ -193,10 +204,12 @@ NAN_METHOD(Function::Invoke) } } - rc = RfcSetParameterActive(baton->functionHandle, parmDesc.name, true, &errorInfo); - if (rc != RFC_OK) { + RfcSetParameterActive(baton->functionHandle, parmDesc.name, true, &self->errorInfo); + LOG_API(self, "RfcSetParameterActive"); + if (self->errorInfo.code != RFC_OK) { delete baton; - RETURN_RFC_ERROR(errorInfo); + self->log(Levels::DBG, "Function::Invoke: RfcSetParameterActive returned error."); + RETURN_RFC_ERROR(self->errorInfo); } } @@ -213,29 +226,36 @@ NAN_METHOD(Function::Invoke) NAN_METHOD(Function::MetaData) { - RFC_RC rc = RFC_OK; unsigned int parmCount; - RFC_ERROR_INFO errorInfo; Function *self = node::ObjectWrap::Unwrap(info.This()); assert(self != nullptr); - rc = RfcGetParameterCount(self->functionDescHandle, &parmCount, &errorInfo); - if (rc != RFC_OK) { - RETURN_RFC_ERROR(errorInfo); + self->log(Levels::SILLY, "Function::MetaData"); + + RfcGetParameterCount(self->functionDescHandle, &parmCount, &self->errorInfo); + LOG_API(self, "RfcGetParameterCount"); + if (self->errorInfo.code != RFC_OK) { + self->log(Levels::DBG, "Function::MetaData: RfcGetParameterCount returned with error"); + RETURN_RFC_ERROR(self->errorInfo); } v8::Local metaObject = Nan::New(); RFC_ABAP_NAME functionName; - rc = RfcGetFunctionName(self->functionDescHandle, functionName, &errorInfo); - if (rc != RFC_OK) { - RETURN_RFC_ERROR(errorInfo); + RfcGetFunctionName(self->functionDescHandle, functionName, &self->errorInfo); + LOG_API(self, "RfcGetFunctionName"); + if (self->errorInfo.code != RFC_OK) { + self->log(Levels::DBG, "Function::MetaData: RfcGetFunctionName returned with error"); + RETURN_RFC_ERROR(self->errorInfo); } - RFC_FUNCTION_HANDLE functionHandle = RfcCreateFunction(self->functionDescHandle, &errorInfo); + RFC_FUNCTION_HANDLE functionHandle = RfcCreateFunction(self->functionDescHandle, &self->errorInfo); + LOG_API(self, "RfcCreateFunction"); if (functionHandle == nullptr) { - RfcDestroyFunction(functionHandle, &errorInfo); - RETURN_RFC_ERROR(errorInfo); + self->log(Levels::DBG, "Function::MetaData: RfcCreateFunction finished with error"); + RfcDestroyFunction(functionHandle, &self->errorInfo); + LOG_API(self, "RfcDestroyFunction"); + RETURN_RFC_ERROR(self->errorInfo); } std::string title = "Signature of SAP RFC function " + convertToString(functionName); @@ -252,40 +272,45 @@ NAN_METHOD(Function::MetaData) for (unsigned int i = 0; i < parmCount; i++) { RFC_PARAMETER_DESC parmDesc; - rc = RfcGetParameterDescByIndex(self->functionDescHandle, i, &parmDesc, &errorInfo); - if (rc != RFC_OK) { - RETURN_RFC_ERROR(errorInfo); + RfcGetParameterDescByIndex(self->functionDescHandle, i, &parmDesc, &self->errorInfo); + LOG_API(self, "RfcGetParameterDescByIndex"); + if (self->errorInfo.code != RFC_OK) { + self->log(Levels::DBG, "Function::MetaData: RfcGetParameterDescByIndex finished with error"); + RETURN_RFC_ERROR(self->errorInfo); } - if (!addMetaData(functionHandle, properties, parmDesc.name, parmDesc.type, - parmDesc.nucLength, parmDesc.direction, &errorInfo, parmDesc.parameterText)) { - RETURN_RFC_ERROR(errorInfo); + if (!self->addMetaData(functionHandle, properties, parmDesc.name, parmDesc.type, + parmDesc.nucLength, parmDesc.direction, parmDesc.parameterText)) { + RETURN_RFC_ERROR(self->errorInfo); } } - RfcDestroyFunction(functionHandle, &errorInfo); + RfcDestroyFunction(functionHandle, &self->errorInfo); + LOG_API(self, "RfcDestroyFunction"); info.GetReturnValue().Set(metaObject); } void Function::EIO_Invoke(uv_work_t *req) { - RFC_RC rc = RFC_OK; int isValid; InvocationBaton *baton = static_cast(req->data); assert(baton != nullptr); assert(baton->functionHandle != nullptr); + assert(baton->function != nullptr); baton->connection->LockMutex(); // Invocation - rc = RfcInvoke(baton->connection->GetConnectionHandle(), baton->functionHandle, &baton->errorInfo); + RfcInvoke(baton->connection->GetConnectionHandle(), baton->functionHandle, &baton->function->errorInfo); + DEFER_LOG_API(baton->function, "RfcInvoke"); // If handle is invalid, fetch a better error message - if (baton->errorInfo.code == RFC_INVALID_HANDLE) { - rc = RfcIsConnectionHandleValid(baton->connection->GetConnectionHandle(), &isValid, &baton->errorInfo); + if (baton->function->errorInfo.code == RFC_INVALID_HANDLE) { + RfcIsConnectionHandleValid(baton->connection->GetConnectionHandle(), &isValid, &baton->function->errorInfo); + DEFER_LOG_API(baton->function, "RfcIsConnectionHandleValid"); } baton->connection->UnlockMutex(); @@ -294,20 +319,21 @@ void Function::EIO_Invoke(uv_work_t *req) void Function::EIO_AfterInvoke(uv_work_t *req) { Nan::HandleScope scope; - RFC_ERROR_INFO errorInfo; InvocationBaton *baton = static_cast(req->data); assert(baton != nullptr); + Function* self = baton->function; + assert(self != nullptr); v8::Local argv[2]; argv[0] = Nan::Null(); argv[1] = Nan::Null(); - if (baton->errorInfo.code != RFC_OK) { - argv[0] = RfcError(baton->errorInfo); + if (self->errorInfo.code != RFC_OK) { + argv[0] = RfcError(self->errorInfo); } - v8::Local result = baton->function->DoReceive(baton->functionHandle); + v8::Local result = self->DoReceive(baton->functionHandle); if (IsException(result)) { argv[0] = result; } else { @@ -315,18 +341,21 @@ void Function::EIO_AfterInvoke(uv_work_t *req) } if (baton->functionHandle) { - RfcDestroyFunction(baton->functionHandle, &errorInfo); + RfcDestroyFunction(baton->functionHandle, &self->errorInfo); + LOG_API(self, "RfcDestroyFunction"); baton->functionHandle = nullptr; } Nan::TryCatch try_catch; assert(!baton->cbInvoke.IsEmpty()); + self->log(Levels::SILLY, "Function::EIO_AfterInvoke: About to call callback"); baton->cbInvoke->Call(Nan::GetCurrentContext()->Global(), 2, argv); delete baton; if (try_catch.HasCaught()) { + self->log(Levels::ERR, "Function::EIO_AfterInvoke: Callback has thrown. Aborting."); Nan::FatalException(try_catch); } } @@ -334,15 +363,14 @@ void Function::EIO_AfterInvoke(uv_work_t *req) v8::Local Function::DoReceive(const CHND container) { Nan::EscapableHandleScope scope; - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; unsigned int parmCount; v8::Local result = Nan::New(); // Get resulting values for exporting/changing/table parameters - rc = RfcGetParameterCount(this->functionDescHandle, &parmCount, &errorInfo); - if (rc != RFC_OK) { + RfcGetParameterCount(this->functionDescHandle, &parmCount, &errorInfo); + LOG_API(this, "RfcGetParameterCount"); + if (errorInfo.code != RFC_OK) { return scope.Escape(RfcError(errorInfo)); } @@ -350,8 +378,9 @@ v8::Local Function::DoReceive(const CHND container) RFC_PARAMETER_DESC parmDesc; v8::Local parmValue; - rc = RfcGetParameterDescByIndex(this->functionDescHandle, i, &parmDesc, &errorInfo); - if (rc != RFC_OK) { + RfcGetParameterDescByIndex(this->functionDescHandle, i, &parmDesc, &errorInfo); + LOG_API(this, "RfcGetParameterDescByIndex"); + if (errorInfo.code != RFC_OK) { return scope.Escape(RfcError(errorInfo)); } @@ -441,12 +470,11 @@ v8::Local Function::SetValue(const CHND container, RFCTYPE type, cons v8::Local Function::StructureToExternal(const CHND container, const SAP_UC *name, v8::Local value) { Nan::EscapableHandleScope scope; - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; RFC_STRUCTURE_HANDLE strucHandle; - rc = RfcGetStructure(container, name, &strucHandle, &errorInfo); - if (rc != RFC_OK) { + RfcGetStructure(container, name, &strucHandle, &errorInfo); + LOG_API(this, "RfcGetStructure"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -456,8 +484,6 @@ v8::Local Function::StructureToExternal(const CHND container, const S v8::Local Function::StructureToExternal(const CHND container, const RFC_STRUCTURE_HANDLE struc, v8::Local value) { Nan::EscapableHandleScope scope; - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; RFC_TYPE_DESC_HANDLE typeHandle; RFC_FIELD_DESC fieldDesc; unsigned fieldCount; @@ -468,19 +494,22 @@ v8::Local Function::StructureToExternal(const CHND container, const R v8::Local valueObj = value->ToObject(); typeHandle = RfcDescribeType(struc, &errorInfo); + LOG_API(this, "RfcDescribeType"); assert(typeHandle); if (typeHandle == nullptr) { return ESCAPE_RFC_ERROR(errorInfo); } - rc = RfcGetFieldCount(typeHandle, &fieldCount, &errorInfo); - if (rc != RFC_OK) { + RfcGetFieldCount(typeHandle, &fieldCount, &errorInfo); + LOG_API(this, "RfcGetFieldCount"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } for (unsigned int i = 0; i < fieldCount; i++) { - rc = RfcGetFieldDescByIndex(typeHandle, i, &fieldDesc, &errorInfo); - if (rc != RFC_OK) { + RfcGetFieldDescByIndex(typeHandle, i, &fieldDesc, &errorInfo); + LOG_API(this, "RfcGetFieldDescByIndex"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -501,8 +530,6 @@ v8::Local Function::StructureToExternal(const CHND container, const R v8::Local Function::TableToExternal(const CHND container, const SAP_UC *name, v8::Local value) { Nan::EscapableHandleScope scope; - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; RFC_TABLE_HANDLE tableHandle; RFC_STRUCTURE_HANDLE strucHandle; uint32_t rowCount; @@ -511,8 +538,9 @@ v8::Local Function::TableToExternal(const CHND container, const SAP_U return ESCAPE_RFC_ERROR("Argument has unexpected type: ", name); } - rc = RfcGetTable(container, name, &tableHandle, &errorInfo); - if (rc != RFC_OK) { + RfcGetTable(container, name, &tableHandle, &errorInfo); + LOG_API(this, "RfcGetTable"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -520,7 +548,8 @@ v8::Local Function::TableToExternal(const CHND container, const SAP_U rowCount = source->Length(); for (uint32_t i = 0; i < rowCount; i++){ - strucHandle = RfcAppendNewRow(tableHandle, nullptr); + strucHandle = RfcAppendNewRow(tableHandle, &errorInfo); + LOG_API(this, "RfcAppendNewRow"); v8::Local line = this->StructureToExternal(container, strucHandle, source->Get(i)); // Bail out on exception @@ -535,16 +564,15 @@ v8::Local Function::TableToExternal(const CHND container, const SAP_U v8::Local Function::StringToExternal(const CHND container, const SAP_UC *name, v8::Local value) { Nan::EscapableHandleScope scope; - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; if (!value->IsString()) { return ESCAPE_RFC_ERROR("Argument has unexpected type: ", name); } v8::String::Value valueU16(value->ToString()); - rc = RfcSetString(container, name, (const SAP_UC*)*valueU16, valueU16.length(), &errorInfo); - if (rc != RFC_OK) { + RfcSetString(container, name, (const SAP_UC*)*valueU16, valueU16.length(), &errorInfo); + LOG_API(this, "RfcSetString"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -554,8 +582,6 @@ v8::Local Function::StringToExternal(const CHND container, const SAP_ v8::Local Function::XStringToExternal(const CHND container, const SAP_UC *name, v8::Local value) { Nan::EscapableHandleScope scope; - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; if (!node::Buffer::HasInstance(value)) { return ESCAPE_RFC_ERROR("Argument has unexpected type: ", name); @@ -564,8 +590,9 @@ v8::Local Function::XStringToExternal(const CHND container, const SAP unsigned int bufferLength = node::Buffer::Length(value); SAP_RAW* bufferData = reinterpret_cast(node::Buffer::Data(value)); - rc = RfcSetXString(container, name, bufferData, bufferLength, &errorInfo); - if (rc != RFC_OK) { + RfcSetXString(container, name, bufferData, bufferLength, &errorInfo); + LOG_API(this, "RfcSetXString"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -575,8 +602,6 @@ v8::Local Function::XStringToExternal(const CHND container, const SAP v8::Local Function::NumToExternal(const CHND container, const SAP_UC *name, v8::Local value, unsigned len) { Nan::EscapableHandleScope scope; - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; if (!value->IsString()) { return ESCAPE_RFC_ERROR("Argument has unexpected type: ", name); @@ -587,8 +612,9 @@ v8::Local Function::NumToExternal(const CHND container, const SAP_UC return ESCAPE_RFC_ERROR("Argument exceeds maximum length: ", name); } - rc = RfcSetNum(container, name, (const RFC_NUM*)*valueU16, valueU16.length(), &errorInfo); - if (rc != RFC_OK) { + RfcSetNum(container, name, (const RFC_NUM*)*valueU16, valueU16.length(), &errorInfo); + LOG_API(this, "RfcSetNum"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -598,8 +624,6 @@ v8::Local Function::NumToExternal(const CHND container, const SAP_UC v8::Local Function::CharToExternal(const CHND container, const SAP_UC *name, v8::Local value, unsigned len) { Nan::EscapableHandleScope scope; - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; if (!value->IsString()) { return ESCAPE_RFC_ERROR("Argument has unexpected type: ", name); @@ -610,8 +634,9 @@ v8::Local Function::CharToExternal(const CHND container, const SAP_UC return ESCAPE_RFC_ERROR("Argument exceeds maximum length: ", name); } - rc = RfcSetChars(container, name, (const RFC_CHAR*)*valueU16, valueU16.length(), &errorInfo); - if (rc != RFC_OK) { + RfcSetChars(container, name, (const RFC_CHAR*)*valueU16, valueU16.length(), &errorInfo); + LOG_API(this, "RfcSetChars"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -621,8 +646,6 @@ v8::Local Function::CharToExternal(const CHND container, const SAP_UC v8::Local Function::ByteToExternal(const CHND container, const SAP_UC *name, v8::Local value, unsigned len) { Nan::EscapableHandleScope scope; - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; if (!node::Buffer::HasInstance(value)) { return ESCAPE_RFC_ERROR("Argument has unexpected type: ", name); @@ -635,8 +658,9 @@ v8::Local Function::ByteToExternal(const CHND container, const SAP_UC SAP_RAW* bufferData = reinterpret_cast(node::Buffer::Data(value)); - rc = RfcSetBytes(container, name, bufferData, len, &errorInfo); - if (rc != RFC_OK) { + RfcSetBytes(container, name, bufferData, len, &errorInfo); + LOG_API(this, "RfcSetBytes"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -647,16 +671,15 @@ v8::Local Function::ByteToExternal(const CHND container, const SAP_UC v8::Local Function::IntToExternal(const CHND container, const SAP_UC *name, v8::Local value) { Nan::EscapableHandleScope scope; - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; if (!value->IsInt32()) { return ESCAPE_RFC_ERROR("Argument has unexpected type: ", name); } RFC_INT rfcValue = value->ToInt32()->Value(); - rc = RfcSetInt(container, name, rfcValue, &errorInfo); - if (rc != RFC_OK) { + RfcSetInt(container, name, rfcValue, &errorInfo); + LOG_API(this, "RfcSetInt"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -666,20 +689,19 @@ v8::Local Function::IntToExternal(const CHND container, const SAP_UC v8::Local Function::Int1ToExternal(const CHND container, const SAP_UC *name, v8::Local value) { Nan::EscapableHandleScope scope; - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; if (!value->IsInt32()) { return ESCAPE_RFC_ERROR("Argument has unexpected type: ", name); } int32_t convertedValue = value->ToInt32()->Value(); - if ((convertedValue < INT8_MIN) || (convertedValue > INT8_MAX)) { + if ((convertedValue < std::numeric_limits::min()) || (convertedValue > std::numeric_limits::max())) { return ESCAPE_RFC_ERROR("Argument out of range: ", name); } RFC_INT1 rfcValue = convertedValue; - rc = RfcSetInt1(container, name, rfcValue, &errorInfo); - if (rc != RFC_OK) { + RfcSetInt1(container, name, rfcValue, &errorInfo); + LOG_API(this, "RfcSetInt1"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -689,21 +711,20 @@ v8::Local Function::Int1ToExternal(const CHND container, const SAP_UC v8::Local Function::Int2ToExternal(const CHND container, const SAP_UC *name, v8::Local value) { Nan::EscapableHandleScope scope; - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; if (!value->IsInt32()) { return ESCAPE_RFC_ERROR("Argument has unexpected type: ", name); } int32_t convertedValue = value->ToInt32()->Value(); - if ((convertedValue < INT16_MIN) || (convertedValue > INT16_MAX)) { + if ((convertedValue < std::numeric_limits::min()) || (convertedValue > std::numeric_limits::max())) { return ESCAPE_RFC_ERROR("Argument out of range: ", name); } RFC_INT2 rfcValue = convertedValue; - rc = RfcSetInt2(container, name, rfcValue, &errorInfo); - if (rc != RFC_OK) { + RfcSetInt2(container, name, rfcValue, &errorInfo); + LOG_API(this, "RfcSetInt2"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -713,16 +734,15 @@ v8::Local Function::Int2ToExternal(const CHND container, const SAP_UC v8::Local Function::FloatToExternal(const CHND container, const SAP_UC *name, v8::Local value) { Nan::EscapableHandleScope scope; - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; if (!value->IsNumber()) { return ESCAPE_RFC_ERROR("Argument has unexpected type: ", name); } RFC_FLOAT rfcValue = value->ToNumber()->Value(); - rc = RfcSetFloat(container, name, rfcValue, &errorInfo); - if (rc != RFC_OK) { + RfcSetFloat(container, name, rfcValue, &errorInfo); + LOG_API(this, "RfcSetFloat"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -732,7 +752,6 @@ v8::Local Function::FloatToExternal(const CHND container, const SAP_U v8::Local Function::DateToExternal(const CHND container, const SAP_UC *name, v8::Local value) { Nan::EscapableHandleScope scope; - RFC_ERROR_INFO errorInfo; if (!value->IsString()) { return ESCAPE_RFC_ERROR("Argument has unexpected type: ", name); @@ -745,8 +764,9 @@ v8::Local Function::DateToExternal(const CHND container, const SAP_UC v8::String::Value rfcValue(str); assert(*rfcValue); - RFC_RC rc = RfcSetDate(container, name, (const RFC_CHAR*)*rfcValue, &errorInfo); - if (rc != RFC_OK) { + RfcSetDate(container, name, (const RFC_CHAR*)*rfcValue, &errorInfo); + LOG_API(this, "RfcSetDate"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -756,7 +776,6 @@ v8::Local Function::DateToExternal(const CHND container, const SAP_UC v8::Local Function::TimeToExternal(const CHND container, const SAP_UC *name, v8::Local value) { Nan::EscapableHandleScope scope; - RFC_ERROR_INFO errorInfo; if (!value->IsString()) { return ESCAPE_RFC_ERROR("Argument has unexpected type: ", name); @@ -769,8 +788,9 @@ v8::Local Function::TimeToExternal(const CHND container, const SAP_UC v8::String::Value rfcValue(str); assert(*rfcValue); - RFC_RC rc = RfcSetTime(container, name, (const RFC_CHAR*)*rfcValue, &errorInfo); - if (rc != RFC_OK) { + RfcSetTime(container, name, (const RFC_CHAR*)*rfcValue, &errorInfo); + LOG_API(this, "RfcSetTime"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -780,8 +800,6 @@ v8::Local Function::TimeToExternal(const CHND container, const SAP_UC v8::Local Function::BCDToExternal(const CHND container, const SAP_UC *name, v8::Local value) { Nan::EscapableHandleScope scope; - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; if (!value->IsNumber()) { return ESCAPE_RFC_ERROR("Argument has unexpected type: ", name); @@ -789,8 +807,9 @@ v8::Local Function::BCDToExternal(const CHND container, const SAP_UC v8::String::Value valueU16(value->ToString()); - rc = RfcSetString(container, name, (const SAP_UC*)*valueU16, valueU16.length(), &errorInfo); - if (rc != RFC_OK) { + RfcSetString(container, name, (const SAP_UC*)*valueU16, valueU16.length(), &errorInfo); + LOG_API(this, "RfcSetString"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -857,12 +876,11 @@ v8::Local Function::GetValue(const CHND container, RFCTYPE type, cons v8::Local Function::StructureToInternal(const CHND container, const SAP_UC *name) { Nan::EscapableHandleScope scope; - RFC_ERROR_INFO errorInfo; - RFC_RC rc = RFC_OK; RFC_STRUCTURE_HANDLE strucHandle; - rc = RfcGetStructure(container, name, &strucHandle, &errorInfo); - if (rc != RFC_OK) { + RfcGetStructure(container, name, &strucHandle, &errorInfo); + LOG_API(this, "RfcGetStructure"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -872,28 +890,29 @@ v8::Local Function::StructureToInternal(const CHND container, const S v8::Local Function::StructureToInternal(const CHND container, const RFC_STRUCTURE_HANDLE struc) { Nan::EscapableHandleScope scope; - RFC_ERROR_INFO errorInfo; - RFC_RC rc = RFC_OK; RFC_TYPE_DESC_HANDLE typeHandle; RFC_FIELD_DESC fieldDesc; unsigned fieldCount; typeHandle = RfcDescribeType(struc, &errorInfo); + LOG_API(this, "RfcDescribeType"); assert(typeHandle); if (typeHandle == nullptr) { return ESCAPE_RFC_ERROR(errorInfo); } - rc = RfcGetFieldCount(typeHandle, &fieldCount, &errorInfo); - if (rc != RFC_OK) { + RfcGetFieldCount(typeHandle, &fieldCount, &errorInfo); + LOG_API(this, "RfcGetFieldCount"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } v8::Local obj = Nan::New(); for (unsigned int i = 0; i < fieldCount; i++) { - rc = RfcGetFieldDescByIndex(typeHandle, i, &fieldDesc, &errorInfo); - if (rc != RFC_OK) { + RfcGetFieldDescByIndex(typeHandle, i, &fieldDesc, &errorInfo); + LOG_API(this, "RfcGetFieldDescByIndex"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -911,19 +930,19 @@ v8::Local Function::StructureToInternal(const CHND container, const R v8::Local Function::TableToInternal(const CHND container, const SAP_UC *name) { Nan::EscapableHandleScope scope; - RFC_ERROR_INFO errorInfo; - RFC_RC rc = RFC_OK; RFC_TABLE_HANDLE tableHandle; RFC_STRUCTURE_HANDLE strucHandle; unsigned rowCount; - rc = RfcGetTable(container, name, &tableHandle, &errorInfo); - if (rc != RFC_OK) { + RfcGetTable(container, name, &tableHandle, &errorInfo); + LOG_API(this, "RfcGetTable"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } - rc = RfcGetRowCount(tableHandle, &rowCount, nullptr); - if (rc != RFC_OK) { + RfcGetRowCount(tableHandle, &rowCount, &errorInfo); + LOG_API(this, "RfcGetRowCount"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -931,8 +950,10 @@ v8::Local Function::TableToInternal(const CHND container, const SAP_U v8::Local obj = Nan::New(); for (unsigned int i = 0; i < rowCount; i++){ - RfcMoveTo(tableHandle, i, nullptr); - strucHandle = RfcGetCurrentRow(tableHandle, nullptr); + RfcMoveTo(tableHandle, i, &errorInfo); + LOG_API(this, "RfcMoveTo"); + strucHandle = RfcGetCurrentRow(tableHandle, &errorInfo); + LOG_API(this, "RfcGetCurrentRow"); v8::Local line = this->StructureToInternal(container, strucHandle); // Bail out on exception @@ -948,12 +969,11 @@ v8::Local Function::TableToInternal(const CHND container, const SAP_U v8::Local Function::StringToInternal(const CHND container, const SAP_UC *name) { Nan::EscapableHandleScope scope; - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; unsigned strLen, retStrLen; - rc = RfcGetStringLength(container, name, &strLen, &errorInfo); - if (rc != RFC_OK) { + RfcGetStringLength(container, name, &strLen, &errorInfo); + LOG_API(this, "RfcGetStringLength"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -965,8 +985,9 @@ v8::Local Function::StringToInternal(const CHND container, const SAP_ assert(buffer); memset(buffer, 0, (strLen + 1) * sizeof(SAP_UC)); - rc = RfcGetString(container, name, buffer, strLen + 1, &retStrLen, &errorInfo); - if (rc != RFC_OK) { + RfcGetString(container, name, buffer, strLen + 1, &retStrLen, &errorInfo); + LOG_API(this, "RfcGetString"); + if (errorInfo.code != RFC_OK) { free(buffer); return ESCAPE_RFC_ERROR(errorInfo); } @@ -981,12 +1002,11 @@ v8::Local Function::StringToInternal(const CHND container, const SAP_ v8::Local Function::XStringToInternal(const CHND container, const SAP_UC *name) { Nan::EscapableHandleScope scope; - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; unsigned strLen, retStrLen; - rc = RfcGetStringLength(container, name, &strLen, &errorInfo); - if (rc != RFC_OK) { + RfcGetStringLength(container, name, &strLen, &errorInfo); + LOG_API(this, "RfcGetStringLength"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -998,8 +1018,9 @@ v8::Local Function::XStringToInternal(const CHND container, const SAP assert(buffer); memset(buffer, 0, strLen * sizeof(SAP_RAW)); - rc = RfcGetXString(container, name, buffer, strLen, &retStrLen, &errorInfo); - if (rc != RFC_OK) { + RfcGetXString(container, name, buffer, strLen, &retStrLen, &errorInfo); + LOG_API(this, "RfcGetXString"); + if (errorInfo.code != RFC_OK) { free(buffer); return ESCAPE_RFC_ERROR(errorInfo); } @@ -1012,14 +1033,14 @@ v8::Local Function::XStringToInternal(const CHND container, const SAP v8::Local Function::NumToInternal(const CHND container, const SAP_UC *name, unsigned len) { Nan::EscapableHandleScope scope; - RFC_ERROR_INFO errorInfo; RFC_NUM *buffer = static_cast(malloc((len + 1) * sizeof(RFC_NUM))); assert(buffer); memset(buffer, 0, (len + 1) * sizeof(RFC_NUM)); - RFC_RC rc = RfcGetNum(container, name, buffer, len, &errorInfo); - if (rc != RFC_OK) { + RfcGetNum(container, name, buffer, len, &errorInfo); + LOG_API(this, "RfcGetNum"); + if (errorInfo.code != RFC_OK) { free(buffer); return ESCAPE_RFC_ERROR(errorInfo); } @@ -1034,14 +1055,14 @@ v8::Local Function::NumToInternal(const CHND container, const SAP_UC v8::Local Function::CharToInternal(const CHND container, const SAP_UC *name, unsigned len) { Nan::EscapableHandleScope scope; - RFC_ERROR_INFO errorInfo; RFC_CHAR *buffer = static_cast(malloc((len + 1) * sizeof(RFC_CHAR))); assert(buffer); memset(buffer, 0, (len + 1) * sizeof(RFC_CHAR)); - RFC_RC rc = RfcGetChars(container, name, buffer, len, &errorInfo); - if (rc != RFC_OK) { + RfcGetChars(container, name, buffer, len, &errorInfo); + LOG_API(this, "RfcGetChars"); + if (errorInfo.code != RFC_OK) { free(buffer); return ESCAPE_RFC_ERROR(errorInfo); } @@ -1056,14 +1077,14 @@ v8::Local Function::CharToInternal(const CHND container, const SAP_UC v8::Local Function::ByteToInternal(const CHND container, const SAP_UC *name, unsigned len) { Nan::EscapableHandleScope scope; - RFC_ERROR_INFO errorInfo; RFC_BYTE *buffer = static_cast(malloc(len * sizeof(RFC_BYTE))); assert(buffer); memset(buffer, 0, len * sizeof(RFC_BYTE)); - RFC_RC rc = RfcGetBytes(container, name, buffer, len, &errorInfo); - if (rc != RFC_OK) { + RfcGetBytes(container, name, buffer, len, &errorInfo); + LOG_API(this, "RfcGetBytes"); + if (errorInfo.code != RFC_OK) { free(buffer); return ESCAPE_RFC_ERROR(errorInfo); } @@ -1076,11 +1097,11 @@ v8::Local Function::ByteToInternal(const CHND container, const SAP_UC v8::Local Function::IntToInternal(const CHND container, const SAP_UC *name) { Nan::EscapableHandleScope scope; - RFC_ERROR_INFO errorInfo; RFC_INT value; - RFC_RC rc = RfcGetInt(container, name, &value, &errorInfo); - if (rc != RFC_OK) { + RfcGetInt(container, name, &value, &errorInfo); + LOG_API(this, "RfcGetInt"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -1090,11 +1111,11 @@ v8::Local Function::IntToInternal(const CHND container, const SAP_UC v8::Local Function::Int1ToInternal(const CHND container, const SAP_UC *name) { Nan::EscapableHandleScope scope; - RFC_ERROR_INFO errorInfo; RFC_INT1 value; - RFC_RC rc = RfcGetInt1(container, name, &value, &errorInfo); - if (rc != RFC_OK) { + RfcGetInt1(container, name, &value, &errorInfo); + LOG_API(this, "RfcGetInt1"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -1104,11 +1125,11 @@ v8::Local Function::Int1ToInternal(const CHND container, const SAP_UC v8::Local Function::Int2ToInternal(const CHND container, const SAP_UC *name) { Nan::EscapableHandleScope scope; - RFC_ERROR_INFO errorInfo; RFC_INT2 value; - RFC_RC rc = RfcGetInt2(container, name, &value, &errorInfo); - if (rc != RFC_OK) { + RfcGetInt2(container, name, &value, &errorInfo); + LOG_API(this, "RfcGetInt2"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -1118,11 +1139,11 @@ v8::Local Function::Int2ToInternal(const CHND container, const SAP_UC v8::Local Function::FloatToInternal(const CHND container, const SAP_UC *name) { Nan::EscapableHandleScope scope; - RFC_ERROR_INFO errorInfo; RFC_FLOAT value; - RFC_RC rc = RfcGetFloat(container, name, &value, &errorInfo); - if (rc != RFC_OK) { + RfcGetFloat(container, name, &value, &errorInfo); + LOG_API(this, "RfcGetFloat"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -1132,11 +1153,11 @@ v8::Local Function::FloatToInternal(const CHND container, const SAP_U v8::Local Function::DateToInternal(const CHND container, const SAP_UC *name) { Nan::EscapableHandleScope scope; - RFC_ERROR_INFO errorInfo; RFC_DATE date = { 0 }; - RFC_RC rc = RfcGetDate(container, name, date, &errorInfo); - if (rc != RFC_OK) { + RfcGetDate(container, name, date, &errorInfo); + LOG_API(this, "RfcGetDate"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -1150,11 +1171,11 @@ v8::Local Function::DateToInternal(const CHND container, const SAP_UC v8::Local Function::TimeToInternal(const CHND container, const SAP_UC *name) { Nan::EscapableHandleScope scope; - RFC_ERROR_INFO errorInfo; RFC_TIME time = { 0 }; - RFC_RC rc = RfcGetTime(container, name, time, &errorInfo); - if (rc != RFC_OK) { + RfcGetTime(container, name, time, &errorInfo); + LOG_API(this, "RfcGetTime"); + if (errorInfo.code != RFC_OK) { return ESCAPE_RFC_ERROR(errorInfo); } @@ -1168,8 +1189,6 @@ v8::Local Function::TimeToInternal(const CHND container, const SAP_UC v8::Local Function::BCDToInternal(const CHND container, const SAP_UC *name) { Nan::EscapableHandleScope scope; - RFC_RC rc = RFC_OK; - RFC_ERROR_INFO errorInfo; unsigned strLen = 25; unsigned retStrLen; SAP_UC *buffer; @@ -1179,17 +1198,19 @@ v8::Local Function::BCDToInternal(const CHND container, const SAP_UC assert(buffer); memset(buffer, 0, (strLen + 1) * sizeof(SAP_UC)); - rc = RfcGetString(container, name, buffer, strLen + 1, &retStrLen, &errorInfo); + RfcGetString(container, name, buffer, strLen + 1, &retStrLen, &errorInfo); + LOG_API(this, "RfcGetString"); - if (rc == RFC_BUFFER_TOO_SMALL) { + if (errorInfo.code == RFC_BUFFER_TOO_SMALL) { // Retry with suggested string length free(buffer); strLen = retStrLen; - } else if (rc != RFC_OK) { + log(Levels::SILLY, "Function::BCDToInternal: Retry"); + } else if (errorInfo.code != RFC_OK) { free(buffer); return ESCAPE_RFC_ERROR(errorInfo); } - } while (rc == RFC_BUFFER_TOO_SMALL); + } while (errorInfo.code == RFC_BUFFER_TOO_SMALL); v8::Local value = Nan::New((const uint16_t*)(buffer), retStrLen).ToLocalChecked(); @@ -1240,12 +1261,12 @@ std::string Function::mapExternalTypeToJavaScriptType(RFCTYPE sapType) } bool Function::addMetaData(const CHND container, v8::Local &parent, - const RFC_ABAP_NAME name, RFCTYPE type, - unsigned int length, RFC_DIRECTION direction, - RFC_ERROR_INFO *errorInfo, RFC_PARAMETER_TEXT paramText) + const RFC_ABAP_NAME name, RFCTYPE type, unsigned int length, + RFC_DIRECTION direction, RFC_PARAMETER_TEXT paramText) { Nan::EscapableHandleScope scope; - RFC_RC rc = RFC_OK; + + log(Levels::SILLY, "Function::addMetaData"); v8::Local actualType = Nan::New(); parent->Set(Nan::New((const uint16_t*)name).ToLocalChecked(), actualType); @@ -1265,7 +1286,7 @@ bool Function::addMetaData(const CHND container, v8::Local &parent, Nan::New((uint16_t*)RfcGetTypeAsString(type)).ToLocalChecked()); if (paramText != nullptr) { - actualType->Set( + actualType->Set( Nan::New("description").ToLocalChecked(), Nan::New((const uint16_t*)paramText).ToLocalChecked()); } @@ -1283,42 +1304,47 @@ bool Function::addMetaData(const CHND container, v8::Local &parent, unsigned fieldCount; RFC_ABAP_NAME typeName; - rc = RfcGetStructure(container, name, &strucHandle, errorInfo); - if (rc != RFC_OK) { + RfcGetStructure(container, name, &strucHandle, &errorInfo); + LOG_API(this, "RfcGetStructure"); + if (errorInfo.code != RFC_OK) { return false; } - typeHandle = RfcDescribeType(strucHandle, errorInfo); + typeHandle = RfcDescribeType(strucHandle, &errorInfo); + LOG_API(this, "RfcDescribeType"); assert(typeHandle); if (typeHandle == nullptr) { return false; } - rc = RfcGetTypeName(typeHandle, typeName, errorInfo); - if (rc != RFC_OK) { + RfcGetTypeName(typeHandle, typeName, &errorInfo); + LOG_API(this, "RfcGetTypeName"); + if (errorInfo.code != RFC_OK) { return false; - } + } - actualType->Set( + actualType->Set( Nan::New("sapTypeName").ToLocalChecked(), Nan::New((const uint16_t*)typeName).ToLocalChecked()); - rc = RfcGetFieldCount(typeHandle, &fieldCount, errorInfo); - if (rc != RFC_OK) { - return false; - } + RfcGetFieldCount(typeHandle, &fieldCount, &errorInfo); + LOG_API(this, "RfcGetFieldCount"); + if (errorInfo.code != RFC_OK) { + return false; + } - v8::Local properties = Nan::New(); + v8::Local properties = Nan::New(); actualType->Set(Nan::New("properties").ToLocalChecked(), properties); for (unsigned int i = 0; i < fieldCount; i++) { - rc = RfcGetFieldDescByIndex(typeHandle, i, &fieldDesc, errorInfo); - if (rc != RFC_OK) { + RfcGetFieldDescByIndex(typeHandle, i, &fieldDesc, &errorInfo); + LOG_API(this, "RfcGetFieldDescByIndex"); + if (errorInfo.code != RFC_OK) { return false; } if (!addMetaData( strucHandle, properties, fieldDesc.name, fieldDesc.type, - fieldDesc.nucLength, RFC_DIRECTION(0), errorInfo)) { + fieldDesc.nucLength, RFC_DIRECTION(0))) { return false; } } @@ -1330,59 +1356,60 @@ bool Function::addMetaData(const CHND container, v8::Local &parent, unsigned fieldCount; RFC_ABAP_NAME typeName; - rc = RfcGetTable(container, name, &tableHandle, errorInfo); - if (rc != RFC_OK) { + RfcGetTable(container, name, &tableHandle, &errorInfo); + LOG_API(this, "RfcGetTable"); + if (errorInfo.code != RFC_OK) { return false; } - typeHandle = RfcDescribeType(tableHandle, errorInfo); + typeHandle = RfcDescribeType(tableHandle, &errorInfo); + LOG_API(this, "RfcDescribeType"); assert(typeHandle); if (typeHandle == nullptr) { return false; } - rc = RfcGetTypeName(typeHandle, typeName, errorInfo); - if (rc != RFC_OK) { - return false; - } - - typeHandle = RfcDescribeType(tableHandle, errorInfo); - assert(typeHandle); - if (typeHandle == nullptr) { - return false; - } + RfcGetTypeName(typeHandle, typeName, &errorInfo); + LOG_API(this, "RfcGetTypeName"); + if (errorInfo.code != RFC_OK) { + return false; + } - rc = RfcGetFieldCount(typeHandle, &fieldCount, errorInfo); - if (rc != RFC_OK) { - return false; - } + RfcGetFieldCount(typeHandle, &fieldCount, &errorInfo); + LOG_API(this, "RfcGetFieldCount"); + if (errorInfo.code != RFC_OK) { + return false; + } - v8::Local items = Nan::New(); - actualType->Set(Nan::New("items").ToLocalChecked(), items); - items->Set( - Nan::New("sapTypeName").ToLocalChecked(), - Nan::New((const uint16_t*)typeName).ToLocalChecked()); + v8::Local items = Nan::New(); + actualType->Set(Nan::New("items").ToLocalChecked(), items); + items->Set( + Nan::New("sapTypeName").ToLocalChecked(), + Nan::New((const uint16_t*)typeName).ToLocalChecked()); items->Set( - Nan::New("type").ToLocalChecked(), - Nan::New("object").ToLocalChecked()); + Nan::New("type").ToLocalChecked(), + Nan::New("object").ToLocalChecked()); v8::Local properties = Nan::New(); items->Set(Nan::New("properties").ToLocalChecked(), properties); - RFC_STRUCTURE_HANDLE rowHandle = RfcAppendNewRow(tableHandle, errorInfo); - if (rc != RFC_OK) { + RFC_STRUCTURE_HANDLE rowHandle = RfcAppendNewRow(tableHandle, &errorInfo); + LOG_API(this, "RfcAppendNewRow"); + if (errorInfo.code != RFC_OK) { return false; } for (unsigned int i = 0; i < fieldCount; i++) { - rc = RfcGetFieldDescByIndex(typeHandle, i, &fieldDesc, errorInfo); - if (rc != RFC_OK) { + RfcGetFieldDescByIndex(typeHandle, i, &fieldDesc, &errorInfo); + LOG_API(this, "RfcGetFieldDescByIndex"); + if (errorInfo.code != RFC_OK) { return false; } + log(Levels::SILLY, "Function::addMetaData recurse"); if (!addMetaData( rowHandle, properties, fieldDesc.name, fieldDesc.type, - fieldDesc.nucLength, RFC_DIRECTION(0), errorInfo)) { + fieldDesc.nucLength, RFC_DIRECTION(0))) { return false; } } diff --git a/src/Function.h b/src/Function.h index 0f0f7a7..5727192 100644 --- a/src/Function.h +++ b/src/Function.h @@ -26,13 +26,11 @@ SOFTWARE. #define FUNCTION_H_ #include "Common.h" -#include -#include -#include +#include "Loggable.h" #include #include "Connection.h" -class Function : public node::ObjectWrap +class Function : public Loggable { public: static NAN_MODULE_INIT(Init); @@ -86,20 +84,22 @@ class Function : public node::ObjectWrap v8::Local BCDToInternal(const CHND container, const SAP_UC *name); static std::string mapExternalTypeToJavaScriptType(RFCTYPE sapType); - static bool addMetaData(const CHND container, v8::Local& parent, - const RFC_ABAP_NAME name, RFCTYPE type, - unsigned int length, RFC_DIRECTION direction, - RFC_ERROR_INFO* errorInfo, RFC_PARAMETER_TEXT paramText = nullptr); + bool addMetaData(const CHND container, v8::Local& parent, const RFC_ABAP_NAME name, + RFCTYPE type, unsigned int length, RFC_DIRECTION direction, + RFC_PARAMETER_TEXT paramText = nullptr); class InvocationBaton { public: - InvocationBaton() : function(nullptr), functionHandle(nullptr) { }; + InvocationBaton() : function(nullptr), functionHandle(nullptr) { } ~InvocationBaton() { RFC_ERROR_INFO errorInfo; if (this->functionHandle) { RfcDestroyFunction(this->functionHandle, &errorInfo); + if(function) { + function->deferLogAPICall("RfcDestroyFunction", __FILE__, BOOST_CURRENT_FUNCTION, __LINE__, errorInfo); + } this->functionHandle = nullptr; } @@ -109,19 +109,19 @@ class Function : public node::ObjectWrap delete this->cbInvoke; this->cbInvoke = nullptr; - }; + } Function *function; Connection *connection; RFC_FUNCTION_HANDLE functionHandle; Nan::Callback *cbInvoke; - RFC_ERROR_INFO errorInfo; }; static Nan::Persistent ctor; Connection *connection; RFC_FUNCTION_DESC_HANDLE functionDescHandle; + RFC_ERROR_INFO errorInfo; }; #endif /* FUNCTION_H_ */ diff --git a/src/Loggable.cc b/src/Loggable.cc new file mode 100644 index 0000000..0719b7b --- /dev/null +++ b/src/Loggable.cc @@ -0,0 +1,247 @@ +/* +----------------------------------------------------------------------------- +Copyright (c) 2016 Scheer E2E AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +----------------------------------------------------------------------------- +*/ + +#include "Loggable.h" +#include + +const std::string Loggable::Levels::SILLY = "silly"; +const std::string Loggable::Levels::DBG = "debug"; +const std::string Loggable::Levels::VERBOSE = "verbose"; +const std::string Loggable::Levels::INFO = "info"; +const std::string Loggable::Levels::WARN = "warn"; +const std::string Loggable::Levels::ERR = "error"; + +const std::string Loggable::API_CALL_MESSAGE = "SAPNWRFC API Call"; + +v8::Local metaToJS( const Loggable::LogEntry::Meta& meta) +{ + Nan::EscapableHandleScope scope; + + v8::Local result = Nan::New(); + + for( Loggable::LogEntry::Meta::const_iterator it = meta.begin(), eit = meta.end(); it != eit; ++it) + { + result->Set( + Nan::New(it->first).ToLocalChecked(), + Nan::New(it->second).ToLocalChecked() + ); + } + + return scope.Escape(result); +} + +static v8::Local errorInfoToJS(const RFC_ERROR_INFO &info) +{ + Nan::EscapableHandleScope scope; + + v8::Local obj = Nan::New(); + obj->Set( + Nan::New("code").ToLocalChecked(), + Nan::New(info.code) + ); + obj->Set( + Nan::New("group").ToLocalChecked(), + Nan::New(info.group) + ); + obj->Set( + Nan::New("key").ToLocalChecked(), + Nan::New((const uint16_t*)(info.key)).ToLocalChecked() + ); + obj->Set( + Nan::New("class").ToLocalChecked(), + Nan::New((const uint16_t*)(info.abapMsgClass)).ToLocalChecked() + ); + obj->Set( + Nan::New("type").ToLocalChecked(), + Nan::New((const uint16_t*)(info.abapMsgType)).ToLocalChecked() + ); + obj->Set( + Nan::New("number").ToLocalChecked(), + Nan::New((const uint16_t*)(info.abapMsgNumber)).ToLocalChecked() + ); + obj->Set( + Nan::New("msgv1").ToLocalChecked(), + Nan::New((const uint16_t*)(info.abapMsgV1)).ToLocalChecked() + ); + obj->Set( + Nan::New("msgv2").ToLocalChecked(), + Nan::New((const uint16_t*)(info.abapMsgV2)).ToLocalChecked() + ); + obj->Set( + Nan::New("msgv3").ToLocalChecked(), + Nan::New((const uint16_t*)(info.abapMsgV3)).ToLocalChecked() + ); + obj->Set( + Nan::New("msgv4").ToLocalChecked(), + Nan::New((const uint16_t*)(info.abapMsgV4)).ToLocalChecked() + ); + + return scope.Escape(obj); +} + +void Loggable::logFunctionWeakCallback(const Nan::WeakCallbackInfo& data) +{ + data.GetParameter()->resetLogFunction(); +} + +Loggable::~Loggable() +{ + resetLogFunction(); +} + +void Loggable::log(const std::string& level, const std::string& message) +{ + log(level, Nan::New(message).ToLocalChecked()); +} + +void Loggable::log(const std::string& level, v8::Local message) +{ + log(level, message, Nan::Undefined()); +} + +void Loggable::log(const std::string& level, const std::string& message, v8::Local meta) +{ + log(level, Nan::New(message).ToLocalChecked(), meta); +} + +void Loggable::log(const std::string& level, v8::Local message, v8::Local meta) +{ + logDeferred(); + log_(level, message, meta); +} + +void Loggable::log_(const std::string& level, v8::Local message, v8::Local meta) +{ + if( logFunction.IsEmpty()) { + logFunction = + Nan::Persistent>( + v8::Local::Cast( + Nan::Get(handle(), + Nan::New("_log").ToLocalChecked()).ToLocalChecked())); + logFunction.SetWeak(this, logFunctionWeakCallback, Nan::WeakCallbackType::kParameter); + logFunction.MarkIndependent(); + } + + v8::Local argv[3]; + argv[0] = Nan::New(level).ToLocalChecked(); + argv[1] = message->ToString(); + argv[2] = meta; + assert(!logFunction.IsEmpty()); + Nan::Call(Nan::New(logFunction), handle(), 3, argv); +} + +void Loggable::log(const LogEntry& logEntry) +{ + Nan::HandleScope scope; + + v8::Handle meta; + if(!logEntry.call.empty()) { + meta = v8::Handle::Cast( metaToJS( logEntry.meta)); + meta->Set(Nan::New("call").ToLocalChecked(), Nan::New(logEntry.call).ToLocalChecked()); + meta->Set(Nan::New("errorInfo").ToLocalChecked(), errorInfoToJS(logEntry.errorInfo)); + } else { + meta = Nan::New(); + } + + if(!logEntry.file.empty()) { + meta->Set(Nan::New("file").ToLocalChecked(), Nan::New(logEntry.file).ToLocalChecked()); + } + + if(!logEntry.function.empty()) { + meta->Set(Nan::New("function").ToLocalChecked(), Nan::New(logEntry.function).ToLocalChecked()); + } + + if(logEntry.line) { + meta->Set(Nan::New("line").ToLocalChecked(), Nan::New(logEntry.line)); + } + + log_(logEntry.level, Nan::New(logEntry.message).ToLocalChecked(), meta); +} + +void Loggable::deferLog(const std::string& level, const std::string& message, const Loggable::LogEntry::Meta& meta) +{ + LogEntry entry; + entry.level = level; + entry.message = message; + entry.meta = meta; + deferredLogs.push_back( entry); +} + +void Loggable::createAPILogEntry_(Loggable::LogEntry& logEntry, const std::string& call, + const std::string& file, const std::string& function, + unsigned long line, RFC_ERROR_INFO& errorInfo, + const Loggable::LogEntry::Meta& meta) +{ + logEntry.level = Levels::DBG; + logEntry.message = API_CALL_MESSAGE; + logEntry.call = call; + logEntry.file = file; + logEntry.function = function; + logEntry.line = line; + logEntry.errorInfo = errorInfo; + logEntry.meta = meta; +} + +void Loggable::logAPICall(const std::string& call, const std::string& file, const std::string& function, + unsigned long line, RFC_ERROR_INFO& errorInfo) +{ + logAPICall(call, file, function, line, errorInfo, LogEntry::Meta()); +} + +void Loggable::logAPICall(const std::string& call, const std::string& file, const std::string& function, + unsigned long line, RFC_ERROR_INFO& errorInfo, const Loggable::LogEntry::Meta& meta) +{ + logDeferred(); + LogEntry logEntry; + createAPILogEntry_(logEntry, call, file, function, line, errorInfo, meta); + log(logEntry); +} + +void Loggable::deferLogAPICall(const std::string& call, const std::string& file, const std::string& function, + unsigned long line, RFC_ERROR_INFO& errorInfo) +{ + deferLogAPICall(call, file, function, line, errorInfo, LogEntry::Meta()); +} + +void Loggable::deferLogAPICall(const std::string& call, const std::string& file, const std::string& function, + unsigned long line, RFC_ERROR_INFO& errorInfo, const Loggable::LogEntry::Meta& meta) +{ + LogEntry logEntry; + createAPILogEntry_(logEntry, call, file, function, line, errorInfo, meta); + deferredLogs.push_back( logEntry); +} + +void Loggable::logDeferred() +{ + for(LogEntries::iterator it = deferredLogs.begin(), eit = deferredLogs.end(); it != eit; ++it) + { + log(*it); + } + deferredLogs.clear(); +} + +void Loggable::resetLogFunction() +{ + logFunction.Reset(); +} diff --git a/src/Loggable.h b/src/Loggable.h new file mode 100644 index 0000000..8570302 --- /dev/null +++ b/src/Loggable.h @@ -0,0 +1,114 @@ +/* +----------------------------------------------------------------------------- +Copyright (c) 2016 Scheer E2E AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +----------------------------------------------------------------------------- +*/ + +#ifndef LOGGABLE_H_ +#define LOGGABLE_H_ + +#include "Common.h" +#include +#include +#include +#include +#include +#include "current_function.hpp" + +class Loggable : public node::ObjectWrap +{ + public: + static void logFunctionWeakCallback(const Nan::WeakCallbackInfo& data); + ~Loggable(); + + class Levels + { + public: + static const std::string SILLY; + static const std::string DBG; // DEBUG may be set by GYP on various occasions... + static const std::string VERBOSE; + static const std::string INFO; + static const std::string WARN; + static const std::string ERR; // ERROR is set by windows.h. I don't even... + }; + + struct LogEntry + { + typedef std::vector > Meta; + + std::string level; + std::string message; + std::string file; + uint32_t line; + std::string function; + std::string call; + Meta meta; + RFC_ERROR_INFO errorInfo; + }; + + static const std::string API_CALL_MESSAGE; + + protected: + + Nan::Persistent> logFunction; + + void log( const std::string& level, const char* message) { log(level, std::string(message)); } + void log( const std::string& level, const std::string& message); + void log( const std::string& level, v8::Local message); + void log( const std::string& level, const char* message, v8::Local meta) { log(level, std::string(message), meta); } + void log( const std::string& level, const std::string& message, v8::Local meta); + void log( const std::string& level, v8::Local message, v8::Local meta); + void log_( const std::string& level, v8::Local message, v8::Local meta); + void log( const LogEntry& logEntry); + void logAPICall(const std::string& call, const std::string& file, const std::string& function, + unsigned long line, RFC_ERROR_INFO& errorInfo); + void logAPICall(const std::string& call, const std::string& file, const std::string& function, + unsigned long line, RFC_ERROR_INFO& errorInfo, const Loggable::LogEntry::Meta& meta); + void deferLogAPICall(const std::string& call, const std::string& file, const std::string& function, + unsigned long line, RFC_ERROR_INFO& errorInfo); + void deferLogAPICall(const std::string& call, const std::string& file, const std::string& function, + unsigned long line, RFC_ERROR_INFO& errorInfo, const Loggable::LogEntry::Meta& meta); + + /* + * Since logging is being done on the JS side, we cannot log anything directly in libuv's + * work task (it works in different thread). This method allows to queue logs to output them + * at later time (at latest just before regular log is outputted, so that order is preserved) + * */ + void deferLog( const std::string& level, const std::string& message, const LogEntry::Meta& meta = LogEntry::Meta()); + void logDeferred(); + + void resetLogFunction(); + + typedef std::vector LogEntries; + LogEntries deferredLogs; + void createAPILogEntry_(Loggable::LogEntry& logEntry, const std::string& call, + const std::string& file, const std::string& function, + unsigned long line, RFC_ERROR_INFO& errorInfo, + const Loggable::LogEntry::Meta& meta); +}; + +#define LOG_API(self,call) { (self)->logAPICall((call),__FILE__,BOOST_CURRENT_FUNCTION,__LINE__,(self)->errorInfo);}while(0) +#define LOG_API_META(self,call,meta) { (self)->logAPICall((call),__FILE__,BOOST_CURRENT_FUNCTION,__LINE__,(self)->errorInfo,(meta));}while(0) +#define DEFER_LOG_API(self,call) { (self)->deferLogAPICall((call),__FILE__,BOOST_CURRENT_FUNCTION,__LINE__,(self)->errorInfo);}while(0) +#define DEFER_LOG_API_META(self,call,meta) { (self)->deferLogAPICall((call),__FILE__,BOOST_CURRENT_FUNCTION,__LINE__,(self)->errorInfo,(meta));}while(0) + + +#endif /* LOGGABLE_H_ */ diff --git a/src/current_function.hpp b/src/current_function.hpp new file mode 100644 index 0000000..cb36e35 --- /dev/null +++ b/src/current_function.hpp @@ -0,0 +1,68 @@ +#ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED +#define BOOST_CURRENT_FUNCTION_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/current_function.hpp - BOOST_CURRENT_FUNCTION +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// http://www.boost.org/libs/utility/current_function.html +// + +namespace boost +{ + +namespace detail +{ + +inline void current_function_helper() +{ + +#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) || defined(__ghs__) + +# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__ + +#elif defined(__DMC__) && (__DMC__ >= 0x810) + +# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__ + +#elif defined(__FUNCSIG__) + +# define BOOST_CURRENT_FUNCTION __FUNCSIG__ + +#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500)) + +# define BOOST_CURRENT_FUNCTION __FUNCTION__ + +#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550) + +# define BOOST_CURRENT_FUNCTION __FUNC__ + +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901) + +# define BOOST_CURRENT_FUNCTION __func__ + +#else + +# define BOOST_CURRENT_FUNCTION "(unknown)" + +#endif + +} + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED +