void WorkerBinding::CreateWorker(const ValueList& args, SharedValue result) { if (args.size()!=2) { throw ValueException::FromString("invalid argument specified"); } bool is_function = args.at(1)->ToBool(); std::string code; Logger *logger = Logger::Get("Worker"); if (is_function) { // convert the function to a string block code = "("; code += args.at(0)->ToString(); code += ")()"; } else { // this is a path -- probably should verify that this is relative and not an absolute URL to remote SharedKMethod appURLToPath = global->GetNS("App.appURLToPath")->ToMethod(); ValueList a; a.push_back(args.at(0)); SharedValue result = appURLToPath->Call(a); const char *path = result->ToString(); logger->Debug("worker file path = %s",path); std::ios::openmode flags = std::ios::in; Poco::FileInputStream *fis = new Poco::FileInputStream(path,flags); std::stringstream ostr; char buf[8096]; int count = 0; while(!fis->eof()) { fis->read((char*)&buf,8095); std::streamsize len = fis->gcount(); if (len>0) { buf[len]='\0'; count+=len; ostr << buf; } else break; } fis->close(); code = std::string(ostr.str()); } logger->Debug("Worker script code = %s", code.c_str()); SharedKObject worker = new Worker(host,global,code); result->SetObject(worker); }
int main(int argc, char ** argv) { try { Appender errApp("Error.log", Level::ERROR, false); Appender debugApp("Debug.log", Level::DEBUG, true); Appender * dynApp = new Appender("Dynamic.log", Level::INFO, false); try { Appender badApp("Error.log", Level::ERROR, false); } catch ( exception & e ) { cout << "Correctly failed to open two appenders to one file." << endl; } logger1.Error("This should show up for all Appenders"); delete dynApp; logger1.Error("This should only be in Error and Debug"); logger2.Info("This should only be in debug"); Appender::enableConsole(Level::INFO); logger1.Info("This should show up on the console."); logger2.Debug("This should only be in the debug log"); fLogger.Info("Entering Foo"); foo(); fLogger.Info("Exiting foo."); Appender::enableConsole(Level::DEBUG); logger2.Debug("This will be in the console."); logger1.fDebug("%s - %i", "format test", 42); Appender::disableConsole(); logger2.Debug("This will not be on the console."); logger1.Error("Exiting"); } catch ( exception & e ) { cerr << "Unhandled exception: "; cerr << e.what() << endl; cerr << "Exiting." << endl; return 1; } return 0; }
void WorkerContext::Sleep(const ValueList &args, KValueRef result) { Logger *logger = Logger::Get("WorkerContext"); long ms = args.at(0)->ToInt(); logger->Debug("worker is sleeping for %d ms", ms); condmutex.lock(); if (condition.tryWait(condmutex, ms)) { logger->Debug("worker sleep was interrupted"); condmutex.unlock(); throw ValueException::FromString("interrupted"); return; } condmutex.unlock(); logger->Debug("worker sleep completed"); }
void WorkerContext::SendQueuedMessages() { Logger *logger = Logger::Get("WorkerContext"); logger->Debug("SendQueuedMessages called"); SharedValue onmessage = worker->Get("onmessage"); Poco::ScopedLock<Poco::Mutex> lock(mutex); if (onmessage->IsMethod()) { if (messages.size()>0) { std::list<SharedValue>::iterator i = messages.begin(); while(i!=messages.end()) { SharedValue v = (*i++); ValueList _args; string name = "worker.message"; AutoPtr<KEventObject> target = this; this->duplicate(); AutoPtr<Event> event = new Event(target, name); event->Set("message", v); _args.push_back(Value::NewObject(event)); host->InvokeMethodOnMainThread(onmessage->ToMethod(),_args,false); } messages.clear(); } } }
void test_Logger(){ { Logger lg; lg.Log(LOG_WARN, "Test logger"); lg.Debug("logger debug"); lg.Fatal("Fatal test [%s] [%d]", "args", 1); lg.SetHandler("test_log"); lg.SetLevel(LOG_ALL); lg.Info("info test [%s]", "args"); Logger* lg_ptr = Logger::GetLogger("test"); lg_ptr->Error("You can see me in file test"); Logger* lg_ptr2 = Logger::GetLogger(); lg_ptr2->Error("You can see me in console"); } { LOG(LOG_DEBUG, "log debug info: %s", "Hello"); } { SetLogger(LOG_WARN, "test_logger.log"); LOG(LOG_DEBUG, "DEBUG NO SEE, you should not see this"); LOG(LOG_ERROR, "ERROR, you should know"); LOG(LOG_WARN, "WARN, you should see this"); } { SetLogger(LOG_ALL); LOG(LOG_DEBUG, "DEBUG [%d], you should see this", LOG_DEBUG); LOG(LOG_WARN, "LOG_WARN [%d], you should see this", LOG_WARN); LOG(LOG_ERROR, "LOG_ERROR [%d], you should see this", LOG_ERROR); LOG(LOG_FATAL, "LOG_FATAL [%d], you should see this", LOG_FATAL); } }
void AsyncCopy::Copy(Poco::Path &src, Poco::Path &dest) { Logger* logger = Logger::Get("Filesystem.AsyncCopy"); std::string srcString = src.toString(); std::string destString = dest.toString(); Poco::File from(srcString); bool isLink = from.isLink(); logger->Debug("file=%s dest=%s link=%i", srcString.c_str(), destString.c_str(), isLink); #ifndef OS_WIN32 if (isLink) { char linkPath[PATH_MAX]; ssize_t length = readlink(from.path().c_str(), linkPath, PATH_MAX); linkPath[length] = '\0'; std::string newPath (dest.toString()); const char *destPath = newPath.c_str(); unlink(destPath); // unlink it first, fails in some OS if already there int result = symlink(linkPath, destPath); if (result == -1) { std::string err = "Copy failed: Could not make symlink ("; err.append(destPath); err.append(") from "); err.append(linkPath); err.append(" : "); err.append(strerror(errno)); throw kroll::ValueException::FromString(err); } } #endif if (!isLink && from.isDirectory()) { Poco::File d(dest.toString()); if (!d.exists()) { d.createDirectories(); } std::vector<std::string> files; from.list(files); std::vector<std::string>::iterator i = files.begin(); while(i!=files.end()) { std::string fn = (*i++); Poco::Path sp(kroll::FileUtils::Join(src.toString().c_str(),fn.c_str(),NULL)); Poco::Path dp(kroll::FileUtils::Join(dest.toString().c_str(),fn.c_str(),NULL)); this->Copy(sp,dp); } } else if (!isLink) { // in this case it's a regular file Poco::File s(src.toString()); s.copyTo(dest.toString().c_str()); } }
void Worker::Terminate(const ValueList& args, SharedValue result) { Logger *logger = Logger::Get("Worker"); logger->Debug("Terminate called"); Poco::ScopedLock<Poco::Mutex> lock(mutex); if (!stopped) { stopped=true; this->condition.signal(); } }
void WorkerContext::PostMessage(const ValueList &args, KValueRef result) { Logger *logger = Logger::Get("WorkerContext"); KValueRef message(args.at(0)); logger->Debug("PostMessage called with %s", message->DisplayString()->c_str()); { Poco::ScopedLock<Poco::Mutex> lock(mutex); messages.push_back(message); } SendQueuedMessages(); }
bool FileStream::Open(FileStreamMode mode, bool binary, bool append) { // close the prev stream if needed this->Close(); try { std::ios::openmode flags = (std::ios::openmode) 0; bool output = false; if (binary) { flags|=std::ios::binary; } if (mode == MODE_APPEND) { flags|=std::ios::out|std::ios::app; output = true; } else if (mode == MODE_WRITE) { flags |= std::ios::out|std::ios::trunc; output = true; } else if (mode == MODE_READ) { flags |= std::ios::in; } #ifdef DEBUG Logger* logger = Logger::Get("Filesystem.FileStream"); logger->Debug("FILE OPEN FLAGS = %d, binary=%d, mode=%d, append=%d",flags,binary,(int)mode,append); #endif if (output) { this->stream = new Poco::FileOutputStream(this->filename,flags); #ifndef OS_WIN32 chmod(this->filename.c_str(),S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); #endif } else { this->stream = new Poco::FileInputStream(this->filename,flags); } return true; } catch (Poco::Exception& exc) { Logger* logger = Logger::Get("Filesystem.FileStream"); logger->Error("Error in open. Exception: %s",exc.displayText().c_str()); throw ValueException::FromString(exc.displayText()); } }
void Worker::Start(const ValueList& args, SharedValue result) { Logger *logger = Logger::Get("Worker"); logger->Debug("Start called"); if (!stopped) { throw ValueException::FromString("Worker already started"); return; } this->context = new WorkerContext(host,this); this->adapter = new Poco::RunnableAdapter<Worker>(*this, &Worker::Run); this->thread.start(*adapter); }
void WorkerContext::ImportScripts(const ValueList &args, KValueRef result) { Logger *logger = Logger::Get("WorkerContext"); AutoPtr<Worker> _worker = worker.cast<Worker>(); JSGlobalContextRef context = KJSUtil::GetGlobalContext(_worker->GetGlobalObject()); for (size_t c = 0; c < args.size(); c++) { std::string path(URLUtils::URLToPath(args.GetString(c))); logger->Debug("Attempting to import worker script = %s", path.c_str()); KJSUtil::EvaluateFile(context, path.c_str()); } }
void WorkerContext::PostMessage(const ValueList &args, SharedValue result) { Logger *logger = Logger::Get("WorkerContext"); logger->Debug("PostMessage called"); try { Poco::ScopedLock<Poco::Mutex> lock(mutex); messages.push_back(args.at(0)); SendQueuedMessages(); } catch(std::exception &e) { logger->Error("Error calling onmessage for worker. Error = %s",e.what()); } }
void WorkerContext::ImportScripts(const ValueList &args, SharedValue result) { Logger *logger = Logger::Get("WorkerContext"); SharedKMethod appURLToPath = host->GetGlobalObject()->GetNS("App.appURLToPath")->ToMethod(); AutoPtr<Worker> _worker = worker.cast<Worker>(); JSGlobalContextRef context = KJSUtil::GetGlobalContext(_worker->GetGlobalObject()); for (size_t c = 0; c < args.size(); c++) { // first convert the path to a full URL file path ValueList a; a.push_back(args.at(c)); SharedValue result = appURLToPath->Call(a); const char *path = result->ToString(); logger->Debug("attempting to import worker script = %s",path); KJSUtil::EvaluateFile(context, (char*)path); } }
void WorkerContext::SendQueuedMessages() { Logger *logger = Logger::Get("WorkerContext"); logger->Debug("SendQueuedMessages called"); if (messages.size() <= 0) return; KValueRef onMessageValue = worker->Get("onmessage"); if (!onMessageValue->IsMethod()) return; KMethodRef onMessage(onMessageValue->ToMethod()); Poco::ScopedLock<Poco::Mutex> lock(mutex); std::list<KValueRef>::iterator i = messages.begin(); while (i != messages.end()) { KValueRef message(*i++); this->CallOnMessageCallback(onMessage, message); } messages.clear(); }
void AsyncCopy::Run(void* data) { START_KROLL_THREAD; Logger* logger = Logger::Get("Filesystem.AsyncCopy"); AsyncCopy* ac = static_cast<AsyncCopy*>(data); std::vector<std::string>::iterator iter = ac->files.begin(); Poco::Path to(ac->destination); Poco::File tof(to.toString()); logger->Debug("Job started: dest=%s, count=%i", ac->destination.c_str(), ac->files.size()); if (!tof.exists()) { tof.createDirectory(); } int c = 0; while (!ac->stopped && iter!=ac->files.end()) { bool err_copy = false; std::string file = (*iter++); c++; logger->Debug("File: path=%s, count=%i\n", file.c_str(), c); try { Poco::Path from(file); Poco::File f(file); if (f.isDirectory()) { ac->Copy(from,to); } else { Poco::Path dest(to,from.getFileName()); ac->Copy(from,dest); } logger->Debug("File copied"); KValueRef value = Value::NewString(file); ValueList args; args.push_back(value); args.push_back(Value::NewInt(c)); args.push_back(Value::NewInt(ac->files.size())); args.push_back(Value::NewBool(true)); RunOnMainThread(ac->callback, args, false); logger->Debug("Callback executed"); } catch (ValueException &ex) { err_copy = true; SharedString ss = ex.DisplayString(); logger->Error(std::string("Error: ") + *ss + " for file: " + file); } catch (Poco::Exception &ex) { err_copy = true; logger->Error(std::string("Error: ") + ex.displayText() + " for file: " + file); } catch (std::exception &ex) { err_copy = true; logger->Error(std::string("Error: ") + ex.what() + " for file: " + file); } catch (...) { err_copy = true; logger->Error(std::string("Unknown error during copy: ") + file); } try { if(err_copy) { KValueRef value = Value::NewString(file); ValueList args; args.push_back(value); args.push_back(Value::NewInt(c)); args.push_back(Value::NewInt(ac->files.size())); args.push_back(Value::NewBool(false)); RunOnMainThread(ac->callback, args, false); } } catch(...) { err_copy = true; logger->Error(std::string("Unknown error during copy: ") + file); } } ac->Set("running",Value::NewBool(false)); ac->stopped = true; logger->Debug(std::string("Job finished")); END_KROLL_THREAD; }
void Worker::Run() { Logger *logger = Logger::Get("Worker"); bool error = false; JSGlobalContextRef context = NULL; try { // create a new global context this->global_object = KJSUtil::CreateNewGlobalContext(this->host); // bind the worker context properties KJSUtil::BindProperties(global_object,this->context); // evaluate the script context = KJSUtil::GetGlobalContext(global_object); KJSUtil::Evaluate(context, (char*)this->code.c_str()); } catch(std::exception &e) { error = true; logger->Error("Error loading worker. Error = %s", e.what()); SharedValue onerror = this->Get("onerror"); if (onerror->IsMethod()) { SharedKMethod method = onerror->ToMethod(); ValueList args; args.push_back(Value::NewString(e.what())); this->host->InvokeMethodOnMainThread(method,args,false); } } if (!error) { // run this thread and wait for pending messages or to be // woken up to stop for(;;) { bool wait = true; { Poco::ScopedLock<Poco::Mutex> lock(mutex); if (this->messages.size()>0) { wait=false; } } if (wait) { condmutex.lock(); // will unlock in wait condition.wait(condmutex); } // check to see if the worker wants to receive messages - we do this // each time since they could define at any time SharedValue mv = KJSUtil::GetProperty(global_object,"onmessage"); if (mv->IsMethod()) { // we have to make a copy since calling the onmessage could be re-entrant // which would cause the postMessage to deadlock. we hold the lock to // make a copy of the contents of the list and then iterate w/o lock std::list<SharedValue> copy; { // lock inside block only to make copy Poco::ScopedLock<Poco::Mutex> lock(mutex); if (this->messages.size()>0) { std::list<SharedValue>::iterator i = this->messages.begin(); while (i!=this->messages.end()) { SharedValue message = (*i++); copy.push_back(message); } this->messages.clear(); } } if (copy.size()>0) { SharedKMethod onmessage = mv->ToMethod(); std::list<SharedValue>::iterator i = copy.begin(); while(i!=copy.end()) { SharedValue message = (*i++); try { ValueList args; string name = "worker.message"; AutoPtr<KEventObject> target = this; this->duplicate(); AutoPtr<Event> event = new Event(target, name); event->Set("message", message); args.push_back(Value::NewObject(event)); host->InvokeMethodOnMainThread(onmessage,args,false); } catch(std::exception &e) { logger->Error("Error dispatching worker message, exception = %s",e.what()); } } } } if (stopped) break; } } // make sure we unregister our global so we don't leak if (global_object!=NULL) { KJSUtil::UnregisterGlobalContext(global_object); } this->global_object = NULL; this->stopped = true; logger->Debug("exiting Worker thread"); }