void MainWindow::on_toolButton_5_clicked() { Journal *j = new Journal; j->exec(); connect(j,SIGNAL(destroyed()),j,SLOT(deleteLater())); }
Incidence * pasteIncidence( Incidence *inc, const QDate &newDate, const QTime *newTime = 0 ) { if ( inc ) { inc = inc->clone(); inc->recreate(); } if ( inc && newDate.isValid() ) { if ( inc->type() == "Event" ) { Event *anEvent = static_cast<Event*>( inc ); // Calculate length of event int daysOffset = anEvent->dtStart().date().daysTo( anEvent->dtEnd().date() ); // new end date if event starts at the same time on the new day KDateTime endDate( anEvent->dtEnd() ); endDate.setDate( newDate.addDays( daysOffset ) ); KDateTime startDate( anEvent->dtStart() ); startDate.setDate( newDate ); if ( newTime ) { // additional offset for new time of day int addSecsOffset( anEvent->dtStart().time().secsTo( *newTime ) ); endDate=endDate.addSecs( addSecsOffset ); startDate.setTime( *newTime ); } anEvent->setDtStart( startDate ); anEvent->setDtEnd( endDate ); } else if ( inc->type() == "Todo" ) { Todo *anTodo = static_cast<Todo*>( inc ); KDateTime dueDate( anTodo->dtDue() ); dueDate.setDate( newDate ); if ( newTime ) { dueDate.setTime( *newTime ); } anTodo->setDtDue( dueDate ); } else if ( inc->type() == "Journal" ) { Journal *anJournal = static_cast<Journal*>( inc ); KDateTime startDate( anJournal->dtStart() ); startDate.setDate( newDate ); if ( newTime ) { startDate.setTime( *newTime ); } else { startDate.setTime( QTime( 0, 0, 0 ) ); } anJournal->setDtStart( startDate ); } else { kDebug() << "Trying to paste unknown incidence of type" << inc->type(); } } return inc; }
int main(const int argc, const char **argv) { std::stringstream usage; std::string cc = ""; // hash map for fetching options data options_map op_data; try { // process command line arguments and 'usage' should contain // the usage message. OptionParser op(argc, argv, usage); int rval = op.processOptions(op_data); if (rval == 0) { // fetch user input from the interfacing code CInterface ci; // yes means load readline support cc = ci.getUserInput(op_data["r"] == "yes"); } else if (rval == 2) { std::cout << usage.str(); return 0; } } catch (po::error & e) { std::cout << "Invalid options passed ...\n"; std::cout << usage.str(); return 1; } // add data meant to be appended to the beginning cc = op_data["a"] + "\n" + cc; // remove beginning and trailing whitespaces with custom function cc = Utility::trim(cc); // write to file only if content is not totally blank if (!cc.empty()) { Journal journal; journal.takeNote(cc); std::string dateformat = op_data["d"]; if (dateformat.begin() == dateformat.end()) { dateformat = "%d/%m/%Y-%H:%M:%S"; } journal.saveNote(dateformat); } return 0; }
void replay_write(std::ostream& stream, const Journal& journal) { stream << replay_record_type_string(ReplayRecord::Type::START) << "\n"; GameMeta meta = journal.meta(); stream << replay_record_type_string(ReplayRecord::Type::META) << " " << meta.players << " " << meta.seed << " " << meta.winner << "\n"; for(const auto& id : journal.inputs()) { stream << replay_record_type_string(ReplayRecord::Type::INPUT) << " " << id.input.to_string() << "\n"; } }
void Internal::action() const { // Do an internal command ostringstream msg; doCommand(command.c_str(), msg); DEBUG cerr << "Internal::action for '" << command << "' returned '" << msg.str() << "''n"; if (msg.str().size()) journal.add(new Message(msg.str())); }
void Journal::rotate() { assert( !dbMutex.atLeastReadLocked() ); durThreadMain.assertWithin(); scoped_lock lk(_curLogFileMutex); if ( inShutdown() ) return; j.updateLSNFile(); if( _curLogFile && _written < DataLimit ) return; if( _curLogFile ) { closeCurrentJournalFile(); removeUnneededJournalFiles(); } try { Timer t; _open(); int ms = t.millis(); if( ms >= 200 ) { log() << "DR101 latency warning on journal file open " << ms << "ms" << endl; } } catch(std::exception& e) { log() << "warning exception opening journal file " << e.what() << endl; throw; } }
static void resetLogBuffer(/*out*/JSectHeader& h, AlignedBuilder& bb) { bb.reset(); h.setSectionLen(0xffffffff); // total length, will fill in later h.seqNumber = getLastDataFileFlushTime(); h.fileId = j.curFileId(); }
void PREPLOGBUFFER(/*out*/ JSectHeader& h, AlignedBuilder& ab) { assertLockedForCommitting(); Timer t; j.assureLogFileOpen(); // so fileId is set _PREPLOGBUFFER(h, ab); stats.curr->_prepLogBufferMicros += t.micros(); }
void Command::action() const { // Perform a command and write the result as Message // Upper limit of 1024 bytes for response. If it's longer, you should write it to // a file and retrieve the file // Note that stderr is lost unless you append 2>&1 to the command. // If exit status is 0, taken as INFO cmd OUTPUT data, else treated as // WARN cmd STATUS xx OUTPUT data // Wierd stuff. The pclose will fail with errno = no child processes as the catcher function // has caught and discarded the signal. Hence need to suspend the Catcher function during // this one. Hope it does not have unintended consequences. string str(cmd); subst(str); DEBUG fprintf(stderr, "Command::action executing command '%s'\n", str.c_str()); FILE * fp = popen(str.c_str(), "r"); if (!fp) { string msg = "event WARN Failed to execute command: "; journal.add(new Message(msg)); } char buf[1024]; int retval; signal(SIGCHLD, SIG_DFL); // This can block if ((retval = fread(&buf[0], 1, 1023, fp)) == -1) { ostringstream omsg; omsg << "event WARN Command '" << cmd << "' failed to execute, errno " << errno; journal.add(new Message(omsg.str())); return; } buf[retval] = '\0'; if (retval == 1023) { // there's more to come - dump it while (retval = fread(&buf[0], 1, 1023, fp)) DEBUG cerr << "Ditching another " << retval << " bytes\n"; } ostringstream response; retval = pclose(fp); signal(SIGCHLD, catcher); response << "event INFO Command '" << cmd << "' STATUS " << retval; response << " OUTPUT\n" << buf; DETAILDEBUG if (errno) perror("pclose"); DEBUG cerr << "Command '" << cmd << ": " << response.str() << "'\n"; journal.add(new Message(response.str())); }
void ItemManage::addNewItem() { string type; do { cout << "Type(B-Book,J-Journal):"; getline(cin,type,'\n'); if (type == "B") { Book newItem; cin>>newItem; newItem.setType("B"); nptr newNode = new LibraryItemNode(&newItem); if(head == NULL) { head = newNode; tail = newNode; } else { tail->setNext(newNode); tail = newNode; } } else if(type == "J") { Journal newItem; cin>>newItem; newItem.setType("J"); nptr newNode = new LibraryItemNode(&newItem); if(head == NULL) { head = newNode; tail = newNode; } else { tail->setNext(newNode); tail = newNode; } }
void ComparisonVisitorTest::testJournalComparison() { const QString summary = QLatin1String( "Testing comparison" ); const QString desc = QLatin1String( "Testing ComparisonVisitor" ); const KDateTime now = KDateTime::currentUtcDateTime(); Journal reference; reference.setSummary( summary ); reference.setDescription( desc ); reference.setDtStart( now ); // create a copy of the reference incidence Journal journal( reference ); IncidenceBase *baseReference = &reference; IncidenceBase *baseIncidence = &journal; QVERIFY( mComparator.compare( baseIncidence, baseReference ) ); // change a property of Incidence (Journal has no new properties) (but not of IncidenceBase) journal.setDescription( summary ); QVERIFY( !mComparator.compare( baseIncidence, baseReference ) ); }
void DataUpload::action() const { // Make the xml files to upload string name("/tmp/data."); time_t now = time(0); // struct tm * mytm = localtime(&now); // char buf[20]; // Implement purge_to: journal.purge(var.purgeTo); char buf[20]; if (conf.getSiteId() < 0) // Treat negative siteid as MAC address instead strcpy(buf, getmac()); else { snprintf(buf, sizeof(buf), "%d", conf.getSiteId()); } name += buf; name += ".xml"; DEBUG cerr << "DataUpload::action Got name as " << name << "\n"; journal.xml(name.c_str()); queue.add(new DataUpload(timeMod(var.dataUpload, 1))); var.lastUpload = now; // Call send.sh string command(conf.serverComms); command += " "; command += buf; command +=" "; command += conf.serverUrl; command += " &"; // background it DEBUG cerr << "Invoking comms: '" << command; int retval = system(command.c_str()); DEBUG cerr << "' Retval from system() is " << retval << endl; // Do a replace in case there is still a GetResponse in the queue queue.replace<GetResponse>(new GetResponse(now + 30)); }
void journalCleanup() { if( testIntent ) return; if( !okToCleanUp ) return; if( !j.tryToCloseCurJournalFile() ) { return; } try { removeJournalFiles(); } catch(std::exception& e) { log() << "error couldn't remove journal file during shutdown " << e.what() << endl; } }
/** assure journal/ dir exists. throws. call during startup. */ void journalMakeDir() { j.init(); filesystem::path p = getJournalDir(); j.dir = p.string(); log() << "journal dir=" << j.dir << endl; if( !exists(j.dir) ) { try { create_directory(j.dir); } catch(std::exception& e) { log() << "error creating directory " << j.dir << ' ' << e.what() << endl; throw; } } }
void journalCleanup() { if( !j.tryToCloseLogFile() ) { return; } for ( boost::filesystem::directory_iterator i( j.dir ); i != boost::filesystem::directory_iterator(); ++i ) { string fileName = boost::filesystem::path(*i).leaf(); if( str::startsWith(fileName, "j._") ) { try { boost::filesystem::remove(*i); } catch(std::exception& e) { log() << "couldn't remove " << fileName << ' ' << e.what() << endl; } } } }
void preallocateFiles() { if (! (cmdLine.durOptions & CmdLine::DurNoCheckSpace)) checkFreeSpace(); if( exists(preallocPath(0)) || // if enabled previously, keep using exists(preallocPath(1)) || ( cmdLine.preallocj && preallocateIsFaster() ) ) { usingPreallocate = true; try { _preallocateFiles(); } catch(...) { log() << "warning caught exception in preallocateFiles, continuing" << endl; } } j.open(); }
void Journal::rotate() { if( _lf && written < DataLimit ) return; scoped_lock lk(_lfMutex); if( _lf && written < DataLimit ) return; if( _lf ) { delete _lf; // close _lf = 0; written = 0; /* remove an older journal file. */ if( nextFileNumber >= 3 ) { unsigned fn = nextFileNumber - 3; // we do unlinks asynchronously - unless they are falling behind. // (unlinking big files can be slow on some operating systems; we don't want to stop world) path p = j.getFilePathFor(fn); if( !j.toUnlink.tryPut(p) ) { /* DR___ for durability error and warning codes Compare to RS___ for replica sets */ log() << "DR100 latency warning on journal unlink" << endl; Timer t; j.toUnlink.put(p); log() << "toUnlink.put() " << t.millis() << "ms" << endl; } } } try { Timer t; open(); int ms = t.millis(); if( ms >= 200 ) { log() << "DR101 latency warning on journal file open " << ms << "ms" << endl; } } catch(std::exception& e) { log() << "warning exception opening journal file " << e.what() << endl; } }
/** we will build an output buffer ourself and then use O_DIRECT we could be in read lock for this caller handles locking @return partially populated sectheader and _ab set */ static void _PREPLOGBUFFER(JSectHeader& h, AlignedBuilder& bb) { // Add the JSectHeader // Invalidate the total length, we will fill it in later. h.setSectionLen(0xffffffff); h.seqNumber = getLastDataFileFlushTime(); h.fileId = j.curFileId(); // Ops other than basic writes (DurOp's) go first const std::vector<std::shared_ptr<DurOp>>& durOps = commitJob.ops(); for (std::vector<std::shared_ptr<DurOp>>::const_iterator i = durOps.begin(); i != durOps.end(); i++) { (*i)->serialize(bb); } // Write intents const std::vector<WriteIntent>& intents = commitJob.getIntentsSorted(); if (!intents.empty()) { prepBasicWrites(bb, intents); } }
void PREPLOGBUFFER(/*out*/ JSectHeader& outHeader, AlignedBuilder& outBuffer) { Timer t; j.assureLogFileOpen(); // so fileId is set _PREPLOGBUFFER(outHeader, outBuffer); stats.curr()->_prepLogBufferMicros += t.micros(); }
namespace dur { BOOST_STATIC_ASSERT( sizeof(JHeader) == 8192 ); BOOST_STATIC_ASSERT( sizeof(JSectHeader) == 8 ); BOOST_STATIC_ASSERT( sizeof(JSectFooter) == 20 ); BOOST_STATIC_ASSERT( sizeof(JEntry) == 8 ); void journalingFailure(const char *msg) { /** todo: (1) don't log too much (2) make an indicator in the journal dir that something bad happened. (2b) refuse to do a[ recovery startup if that is there without manual override. */ log() << "journaling error " << msg << endl; } struct Journal { static const unsigned long long DataLimit = 1 * 1024 * 1024 * 1024; unsigned long long written; unsigned nextFileNumber; string dir; MVar<path> &toUnlink; Journal() : toUnlink(*(new MVar<path>)), /* freeing MVar at program termination would be problematic */ _lfMutex("lfMutex") { written = 0; nextFileNumber = 0; _lf = 0; } void open(); void rotate(); void journal(const AlignedBuilder& b); path getFilePathFor(int filenumber) const; bool tryToCloseLogFile() { mutex::try_lock lk(_lfMutex, 2000); if( lk.ok ) { delete _lf; _lf = 0; } return lk.ok; } private: LogFile *_lf; mutex _lfMutex; // lock when using _lf. }; static Journal j; path Journal::getFilePathFor(int filenumber) const { filesystem::path p(dir); p /= (str::stream() << "j._" << filenumber); return p; } void journalCleanup() { if( !j.tryToCloseLogFile() ) { return; } for ( boost::filesystem::directory_iterator i( j.dir ); i != boost::filesystem::directory_iterator(); ++i ) { string fileName = boost::filesystem::path(*i).leaf(); if( str::startsWith(fileName, "j._") ) { try { boost::filesystem::remove(*i); } catch(std::exception& e) { log() << "couldn't remove " << fileName << ' ' << e.what() << endl; } } } } /** assure journal/ dir exists. throws */ void journalMakeDir() { filesystem::path p(dbpath); p /= "journal"; j.dir = p.string(); if( !exists(j.dir) ) { try { create_directory(j.dir); } catch(std::exception& e) { log() << "error creating directory " << j.dir << ' ' << e.what() << endl; throw; } } } /* threading: only durThread() calls this, thus safe. */ void Journal::open() { mutex::scoped_lock lk(_lfMutex); assert( _lf == 0 ); string fname = getFilePathFor(nextFileNumber).string(); _lf = new LogFile(fname); nextFileNumber++; { JHeader h(fname); AlignedBuilder b(8192); b.appendStruct(h); _lf->synchronousAppend(b.buf(), b.len()); } } void unlinkThread() { Client::initThread("unlink"); while( 1 ) { path p = j.toUnlink.take(); try { remove(p); } catch(std::exception& e) { log() << "error unlink of journal file " << p.string() << " failed " << e.what() << endl; } } } /** check if time to rotate files. assure a file is open. done separately from the journal() call as we can do this part outside of lock. thread: durThread() */ void journalRotate() { j.rotate(); } void Journal::rotate() { if( _lf && written < DataLimit ) return; scoped_lock lk(_lfMutex); if( _lf && written < DataLimit ) return; if( _lf ) { delete _lf; // close _lf = 0; written = 0; /* remove an older journal file. */ if( nextFileNumber >= 3 ) { unsigned fn = nextFileNumber - 3; // we do unlinks asynchronously - unless they are falling behind. // (unlinking big files can be slow on some operating systems; we don't want to stop world) path p = j.getFilePathFor(fn); if( !j.toUnlink.tryPut(p) ) { /* DR___ for durability error and warning codes Compare to RS___ for replica sets */ log() << "DR100 latency warning on journal unlink" << endl; Timer t; j.toUnlink.put(p); log() << "toUnlink.put() " << t.millis() << "ms" << endl; } } } try { Timer t; open(); int ms = t.millis(); if( ms >= 200 ) { log() << "DR101 latency warning on journal file open " << ms << "ms" << endl; } } catch(std::exception& e) { log() << "warning exception opening journal file " << e.what() << endl; } } /** write to journal thread: durThread() */ void journal(const AlignedBuilder& b) { j.journal(b); } void Journal::journal(const AlignedBuilder& b) { try { mutex::scoped_lock lk(_lfMutex); if( _lf == 0 ) open(); written += b.len(); _lf->synchronousAppend((void *) b.buf(), b.len()); } catch(std::exception& e) { log() << "warning exception in dur::journal " << e.what() << endl; } } }
/** write to journal thread: durThread() */ void journal(const AlignedBuilder& b) { j.journal(b); }
void journalCleanup() { j.cleanup(); }
namespace dur { extern Journal j; RelativePath local = RelativePath::fromRelativePath("local"); static MongoMMF* findMMF_inlock(void *ptr, size_t &ofs) { MongoMMF *f = privateViews.find_inlock(ptr, ofs); if( f == 0 ) { error() << "findMMF_inlock failed " << privateViews.numberOfViews_inlock() << endl; printStackTrace(); // we want a stack trace and the assert below didn't print a trace once in the real world - not sure why stringstream ss; ss << "view pointer cannot be resolved " << hex << (size_t) ptr; journalingFailure(ss.str().c_str()); // asserts, which then abends } return f; } /** put the basic write operation into the buffer (bb) to be journaled */ static void prepBasicWrite_inlock(AlignedBuilder&bb, const WriteIntent *i, RelativePath& lastDbPath) { size_t ofs = 1; MongoMMF *mmf = findMMF_inlock(i->start(), /*out*/ofs); if( unlikely(!mmf->willNeedRemap()) ) { // tag this mmf as needed a remap of its private view later. // usually it will already be dirty/already set, so we do the if above first // to avoid possibility of cpu cache line contention mmf->willNeedRemap() = true; } // since we have already looked up the mmf, we go ahead and remember the write view location // so we don't have to find the MongoMMF again later in WRITETODATAFILES() // // this was for WRITETODATAFILES_Impl2 so commented out now // /* dassert( i->w_ptr == 0 ); i->w_ptr = ((char*)mmf->view_write()) + ofs; */ JEntry e; e.len = min(i->length(), (unsigned)(mmf->length() - ofs)); //dont write past end of file assert( ofs <= 0x80000000 ); e.ofs = (unsigned) ofs; e.setFileNo( mmf->fileSuffixNo() ); if( mmf->relativePath() == local ) { e.setLocalDbContextBit(); } else if( mmf->relativePath() != lastDbPath ) { lastDbPath = mmf->relativePath(); JDbContext c; bb.appendStruct(c); bb.appendStr(lastDbPath.toString()); } bb.appendStruct(e); #if defined(_EXPERIMENTAL) i->ofsInJournalBuffer = bb.len(); #endif bb.appendBuf(i->start(), e.len); if (unlikely(e.len != (unsigned)i->length())) { log() << "journal info splitting prepBasicWrite at boundary" << endl; // This only happens if we write to the last byte in a file and // the fist byte in another file that is mapped adjacently. I // think most OSs leave at least a one page gap between // mappings, but better to be safe. WriteIntent next ((char*)i->start() + e.len, i->length() - e.len); prepBasicWrite_inlock(bb, &next, lastDbPath); } } void assertNothingSpooled(); /** basic write ops / write intents. note there is no particular order to these : if we have two writes to the same location during the group commit interval, it is likely (although not assured) that it is journaled here once. */ static void prepBasicWrites(AlignedBuilder& bb) { scoped_lock lk(privateViews._mutex()); // each time events switch to a different database we journal a JDbContext // switches will be rare as we sort by memory location first and we batch commit. RelativePath lastDbPath; assertNothingSpooled(); const vector<WriteIntent>& _intents = commitJob.getIntentsSorted(); assert( !_intents.empty() ); WriteIntent last; for( vector<WriteIntent>::const_iterator i = _intents.begin(); i != _intents.end(); i++ ) { if( i->start() < last.end() ) { // overlaps last.absorb(*i); } else { // discontinuous if( i != _intents.begin() ) prepBasicWrite_inlock(bb, &last, lastDbPath); last = *i; } } prepBasicWrite_inlock(bb, &last, lastDbPath); } static void resetLogBuffer(/*out*/JSectHeader& h, AlignedBuilder& bb) { bb.reset(); h.setSectionLen(0xffffffff); // total length, will fill in later h.seqNumber = getLastDataFileFlushTime(); h.fileId = j.curFileId(); } /** we will build an output buffer ourself and then use O_DIRECT we could be in read lock for this caller handles locking @return partially populated sectheader and _ab set */ static void _PREPLOGBUFFER(JSectHeader& h, AlignedBuilder& bb) { assert( cmdLine.dur ); assertLockedForCommitting(); resetLogBuffer(h, bb); // adds JSectHeader // ops other than basic writes (DurOp's) { for( vector< shared_ptr<DurOp> >::iterator i = commitJob.ops().begin(); i != commitJob.ops().end(); ++i ) { (*i)->serialize(bb); } } prepBasicWrites(bb); return; } void PREPLOGBUFFER(/*out*/ JSectHeader& h, AlignedBuilder& ab) { assertLockedForCommitting(); Timer t; j.assureLogFileOpen(); // so fileId is set _PREPLOGBUFFER(h, ab); stats.curr->_prepLogBufferMicros += t.micros(); } }
namespace dur { BOOST_STATIC_ASSERT( sizeof(JHeader) == 8192 ); BOOST_STATIC_ASSERT( sizeof(JSectHeader) == 12 ); BOOST_STATIC_ASSERT( sizeof(JSectFooter) == 32 ); BOOST_STATIC_ASSERT( sizeof(JEntry) == 12 ); BOOST_STATIC_ASSERT( sizeof(LSNFile) == 88 ); filesystem::path getJournalDir() { filesystem::path p(dbpath); p /= "journal"; return p; } path lsnPath() { return getJournalDir()/"lsn"; } extern CodeBlock durThreadMain; /** this should be called when something really bad happens so that we can flag appropriately */ void journalingFailure(const char *msg) { /** todo: (1) don't log too much (2) make an indicator in the journal dir that something bad happened. (2b) refuse to do a recovery startup if that is there without manual override. */ log() << "journaling error " << msg << endl; assert(false); } JHeader::JHeader(string fname) { magic[0] = 'j'; magic[1] = '\n'; _version = CurrentVersion; memset(ts, 0, sizeof(ts)); strncpy(ts, time_t_to_String_short(time(0)).c_str(), sizeof(ts)-1); memset(dbpath, 0, sizeof(dbpath)); strncpy(dbpath, fname.c_str(), sizeof(dbpath)-1); memset(reserved3, 0, sizeof(reserved3)); txt2[0] = txt2[1] = '\n'; n1 = n2 = n3 = n4 = '\n'; } // class Journal Journal j; const unsigned long long LsnShutdownSentinel = ~((unsigned long long)0); Journal::Journal() : _curLogFileMutex("JournalLfMutex") { _written = 0; _nextFileNumber = 0; _curLogFile = 0; _preFlushTime = 0; _lastFlushTime = 0; _writeToLSNNeeded = false; } path Journal::getFilePathFor(int filenumber) const { filesystem::path p(dir); p /= string(str::stream() << "j._" << filenumber); return p; } /** never throws @return true if journal dir is not empty */ bool haveJournalFiles() { try { for ( boost::filesystem::directory_iterator i( getJournalDir() ); i != boost::filesystem::directory_iterator(); ++i ) { string fileName = boost::filesystem::path(*i).leaf(); if( str::startsWith(fileName, "j._") ) return true; } } catch(...) { } return false; } /** throws */ void removeJournalFiles() { log() << "removeJournalFiles" << endl; try { for ( boost::filesystem::directory_iterator i( getJournalDir() ); i != boost::filesystem::directory_iterator(); ++i ) { string fileName = boost::filesystem::path(*i).leaf(); if( str::startsWith(fileName, "j._") ) { try { boost::filesystem::remove(*i); } catch(std::exception& e) { log() << "couldn't remove " << fileName << ' ' << e.what() << endl; throw; } } } try { boost::filesystem::remove(lsnPath()); } catch(...) { log() << "couldn't remove " << lsnPath().string() << endl; throw; } } catch( std::exception& e ) { log() << "error removing journal files " << e.what() << endl; throw; } assert(!haveJournalFiles()); log(1) << "removeJournalFiles end" << endl; } /** at clean shutdown */ bool okToCleanUp = false; // successful recovery would set this to true void Journal::cleanup() { if( !okToCleanUp ) return; try { scoped_lock lk(_curLogFileMutex); closeCurrentJournalFile(); removeJournalFiles(); } catch(std::exception& e) { log() << "error couldn't remove journal file during shutdown " << e.what() << endl; throw; } } void journalCleanup() { j.cleanup(); } /** assure journal/ dir exists. throws. call during startup. */ void journalMakeDir() { j.init(); filesystem::path p = getJournalDir(); j.dir = p.string(); log() << "journal dir=" << j.dir << endl; if( !exists(j.dir) ) { try { create_directory(j.dir); } catch(std::exception& e) { log() << "error creating directory " << j.dir << ' ' << e.what() << endl; throw; } } } void Journal::_open() { assert( _curLogFile == 0 ); string fname = getFilePathFor(_nextFileNumber).string(); _curLogFile = new LogFile(fname); _nextFileNumber++; { JHeader h(fname); AlignedBuilder b(8192); b.appendStruct(h); _curLogFile->synchronousAppend(b.buf(), b.len()); } } void Journal::init() { assert( _curLogFile == 0 ); MongoFile::notifyPreFlush = preFlush; MongoFile::notifyPostFlush = postFlush; } void Journal::open() { assert( MongoFile::notifyPreFlush == preFlush ); mutex::scoped_lock lk(_curLogFileMutex); _open(); } void LSNFile::set(unsigned long long x) { memset(this, 0, sizeof(*this)); lsn = x; checkbytes = ~x; } /** logs details of the situation, and returns 0, if anything surprising in the LSNFile if something highly surprising, throws to abort */ unsigned long long LSNFile::get() { uassert(13614, "unexpected version number of lsn file in journal/ directory", ver == 0); if( ~lsn != checkbytes ) { log() << "lsnfile not valid. recovery will be from log start. lsn: " << hex << lsn << " checkbytes: " << hex << checkbytes << endl; return 0; } return lsn; } /** called during recovery (the error message text below assumes that) */ unsigned long long journalReadLSN() { if( !debug ) { // in nondebug build, for now, be conservative until more tests written, and apply the whole journal. // however we will still write the lsn file to exercise that code, and use in _DEBUG build. return 0; } if( !MemoryMappedFile::exists(lsnPath()) ) { log() << "info no lsn file in journal/ directory" << endl; return 0; } try { // os can flush as it likes. if it flushes slowly, we will just do extra work on recovery. // however, given we actually close the file when writing, that seems unlikely. LSNFile L; File f; f.open(lsnPath().string().c_str()); assert(f.is_open()); f.read(0,(char*)&L, sizeof(L)); unsigned long long lsn = L.get(); return lsn; } catch(std::exception& e) { uasserted(13611, str::stream() << "can't read lsn file in journal directory : " << e.what()); } return 0; } unsigned long long getLastDataFileFlushTime() { return j.lastFlushTime(); } /** remember "last sequence number" to speed recoveries concurrency: called by durThread only. */ void Journal::updateLSNFile() { if( !_writeToLSNNeeded ) return; durThreadMain.assertWithin(); _writeToLSNNeeded = false; try { // os can flush as it likes. if it flushes slowly, we will just do extra work on recovery. // however, given we actually close the file, that seems unlikely. File f; f.open(lsnPath().string().c_str()); if( !f.is_open() ) { // can get 0 if an i/o error log() << "warning: open of lsn file failed" << endl; return; } log() << "lsn set " << _lastFlushTime << endl; LSNFile lsnf; lsnf.set(_lastFlushTime); f.write(0, (char*)&lsnf, sizeof(lsnf)); } catch(std::exception& e) { log() << "warning: write to lsn file failed " << e.what() << endl; // keep running (ignore the error). recovery will be slow. } } void Journal::preFlush() { j._preFlushTime = Listener::getElapsedTimeMillis(); } void Journal::postFlush() { j._lastFlushTime = j._preFlushTime; j._writeToLSNNeeded = true; } // call from within _curLogFileMutex void Journal::closeCurrentJournalFile() { if (!_curLogFile) return; JFile jf; jf.filename = _curLogFile->_name; jf.lastEventTimeMs = Listener::getElapsedTimeMillis(); _oldJournalFiles.push_back(jf); delete _curLogFile; // close _curLogFile = 0; _written = 0; } /** remove older journal files. be in _curLogFileMutex but not dbMutex when calling */ void Journal::removeUnneededJournalFiles() { while( !_oldJournalFiles.empty() ) { JFile f = _oldJournalFiles.front(); if( f.lastEventTimeMs < _lastFlushTime + ExtraKeepTimeMs ) { // eligible for deletion path p( f.filename ); log() << "old journal file will be removed: " << f.filename << endl; remove(p); } else { break; } _oldJournalFiles.pop_front(); } } /** check if time to rotate files. assure a file is open. done separately from the journal() call as we can do this part outside of lock. thread: durThread() */ void journalRotate() { j.rotate(); } void Journal::rotate() { assert( !dbMutex.atLeastReadLocked() ); durThreadMain.assertWithin(); scoped_lock lk(_curLogFileMutex); if ( inShutdown() ) return; j.updateLSNFile(); if( _curLogFile && _written < DataLimit ) return; if( _curLogFile ) { closeCurrentJournalFile(); removeUnneededJournalFiles(); } try { Timer t; _open(); int ms = t.millis(); if( ms >= 200 ) { log() << "DR101 latency warning on journal file open " << ms << "ms" << endl; } } catch(std::exception& e) { log() << "warning exception opening journal file " << e.what() << endl; throw; } } /** write to journal */ void journal(const AlignedBuilder& b) { j.journal(b); } void Journal::journal(const AlignedBuilder& b) { try { mutex::scoped_lock lk(_curLogFileMutex); if( _curLogFile == 0 ) _open(); stats.curr->_journaledBytes += b.len(); _written += b.len(); _curLogFile->synchronousAppend((void *) b.buf(), b.len()); } catch(std::exception& e) { log() << "warning exception in dur::journal " << e.what() << endl; throw; } } }
unsigned long long getLastDataFileFlushTime() { return j.lastFlushTime(); }
void Sockconn::logon(int fd, const char * msg) { // Process logon. Set device number in map con[]. // 2.10 handles unit logon where controllernum is 0.0, 2.1 or similar. char typeStr[10]; enum DeviceType type; int pid, device, unit, numread, major, minor; unit = 0; numread = sscanf(msg, "logon %9s %d.%d %d %d.%d", typeStr, &major, &minor, &pid, &device, &unit); if (numread != 5 && numread != 6) { fprintf(stderr, "Logon: only got %d fields not 5 or 6 from '%s'\n", numread, msg); return; } if (device < 0 || device >= MAXDEVICES) { cerr << "Socks.login: invalid device number " << device << " in " << msg << endl; return; } type = noDevice; // ADD CONTROLLER if (strncmp(typeStr, "steca", 5) == 0) type = steca_t; else if (strncmp(typeStr, "victron", 7) == 0) type = victron_t; else if (strncmp(typeStr, "turbine", 7) == 0) type = turbine_t; else if (strncmp(typeStr, "fronius", 7) == 0) type = fronius_t; else if (strncmp(typeStr, "davis", 5) == 0) type = davis_t; else if (strncmp(typeStr, "pulse", 5) == 0) type = pulse_t; else if (strncmp(typeStr, "rico", 4) == 0) type = rico_t; else if (strncmp(typeStr, "generic", 7) == 0) type = generic_t; else if (strncmp(typeStr, "owl", 3) == 0) type = owl_t; else if (strncmp(typeStr, "soladin", 7) == 0) type = soladin_t; else if (strncmp(typeStr, "sevenseg", 8) == 0) type = sevenseg_t; else if (strncmp(typeStr, "meter", 5) == 0) type = meter_t; else if (strncmp(typeStr, "resol", 5) == 0) type = resol_t; else if (strncmp(typeStr, "sma", 3) == 0) type = sma_t; else if (strncmp(typeStr, "inverter", 8) == 0) type = inverter_t; else if (strncmp(typeStr, "thermal", 7) == 0) type = thermal_t; else if (strncmp(typeStr, "sensor", 6) == 0) type = sensor_t; else fprintf(stderr, "ERROR logon name %s not recognised", typeStr); DEBUG fprintf(stderr, "Logon: Device %d.%d (%d.%d) %s on FD %d, type %d\n", device, unit, major, minor, typeStr, fd, type); // sockconn[device].type = type; ostringstream error; // If the config is Generic, permit the logon to be different and set the conf[] appropriately if (type != conf.getType(device)) { if (conf.getType(device) == generic_t) { conf[device].type = type; // Doesn't bounds or sanity check unit index. // Units cannot have different types. current.setDevice(device, unit, type); } else { error << "event WARN logon: mismatch. Logon " << deviceStr[type] << " (" << type << ") Config " << deviceStr[conf.getType(device)] << " (" << conf.getType(device) << ")"; journal.add(new Message(error.str())); } } if (conf[device].units < unit + 1) { error << "event WARN logon: Device " << device << " (" << deviceStr[type] << ") Unit " << unit << " Only " << conf[device].units << " configured"; journal.add(new Message(error.str())); } fd2contr[fd] = device; fd2unit[fd] = unit; // Usually 0. if (unit == 0) contr2fd[device] = fd; conf[device].major = major; conf[device].minor = minor; conf[device].pid = pid; }
void GameLoop::next_screen() { if(nullptr != m_screen) m_screen->stop(); if(nullptr == m_screen) { NetworkMode mode = the_context.configuration->network_mode; if(NetworkMode::SERVER == mode) { m_server_screen = m_screen_factory.create_server(); m_screen = m_server_screen.get(); } else { if(NetworkMode::LOCAL == mode) { m_client.reset(new LocalClient()); } else { if(!the_context.configuration->server_url.has_value()) throw GameException("Client mode requires server_url configuration."); auto net_client = std::make_unique<ENetClient>(the_context.configuration->server_url->c_str(), the_context.configuration->port); // network implementation m_client.reset(new BasicClient(std::move(net_client))); } m_screen_factory.set_client(m_client.get()); // If we want to play back a replay, feed it all to the client // and let the normal timing in the game loop take care of it. auto replay_path = the_context.configuration->replay_path; if(replay_path.has_value() && !std::filesystem::is_regular_file(replay_path.value())) { Log::error("Replay not found: %s", replay_path->u8string().c_str()); replay_path.reset(); } if(replay_path.has_value()) { std::ifstream stream{replay_path.value()}; Journal journal = replay_read(stream); GameMeta meta = journal.meta(); meta.winner = NOONE; // this is currently necessary to prevent early exit m_client->send_reset(meta); m_client->game_start(); for(InputDiscovered id : journal.inputs()) { m_client->send_input(id.input); } m_game_screen = m_screen_factory.create_game(); m_screen = m_game_screen.get(); // We do not copy-save the same game again in replay mode. the_context.configuration->autorecord = false; } else { m_menu_screen = m_screen_factory.create_menu(); m_screen = m_menu_screen.get(); } } // debug //DrawPink pink_draw(m_sdl_factory, 255, 0, 255); //m_pink_screen = std::make_unique<PinkScreen>(std::move(pink_draw)); //m_screen = m_pink_screen.get(); } else if(ServerScreen* serv = dynamic_cast<ServerScreen*>(m_screen)) { m_server_screen.release(); m_screen = nullptr; } else if(MenuScreen* menu = dynamic_cast<MenuScreen*>(m_screen)) { if(MenuScreen::Result::PLAY == menu->result()) { m_client->game_start(); // create game state from meta info m_game_screen = m_screen_factory.create_game(); m_transition_screen = m_screen_factory.create_transition(*menu, *m_game_screen); m_screen = m_transition_screen.get(); } else if(MenuScreen::Result::QUIT == menu->result()) { m_menu_screen.release(); m_screen = nullptr; } } else if(GameScreen* game = dynamic_cast<GameScreen*>(m_screen)) { if(the_context.configuration->replay_path.has_value()) { // After a replay, just exit. // NOTE: if we did not, we would have to restore the autorecord config flag. m_game_screen.release(); m_screen = nullptr; } else { // Go back to menu m_menu_screen = m_screen_factory.create_menu(); m_transition_screen = m_screen_factory.create_transition(*game, *m_menu_screen); m_screen = m_transition_screen.get(); } } else if(TransitionScreen* transition = dynamic_cast<TransitionScreen*>(m_screen)) { m_screen = &transition->successor(); m_transition_screen.release(); // BUG! We keep the predecessor screen around unnecessarily. } else if(PinkScreen* pink = dynamic_cast<PinkScreen*>(m_screen)) { if(m_pink_screen.get() == pink) { DrawPink creme_draw(250, 220, 220); m_creme_screen = std::make_unique<PinkScreen>(std::move(creme_draw)); m_transition_screen = m_screen_factory.create_transition(*pink, *m_creme_screen); m_screen = m_transition_screen.get(); } else { DrawPink pink_draw(255, 0, 255); m_pink_screen = std::make_unique<PinkScreen>(std::move(pink_draw)); m_transition_screen = m_screen_factory.create_transition(*pink, *m_pink_screen); m_screen = m_transition_screen.get(); } } else { assert(false); // unknown type of m_screen } }
/** check if time to rotate files. assure a file is open. done separately from the journal() call as we can do this part outside of lock. thread: durThread() */ void journalRotate() { j.rotate(); }
void journalCleanup(bool log) { j.cleanup(log); }
void KNotesPlugin::processDropEvent( QDropEvent *event ) { const QMimeData *md = event->mimeData(); if ( KVCardDrag::canDecode( md ) ) { KABC::Addressee::List contacts; KVCardDrag::fromMimeData( md, contacts ); KABC::Addressee::List::ConstIterator it; QStringList attendees; for ( it = contacts.constBegin(); it != contacts.constEnd(); ++it ) { QString email = (*it).fullEmail(); if ( email.isEmpty() ) { attendees.append( (*it).realName() + "<>" ); } else { attendees.append( email ); } } event->accept(); static_cast<KNotesPart *>( part() )->newNote( i18nc( "@item", "Meeting" ), attendees.join( ", " ) ); return; } if ( ICalDrag::canDecode( event->mimeData() ) ) { CalendarLocal cal( KSystemTimeZones::local() ); if ( ICalDrag::fromMimeData( event->mimeData(), &cal ) ) { Journal::List journals = cal.journals(); if ( !journals.isEmpty() ) { event->accept(); Journal *j = journals.first(); static_cast<KNotesPart *>( part() )-> newNote( i18nc( "@item", "Note: %1", j->summary() ), j->description() ); return; } // else fall through to text decoding } } if ( md->hasText() ) { static_cast<KNotesPart *>( part() )->newNote( i18nc( "@item", "New Note" ), md->text() ); return; } if ( MailList::canDecode( md ) ) { MailList mails = MailList::fromMimeData( md ); event->accept(); if ( mails.count() != 1 ) { KMessageBox::sorry( core(), i18nc( "@info", "Dropping multiple mails is not supported." ) ); } else { MailSummary mail = mails.first(); QString txt = i18nc( "@item", "From: %1\nTo: %2\nSubject: %3", mail.from(), mail.to(), mail.subject() ); static_cast<KNotesPart *>( part() )->newNote( i18nc( "@item", "Mail: %1", mail.subject() ), txt ); } return; } kWarning() << QString( "Cannot handle drop events of type '%1'." ).arg( event->format() ); }