static void TestIntervals(void) { PRStatus rv; PRUint32 delta; PRInt32 seconds; PRUint64 elapsed, thousand; PRTime timein, timeout; PRLock *ml = PR_NewLock(); PRCondVar *cv = PR_NewCondVar(ml); for (seconds = 0; seconds < 10; ++seconds) { PRIntervalTime ticks = PR_SecondsToInterval(seconds); PR_Lock(ml); timein = PR_Now(); rv = PR_WaitCondVar(cv, ticks); timeout = PR_Now(); PR_Unlock(ml); LL_SUB(elapsed, timeout, timein); LL_I2L(thousand, 1000); LL_DIV(elapsed, elapsed, thousand); LL_L2UI(delta, elapsed); if (debug_mode) PR_fprintf(output, "TestIntervals: %swaiting %ld seconds took %ld msecs\n", ((rv == PR_SUCCESS) ? "" : "FAILED "), seconds, delta); } PR_DestroyCondVar(cv); PR_DestroyLock(ml); if (debug_mode) PR_fprintf(output, "\n"); } /* TestIntervals */
PRMJ_ToExtendedTime(PRInt32 time) { PRInt64 exttime; PRInt64 g1970GMTMicroSeconds; PRInt64 low; time_t diff; PRInt64 tmp; PRInt64 tmp1; diff = PRMJ_LocalGMTDifference(); LL_UI2L(tmp, PRMJ_USEC_PER_SEC); LL_I2L(tmp1,diff); LL_MUL(tmp,tmp,tmp1); LL_UI2L(g1970GMTMicroSeconds,G1970GMTMICROHI); LL_UI2L(low,G1970GMTMICROLOW); #ifndef HAVE_LONG_LONG LL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,16); LL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,16); #else LL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,32); #endif LL_ADD(g1970GMTMicroSeconds,g1970GMTMicroSeconds,low); LL_I2L(exttime,time); LL_ADD(exttime,exttime,g1970GMTMicroSeconds); LL_SUB(exttime,exttime,tmp); return exttime; }
static SECCertTimeValidity _NSSCPY_CheckCrlTimes(CERTCrl *crl, PRTime t) { PRTime notBefore, notAfter, llPendingSlop, tmp1; SECStatus rv; PRInt32 pSlop = CERT_GetSlopTime(); rv = _NSSCPY_GetCrlTimes(crl, ¬Before, ¬After); if (rv) { return(secCertTimeExpired); } LL_I2L(llPendingSlop, pSlop); /* convert to micro seconds */ LL_I2L(tmp1, PR_USEC_PER_SEC); LL_MUL(llPendingSlop, llPendingSlop, tmp1); LL_SUB(notBefore, notBefore, llPendingSlop); if ( LL_CMP( t, <, notBefore ) ) { return(secCertTimeNotValidYet); } /* If next update is omitted and the test for notBefore passes, then * we assume that the crl is up to date. */ if ( LL_IS_ZERO(notAfter) ) { return(secCertTimeValid); } if ( LL_CMP( t, >, notAfter) ) { return(secCertTimeExpired); } return(secCertTimeValid); }
void nsTimelineServiceTimer::stop(PRTime now) { TIMER_CHECK_OWNER(); mRunning--; if (mRunning == 0) { PRTime delta, accum; LL_SUB(delta, now, mStart); LL_ADD(accum, mAccum, delta); mAccum = accum; } }
PRUint32 deltaMicroSeconds(PRTime aStartTime, PRTime aEndTime) { PRUint32 delta; PRUint64 loadTime64; LL_SUB(loadTime64, aEndTime, aStartTime); LL_L2UI(delta, loadTime64); return delta; }
PRTime nsTimelineServiceTimer::getAccum(PRTime now) { TIMER_CHECK_OWNER(); PRTime accum; if (!mRunning) { accum = mAccum; } else { PRTime delta; LL_SUB(delta, now, mStart); LL_ADD(accum, mAccum, delta); } return accum; }
/* * Make this public if we need it. */ static nsresult NS_TimelineMarkV(const char *text, va_list args) { PRTime elapsed,tmp; PR_CallOnce(&initonce, TimelineInit); TimelineThreadData *thread = GetThisThreadData(); tmp = Now(); LL_SUB(elapsed, tmp, thread->initTime); PrintTime(elapsed, text, args); return NS_OK; }
static PRInt64 PR_CALLBACK FileAvailable64(PRFileDesc *fd) { PRInt64 result, cur, end; PRInt64 minus_one; LL_I2L(minus_one, -1); cur = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_CUR); if (LL_GE_ZERO(cur)) end = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_END); if (!LL_GE_ZERO(cur) || !LL_GE_ZERO(end)) return minus_one; LL_SUB(result, end, cur); (void)_PR_MD_LSEEK64(fd, cur, PR_SEEK_SET); return result; }
static void TestNowOverhead(void) { PRTime timeout, timein; PRInt32 overhead, loops = 1000000; PRInt64 elapsed, per_call, ten23rd, ten26th; LL_I2L(ten23rd, 1000); LL_I2L(ten26th, 1000000); timein = PR_Now(); while (--loops > 0) timeout = PR_Now(); LL_SUB(elapsed, timeout, timein); LL_MUL(elapsed, elapsed, ten23rd); LL_DIV(per_call, elapsed, ten26th); LL_L2I(overhead, per_call); PR_fprintf( output, "Overhead of 'PR_Now()' is %u nsecs\n\n", overhead); } /* TestNowOverhead */
PRMJ_ToBaseTime(PRInt64 time) { PRInt64 g1970GMTMicroSeconds; PRInt64 g2037GMTMicroSeconds; PRInt64 low; PRInt32 result; LL_UI2L(g1970GMTMicroSeconds,G1970GMTMICROHI); LL_UI2L(low,G1970GMTMICROLOW); #ifndef HAVE_LONG_LONG LL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,16); LL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,16); #else LL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,32); #endif LL_ADD(g1970GMTMicroSeconds,g1970GMTMicroSeconds,low); LL_UI2L(g2037GMTMicroSeconds,G2037GMTMICROHI); LL_UI2L(low,G2037GMTMICROLOW); #ifndef HAVE_LONG_LONG LL_SHL(g2037GMTMicroSeconds,g2037GMTMicroSeconds,16); LL_SHL(g2037GMTMicroSeconds,g2037GMTMicroSeconds,16); #else LL_SHL(g2037GMTMicroSeconds,g2037GMTMicroSeconds,32); #endif LL_ADD(g2037GMTMicroSeconds,g2037GMTMicroSeconds,low); if(LL_CMP(time, <, g1970GMTMicroSeconds) || LL_CMP(time, >, g2037GMTMicroSeconds)){ return -1; } LL_SUB(time,time,g1970GMTMicroSeconds); LL_L2I(result,time); return result; }
/** Returns a timestamp string containing the local time, if at least * deltaSec seconds have elapsed since the last timestamp. Otherwise, * a null string is returned. * @param deltaSec minimum elapsed seconds since last timestamp (>=0) * @param lastTime in/out parameter containing time of last timestamp * @param aTimeStamp returned timestamp string * @return NS_OK on success */ NS_IMETHODIMP mozXMLTermUtils::TimeStamp(PRInt32 deltaSec, PRTime& lastTime, nsString& aTimeStamp) { static const PRInt32 DATE_LEN = 19; PRTime deltaTime ; char dateStr[DATE_LEN+1]; PRTime curTime, difTime; curTime = PR_Now(); LL_SUB(difTime, curTime, lastTime); LL_I2L(deltaTime, deltaSec*1000000); if (LL_CMP(difTime, <, deltaTime)) { // Not enough time has elapsed for a new time stamp aTimeStamp.SetLength(0); return NS_OK; } lastTime = curTime; // Current local time PRExplodedTime localTime; PR_ExplodeTime(curTime, PR_LocalTimeParameters, &localTime); PRInt32 nWritten = PR_snprintf(dateStr, DATE_LEN+1, "%02d:%02d:%02d %02d/%02d/%04d", // XXX i18n! localTime.tm_hour, localTime.tm_min, localTime.tm_sec, localTime.tm_mday, localTime.tm_month+1, localTime.tm_year); if (nWritten != DATE_LEN) return NS_ERROR_FAILURE; XMLT_LOG(mozXMLTermUtils::LocalTime,99,("localTime=%s\n", dateStr)); aTimeStamp.AssignASCII(dateStr); return NS_OK; }
int main(int argc, char** argv) { FILE* fp = fopen("words.txt", "r"); if (nsnull == fp) { printf("can't open words.txt\n"); return -1; } PRInt32 count = 0; PRUnichar** strings = new PRUnichar*[60000]; nsIAtom** ids = new nsIAtom*[60000]; nsAutoString s1, s2; PRTime start = PR_Now(); PRInt32 i; for (i = 0; i < 60000; i++) { char buf[1000]; char* s = fgets(buf, sizeof(buf), fp); if (nsnull == s) { break; } nsCAutoString sb; sb.Assign(buf); strings[count++] = ToNewUnicode(sb); ToUpperCase(sb); strings[count++] = ToNewUnicode(sb); } PRTime end0 = PR_Now(); // Find and create idents for (i = 0; i < count; i++) { ids[i] = NS_NewAtom(strings[i]); } PRUnichar qqs[1]; qqs[0] = 0; nsIAtom* qq = NS_NewAtom(qqs); PRTime end1 = PR_Now(); // Now make sure we can find all the idents we just made for (i = 0; i < count; i++) { const char *utf8String; ids[i]->GetUTF8String(&utf8String); nsIAtom* id = NS_NewAtom(utf8String); if (id != ids[i]) { id->ToString(s1); ids[i]->ToString(s2); printf("find failed: id='%s' ids[%d]='%s'\n", NS_LossyConvertUTF16toASCII(s1).get(), i, NS_LossyConvertUTF16toASCII(s2).get()); return -1; } NS_RELEASE(id); } PRTime end2 = PR_Now(); // Destroy all the atoms we just made NS_RELEASE(qq); for (i = 0; i < count; i++) { NS_RELEASE(ids[i]); } // Print out timings PRTime end3 = PR_Now(); PRTime creates, finds, lookups, dtor, ustoms; LL_I2L(ustoms, 1000); LL_SUB(creates, end0, start); LL_DIV(creates, creates, ustoms); LL_SUB(finds, end1, end0); LL_DIV(finds, finds, ustoms); LL_SUB(lookups, end2, end1); LL_DIV(lookups, lookups, ustoms); LL_SUB(dtor, end3, end2); char buf[500]; PR_snprintf(buf, sizeof(buf), "making %d ident strings took %lldms", count, creates); puts(buf); PR_snprintf(buf, sizeof(buf), "%d new idents took %lldms", count, finds); puts(buf); PR_snprintf(buf, sizeof(buf), "%d ident lookups took %lldms", count, lookups); puts(buf); PR_snprintf(buf, sizeof(buf), "dtor took %lldusec", dtor); puts(buf); printf("%d live atoms\n", NS_GetNumberOfAtoms()); NS_POSTCONDITION(0 == NS_GetNumberOfAtoms(), "dangling atoms"); return 0; }
nsresult nsMsgSearchAdapter::EncodeImapTerm (nsIMsgSearchTerm *term, bool reallyDredd, const PRUnichar *srcCharset, const PRUnichar *destCharset, char **ppOutTerm) { NS_ENSURE_ARG_POINTER(term); NS_ENSURE_ARG_POINTER(ppOutTerm); nsresult err = NS_OK; bool useNot = false; bool useQuotes = false; bool ignoreValue = false; nsCAutoString arbitraryHeader; const char *whichMnemonic = nsnull; const char *orHeaderMnemonic = nsnull; *ppOutTerm = nsnull; nsCOMPtr <nsIMsgSearchValue> searchValue; nsresult rv = term->GetValue(getter_AddRefs(searchValue)); NS_ENSURE_SUCCESS(rv,rv); nsMsgSearchOpValue op; term->GetOp(&op); if (op == nsMsgSearchOp::DoesntContain || op == nsMsgSearchOp::Isnt) useNot = true; nsMsgSearchAttribValue attrib; term->GetAttrib(&attrib); switch (attrib) { case nsMsgSearchAttrib::ToOrCC: orHeaderMnemonic = m_kImapCC; // fall through to case nsMsgSearchAttrib::To: case nsMsgSearchAttrib::To: whichMnemonic = m_kImapTo; break; case nsMsgSearchAttrib::CC: whichMnemonic = m_kImapCC; break; case nsMsgSearchAttrib::Sender: whichMnemonic = m_kImapFrom; break; case nsMsgSearchAttrib::Subject: whichMnemonic = m_kImapSubject; break; case nsMsgSearchAttrib::Body: whichMnemonic = m_kImapBody; break; case nsMsgSearchAttrib::AgeInDays: // added for searching online for age in days... // for AgeInDays, we are actually going to perform a search by date, so convert the operations for age // to the IMAP mnemonics that we would use for date! { // If we have a future date, the > and < are reversed. // e.g. ageInDays > 2 means more than 2 days old ("date before X") whereas // ageInDays > -2 should be more than 2 days in the future ("date after X") PRInt32 ageInDays; searchValue->GetAge(&ageInDays); bool dateInFuture = (ageInDays < 0); switch (op) { case nsMsgSearchOp::IsGreaterThan: whichMnemonic = (!dateInFuture) ? m_kImapBefore : m_kImapSince; break; case nsMsgSearchOp::IsLessThan: whichMnemonic = (!dateInFuture) ? m_kImapSince : m_kImapBefore; break; case nsMsgSearchOp::Is: whichMnemonic = m_kImapSentOn; break; default: NS_ASSERTION(false, "invalid search operator"); return NS_ERROR_INVALID_ARG; } } break; case nsMsgSearchAttrib::Size: switch (op) { case nsMsgSearchOp::IsGreaterThan: whichMnemonic = m_kImapSizeLarger; break; case nsMsgSearchOp::IsLessThan: whichMnemonic = m_kImapSizeSmaller; break; default: NS_ASSERTION(false, "invalid search operator"); return NS_ERROR_INVALID_ARG; } break; case nsMsgSearchAttrib::Date: switch (op) { case nsMsgSearchOp::IsBefore: whichMnemonic = m_kImapBefore; break; case nsMsgSearchOp::IsAfter: whichMnemonic = m_kImapSince; break; case nsMsgSearchOp::Isnt: /* we've already added the "Not" so just process it like it was a date is search */ case nsMsgSearchOp::Is: whichMnemonic = m_kImapSentOn; break; default: NS_ASSERTION(false, "invalid search operator"); return NS_ERROR_INVALID_ARG; } break; case nsMsgSearchAttrib::AnyText: whichMnemonic = m_kImapAnyText; break; case nsMsgSearchAttrib::Keywords: whichMnemonic = m_kImapKeyword; break; case nsMsgSearchAttrib::MsgStatus: useNot = false; // bizarrely, NOT SEEN is wrong, but UNSEEN is right. ignoreValue = true; // the mnemonic is all we need PRUint32 status; searchValue->GetStatus(&status); switch (status) { case nsMsgMessageFlags::Read: whichMnemonic = op == nsMsgSearchOp::Is ? m_kImapSeen : m_kImapNotSeen; break; case nsMsgMessageFlags::Replied: whichMnemonic = op == nsMsgSearchOp::Is ? m_kImapAnswered : m_kImapNotAnswered; break; case nsMsgMessageFlags::New: whichMnemonic = op == nsMsgSearchOp::Is ? m_kImapNew : m_kImapNotNew; break; case nsMsgMessageFlags::Marked: whichMnemonic = op == nsMsgSearchOp::Is ? m_kImapFlagged : m_kImapNotFlagged; break; default: NS_ASSERTION(false, "invalid search operator"); return NS_ERROR_INVALID_ARG; } break; default: if ( attrib > nsMsgSearchAttrib::OtherHeader && attrib < nsMsgSearchAttrib::kNumMsgSearchAttributes) { nsCString arbitraryHeaderTerm; term->GetArbitraryHeader(arbitraryHeaderTerm); if (!arbitraryHeaderTerm.IsEmpty()) { arbitraryHeader.AssignLiteral(" \""); arbitraryHeader.Append(arbitraryHeaderTerm); arbitraryHeader.AppendLiteral("\" "); whichMnemonic = arbitraryHeader.get(); } else return NS_ERROR_FAILURE; } else { NS_ASSERTION(false, "invalid search operator"); return NS_ERROR_INVALID_ARG; } } char *value = nsnull; char dateBuf[100]; dateBuf[0] = '\0'; bool valueWasAllocated = false; if (attrib == nsMsgSearchAttrib::Date) { // note that there used to be code here that encoded an RFC822 date for imap searches. // The IMAP RFC 2060 is misleading to the point that it looks like it requires an RFC822 // date but really it expects dd-mmm-yyyy, like dredd, and refers to the RFC822 date only in that the // dd-mmm-yyyy date will match the RFC822 date within the message. PRTime adjustedDate; searchValue->GetDate(&adjustedDate); if (whichMnemonic == m_kImapSince) { // it looks like the IMAP server searches on Since includes the date in question... // our UI presents Is, IsGreater and IsLessThan. For the IsGreater case (m_kImapSince) // we need to adjust the date so we get greater than and not greater than or equal to which // is what the IMAP server wants to search on // won't work on Mac. // ack, is this right? is PRTime seconds or microseconds? PRInt64 microSecondsPerSecond, secondsInDay, microSecondsInDay; LL_I2L(microSecondsPerSecond, PR_USEC_PER_SEC); LL_UI2L(secondsInDay, 60 * 60 * 24); LL_MUL(microSecondsInDay, secondsInDay, microSecondsPerSecond); LL_ADD(adjustedDate, adjustedDate, microSecondsInDay); // bump up to the day after this one... } PRExplodedTime exploded; PR_ExplodeTime(adjustedDate, PR_LocalTimeParameters, &exploded); PR_FormatTimeUSEnglish(dateBuf, sizeof(dateBuf), "%d-%b-%Y", &exploded); // strftime (dateBuf, sizeof(dateBuf), "%d-%b-%Y", localtime (/* &term->m_value.u.date */ &adjustedDate)); value = dateBuf; } else { if (attrib == nsMsgSearchAttrib::AgeInDays) { // okay, take the current date, subtract off the age in days, then do an appropriate Date search on // the resulting day. PRInt32 ageInDays; searchValue->GetAge(&ageInDays); PRTime now = PR_Now(); PRTime matchDay; PRInt64 microSecondsPerSecond, secondsInDays, microSecondsInDay; LL_I2L(microSecondsPerSecond, PR_USEC_PER_SEC); LL_I2L(secondsInDays, 60 * 60 * 24 * ageInDays); LL_MUL(microSecondsInDay, secondsInDays, microSecondsPerSecond); LL_SUB(matchDay, now, microSecondsInDay); // = now - term->m_value.u.age * 60 * 60 * 24; PRExplodedTime exploded; PR_ExplodeTime(matchDay, PR_LocalTimeParameters, &exploded); PR_FormatTimeUSEnglish(dateBuf, sizeof(dateBuf), "%d-%b-%Y", &exploded); // strftime (dateBuf, sizeof(dateBuf), "%d-%b-%Y", localtime (&matchDay)); value = dateBuf; } else if (attrib == nsMsgSearchAttrib::Size) { PRUint32 sizeValue; nsCAutoString searchTermValue; searchValue->GetSize(&sizeValue); // Multiply by 1024 to get into kb resolution sizeValue *= 1024; // Ensure that greater than is really greater than // in kb resolution. if (op == nsMsgSearchOp::IsGreaterThan) sizeValue += 1024; searchTermValue.AppendInt(sizeValue); value = ToNewCString(searchTermValue); valueWasAllocated = true; } else if (IS_STRING_ATTRIBUTE(attrib)) { PRUnichar *convertedValue; // = reallyDredd ? MSG_EscapeSearchUrl (term->m_value.u.string) : msg_EscapeImapSearchProtocol(term->m_value.u.string); nsString searchTermValue; searchValue->GetStr(searchTermValue); // Ugly switch for Korean mail/news charsets. // We want to do this here because here is where // we know what charset we want to use. #ifdef DOING_CHARSET if (reallyDredd) dest_csid = INTL_DefaultNewsCharSetID(dest_csid); else dest_csid = INTL_DefaultMailCharSetID(dest_csid); #endif // do all sorts of crazy escaping convertedValue = reallyDredd ? EscapeSearchUrl (searchTermValue.get()) : EscapeImapSearchProtocol(searchTermValue.get()); useQuotes = ((!reallyDredd || (nsDependentString(convertedValue).FindChar(PRUnichar(' ')) != -1)) && (attrib != nsMsgSearchAttrib::Keywords)); // now convert to char* and escape quoted_specials nsCAutoString valueStr; nsresult rv = ConvertFromUnicode(NS_LossyConvertUTF16toASCII(destCharset).get(), nsDependentString(convertedValue), valueStr); if (NS_SUCCEEDED(rv)) { const char *vptr = valueStr.get(); // max escaped length is one extra character for every character in the cmd. nsAutoArrayPtr<char> newValue(new char[2*strlen(vptr) + 1]); if (newValue) { char *p = newValue; while (1) { char ch = *vptr++; if (!ch) break; if ((useQuotes ? ch == '"' : 0) || ch == '\\') *p++ = '\\'; *p++ = ch; } *p = '\0'; value = strdup(newValue); // realloc down to smaller size } } else value = strdup(""); NS_Free(convertedValue); valueWasAllocated = true; } } // this should be rewritten to use nsCString int subLen = (value ? strlen(value) : 0) + (useNot ? strlen(m_kImapNot) : 0) + strlen(m_kImapHeader); int len = strlen(whichMnemonic) + subLen + (useQuotes ? 2 : 0) + (orHeaderMnemonic ? (subLen + strlen(m_kImapOr) + strlen(orHeaderMnemonic) + 2 /*""*/) : 0) + 10; // add slough for imap string literals char *encoding = new char[len]; if (encoding) { encoding[0] = '\0'; // Remember: if ToOrCC and useNot then the expression becomes NOT To AND Not CC as opposed to (NOT TO) || (NOT CC) if (orHeaderMnemonic && !useNot) PL_strcat(encoding, m_kImapOr); if (useNot) PL_strcat (encoding, m_kImapNot); if (!arbitraryHeader.IsEmpty()) PL_strcat (encoding, m_kImapHeader); PL_strcat (encoding, whichMnemonic); if (!ignoreValue) err = EncodeImapValue(encoding, value, useQuotes, reallyDredd); if (orHeaderMnemonic) { if (useNot) PL_strcat(encoding, m_kImapNot); PL_strcat (encoding, m_kImapHeader); PL_strcat (encoding, orHeaderMnemonic); if (!ignoreValue) err = EncodeImapValue(encoding, value, useQuotes, reallyDredd); } // kmcentee, don't let the encoding end with whitespace, // this throws off later url STRCMP if (*encoding && *(encoding + strlen(encoding) - 1) == ' ') *(encoding + strlen(encoding) - 1) = '\0'; } if (value && valueWasAllocated) NS_Free (value); *ppOutTerm = encoding; return err; }
/* * get the difference in seconds between this time zone and UTC (GMT) */ PR_IMPLEMENT(time_t) PRMJ_LocalGMTDifference() { #if defined(XP_UNIX) || defined(XP_PC) struct tm ltime; /* get the difference between this time zone and GMT */ memset((char *)<ime,0,sizeof(ltime)); ltime.tm_mday = 2; ltime.tm_year = 70; #ifdef SUNOS4 ltime.tm_zone = 0; ltime.tm_gmtoff = 0; return timelocal(<ime) - (24 * 3600); #else return mktime(<ime) - (24L * 3600L); #endif #endif #if defined(XP_MAC) static time_t zone = -1L; MachineLocation machineLocation; PRUint64 gmtOffsetSeconds; PRUint64 gmtDelta; PRUint64 dlsOffset; PRInt32 offset; /* difference has been set no need to recalculate */ if(zone != -1) return zone; /* Get the information about the local machine, including * its GMT offset and its daylight savings time info. * Convert each into wides that we can add to * startupTimeMicroSeconds. */ MyReadLocation(&machineLocation); /* Mask off top eight bits of gmtDelta, sign extend lower three. */ if ((machineLocation.u.gmtDelta & 0x00800000) != 0) { gmtOffsetSeconds.lo = (machineLocation.u.gmtDelta & 0x00FFFFFF) | 0xFF000000; gmtOffsetSeconds.hi = 0xFFFFFFFF; LL_UI2L(gmtDelta,0); } else { gmtOffsetSeconds.lo = (machineLocation.u.gmtDelta & 0x00FFFFFF); gmtOffsetSeconds.hi = 0; LL_UI2L(gmtDelta,PRMJ_DAY_SECONDS); } /* normalize time to be positive if you are behind GMT. gmtDelta will always * be positive. */ LL_SUB(gmtDelta,gmtDelta,gmtOffsetSeconds); /* Is Daylight Savings On? If so, we need to add an hour to the offset. */ if (machineLocation.u.dlsDelta != 0) { LL_UI2L(dlsOffset, PRMJ_HOUR_SECONDS); } else LL_I2L(dlsOffset, 0); LL_ADD(gmtDelta,gmtDelta, dlsOffset); LL_L2I(offset,gmtDelta); zone = offset; return (time_t)offset; #endif }
PRMJ_Now(void) { #ifdef XP_PC PRInt64 s, us, ms2us, s2us; struct timeb b; #endif /* XP_PC */ #ifdef XP_UNIX struct timeval tv; PRInt64 s, us, s2us; #endif /* XP_UNIX */ #ifdef XP_MAC UnsignedWide upTime; PRInt64 localTime; PRInt64 gmtOffset; PRInt64 dstOffset; time_t gmtDiff; PRInt64 s2us; #endif /* XP_MAC */ #ifdef XP_PC ftime(&b); LL_UI2L(ms2us, PRMJ_USEC_PER_MSEC); LL_UI2L(s2us, PRMJ_USEC_PER_SEC); LL_UI2L(s, b.time); LL_UI2L(us, b.millitm); LL_MUL(us, us, ms2us); LL_MUL(s, s, s2us); LL_ADD(s, s, us); return s; #endif #ifdef XP_UNIX #if defined(SOLARIS) gettimeofday(&tv); #else gettimeofday(&tv, 0); #endif /* SOLARIS */ LL_UI2L(s2us, PRMJ_USEC_PER_SEC); LL_UI2L(s, tv.tv_sec); LL_UI2L(us, tv.tv_usec); LL_MUL(s, s, s2us); LL_ADD(s, s, us); return s; #endif /* XP_UNIX */ #ifdef XP_MAC LL_UI2L(localTime,0); gmtDiff = PRMJ_LocalGMTDifference(); LL_I2L(gmtOffset,gmtDiff); LL_UI2L(s2us, PRMJ_USEC_PER_SEC); LL_MUL(gmtOffset,gmtOffset,s2us); LL_UI2L(dstOffset,0); dstOffset = PRMJ_DSTOffset(dstOffset); LL_SUB(gmtOffset,gmtOffset,dstOffset); /* don't adjust for DST since it sets ctime and gmtime off on the MAC */ Microseconds(&upTime); LL_ADD(localTime,localTime,gmtOffset); LL_ADD(localTime,localTime, *((PRUint64 *)&dstLocalBaseMicroseconds)); LL_ADD(localTime,localTime, *((PRUint64 *)&upTime)); return *((PRUint64 *)&localTime); #endif /* XP_MAC */ }
// Set rcvDate to true to get the Received: date instead of the Date: date. nsresult nsMsgGroupView::GetAgeBucketValue(nsIMsgDBHdr *aMsgHdr, PRUint32 * aAgeBucket, bool rcvDate) { NS_ENSURE_ARG_POINTER(aMsgHdr); NS_ENSURE_ARG_POINTER(aAgeBucket); PRTime dateOfMsg; nsresult rv; if (!rcvDate) rv = aMsgHdr->GetDate(&dateOfMsg); else { PRUint32 rcvDateSecs; rv = aMsgHdr->GetUint32Property("dateReceived", &rcvDateSecs); Seconds2PRTime(rcvDateSecs, &dateOfMsg); } NS_ENSURE_SUCCESS(rv, rv); PRTime currentTime = PR_Now(); PRExplodedTime currentExplodedTime; PR_ExplodeTime(currentTime, PR_LocalTimeParameters, ¤tExplodedTime); PRExplodedTime explodedMsgTime; PR_ExplodeTime(dateOfMsg, PR_LocalTimeParameters, &explodedMsgTime); if (m_lastCurExplodedTime.tm_mday && m_lastCurExplodedTime.tm_mday != currentExplodedTime.tm_mday) m_dayChanged = true; // this will cause us to rebuild the view. m_lastCurExplodedTime = currentExplodedTime; if (currentExplodedTime.tm_year == explodedMsgTime.tm_year && currentExplodedTime.tm_month == explodedMsgTime.tm_month && currentExplodedTime.tm_mday == explodedMsgTime.tm_mday) { // same day... *aAgeBucket = 1; } // figure out how many days ago this msg arrived else if (LL_CMP(currentTime, >, dateOfMsg)) { // some constants for calculation static PRInt64 microSecondsPerSecond; static PRInt64 microSecondsPerDay; static PRInt64 secondsPerDay; static PRInt64 microSecondsPer6Days; static PRInt64 microSecondsPer13Days; static bool bGotConstants = false; if ( !bGotConstants ) { // seeds LL_I2L ( microSecondsPerSecond, PR_USEC_PER_SEC ); LL_UI2L ( secondsPerDay, 60 * 60 * 24 ); // derivees LL_MUL( microSecondsPerDay, secondsPerDay, microSecondsPerSecond ); LL_MUL( microSecondsPer6Days, microSecondsPerDay, 6 ); LL_MUL( microSecondsPer13Days, microSecondsPerDay, 13 ); bGotConstants = true; } // setting the time variables to local time PRInt64 GMTLocalTimeShift; LL_ADD( GMTLocalTimeShift, currentExplodedTime.tm_params.tp_gmt_offset, currentExplodedTime.tm_params.tp_dst_offset ); LL_MUL( GMTLocalTimeShift, GMTLocalTimeShift, microSecondsPerSecond ); LL_ADD( currentTime, currentTime, GMTLocalTimeShift ); LL_ADD( dateOfMsg, dateOfMsg, GMTLocalTimeShift ); // the most recent midnight, counting from current time PRInt64 todaysMicroSeconds, mostRecentMidnight; LL_MOD( todaysMicroSeconds, currentTime, microSecondsPerDay ); LL_SUB( mostRecentMidnight, currentTime, todaysMicroSeconds ); PRInt64 yesterday; LL_SUB( yesterday, mostRecentMidnight, microSecondsPerDay ); // most recent midnight minus 6 days PRInt64 mostRecentWeek; LL_SUB( mostRecentWeek, mostRecentMidnight, microSecondsPer6Days ); // was the message sent yesterday? if ( LL_CMP( dateOfMsg, >=, yesterday ) ) // yes .... *aAgeBucket = 2; else if ( LL_CMP(dateOfMsg, >=, mostRecentWeek) ) *aAgeBucket = 3; else {
NS_IMETHODIMP CVE_2013_1732_firefox12_0_nsBlockFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aMetrics, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsBlockFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus); #ifdef DEBUG if (gNoisyReflow) { IndentBy(stdout, gNoiseIndent); ListTag(stdout); printf(": begin reflow availSize=%d,%d computedSize=%d,%d\n", aReflowState.availableWidth, aReflowState.availableHeight, aReflowState.ComputedWidth(), aReflowState.ComputedHeight()); } AutoNoisyIndenter indent(gNoisy); PRTime start = LL_ZERO; // Initialize these variablies to silence the compiler. PRInt32 ctc = 0; // We only use these if they are set (gLameReflowMetrics). if (gLameReflowMetrics) { start = PR_Now(); ctc = nsLineBox::GetCtorCount(); } #endif const nsHTMLReflowState *reflowState = &aReflowState; nsAutoPtr<nsHTMLReflowState> mutableReflowState; // If we have non-auto height, we're clipping our kids and we fit, // make sure our kids fit too. if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE && aReflowState.ComputedHeight() != NS_AUTOHEIGHT && ApplyOverflowClipping(this, aReflowState.mStyleDisplay)) { nsMargin heightExtras = aReflowState.mComputedBorderPadding; if (GetSkipSides() & NS_SIDE_TOP) { heightExtras.top = 0; } else { // Bottom margin never causes us to create continuations, so we // don't need to worry about whether it fits in its entirety. heightExtras.top += aReflowState.mComputedMargin.top; } if (GetEffectiveComputedHeight(aReflowState) + heightExtras.TopBottom() <= aReflowState.availableHeight) { mutableReflowState = new nsHTMLReflowState(aReflowState); mutableReflowState->availableHeight = NS_UNCONSTRAINEDSIZE; reflowState = mutableReflowState; } } // See comment below about oldSize. Use *only* for the // abs-pos-containing-block-size-change optimization! nsSize oldSize = GetSize(); // Should we create a float manager? nsAutoFloatManager autoFloatManager(const_cast<nsHTMLReflowState&>(*reflowState)); // XXXldb If we start storing the float manager in the frame rather // than keeping it around only during reflow then we should create it // only when there are actually floats to manage. Otherwise things // like tables will gain significant bloat. bool needFloatManager = nsBlockFrame::BlockNeedsFloatManager(this); if (needFloatManager) autoFloatManager.CreateFloatManager(aPresContext); // OK, some lines may be reflowed. Blow away any saved line cursor // because we may invalidate the nondecreasing // overflowArea.VisualOverflow().y/yMost invariant, and we may even // delete the line with the line cursor. ClearLineCursor(); if (IsFrameTreeTooDeep(*reflowState, aMetrics, aStatus)) { return NS_OK; } bool marginRoot = BlockIsMarginRoot(this); nsBlockReflowState state(*reflowState, aPresContext, this, aMetrics, marginRoot, marginRoot, needFloatManager); #ifdef IBMBIDI if (GetStateBits() & NS_BLOCK_NEEDS_BIDI_RESOLUTION) static_cast<nsBlockFrame*>(GetFirstContinuation())->ResolveBidi(); #endif // IBMBIDI if (RenumberLists(aPresContext)) { AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN); } nsresult rv = NS_OK; // ALWAYS drain overflow. We never want to leave the previnflow's // overflow lines hanging around; block reflow depends on the // overflow line lists being cleared out between reflow passes. DrainOverflowLines(); // Handle paginated overflow (see nsContainerFrame.h) nsOverflowAreas ocBounds; nsReflowStatus ocStatus = NS_FRAME_COMPLETE; if (GetPrevInFlow()) { ReflowOverflowContainerChildren(aPresContext, *reflowState, ocBounds, 0, ocStatus); } // Now that we're done cleaning up our overflow container lists, we can // give |state| its nsOverflowContinuationTracker. nsOverflowContinuationTracker tracker(aPresContext, this, false); state.mOverflowTracker = &tracker; // Drain & handle pushed floats DrainPushedFloats(state); nsOverflowAreas fcBounds; nsReflowStatus fcStatus = NS_FRAME_COMPLETE; rv = ReflowPushedFloats(state, fcBounds, fcStatus); NS_ENSURE_SUCCESS(rv, rv); // If we're not dirty (which means we'll mark everything dirty later) // and our width has changed, mark the lines dirty that we need to // mark dirty for a resize reflow. if (reflowState->mFlags.mHResize) PrepareResizeReflow(state); mState &= ~NS_FRAME_FIRST_REFLOW; // Now reflow... rv = ReflowDirtyLines(state); NS_ASSERTION(NS_SUCCEEDED(rv), "reflow dirty lines failed"); if (NS_FAILED(rv)) return rv; NS_MergeReflowStatusInto(&state.mReflowStatus, ocStatus); NS_MergeReflowStatusInto(&state.mReflowStatus, fcStatus); // If we end in a BR with clear and affected floats continue, // we need to continue, too. if (NS_UNCONSTRAINEDSIZE != reflowState->availableHeight && NS_FRAME_IS_COMPLETE(state.mReflowStatus) && state.mFloatManager->ClearContinues(FindTrailingClear())) { NS_FRAME_SET_INCOMPLETE(state.mReflowStatus); } if (!NS_FRAME_IS_FULLY_COMPLETE(state.mReflowStatus)) { if (GetOverflowLines() || GetPushedFloats()) { state.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW; } #ifdef DEBUG_kipp ListTag(stdout); printf(": block is not fully complete\n"); #endif } CheckFloats(state); // Place the "marker" (bullet) frame if it is placed next to a block // child. // // According to the CSS2 spec, section 12.6.1, the "marker" box // participates in the height calculation of the list-item box's // first line box. // // There are exactly two places a bullet can be placed: near the // first or second line. It's only placed on the second line in a // rare case: an empty first line followed by a second line that // contains a block (example: <LI>\n<P>... ). This is where // the second case can happen. if (mBullet && HaveOutsideBullet() && !mLines.empty() && (mLines.front()->IsBlock() || (0 == mLines.front()->mBounds.height && mLines.front() != mLines.back() && mLines.begin().next()->IsBlock()))) { // Reflow the bullet nsHTMLReflowMetrics metrics; // XXX Use the entire line when we fix bug 25888. nsLayoutUtils::LinePosition position; bool havePosition = nsLayoutUtils::GetFirstLinePosition(this, &position); nscoord lineTop = havePosition ? position.mTop : reflowState->mComputedBorderPadding.top; ReflowBullet(state, metrics, lineTop); NS_ASSERTION(!BulletIsEmpty() || metrics.height == 0, "empty bullet took up space"); if (havePosition && !BulletIsEmpty()) { // We have some lines to align the bullet with. // Doing the alignment using the baseline will also cater for // bullets that are placed next to a child block (bug 92896) // Tall bullets won't look particularly nice here... nsRect bbox = mBullet->GetRect(); bbox.y = position.mBaseline - metrics.ascent; mBullet->SetRect(bbox); } // Otherwise just leave the bullet where it is, up against our top padding. } // Compute our final size nscoord bottomEdgeOfChildren; ComputeFinalSize(*reflowState, state, aMetrics, &bottomEdgeOfChildren); nsRect areaBounds = nsRect(0, 0, aMetrics.width, aMetrics.height); ComputeOverflowAreas(areaBounds, reflowState->mStyleDisplay, bottomEdgeOfChildren, aMetrics.mOverflowAreas); // Factor overflow container child bounds into the overflow area aMetrics.mOverflowAreas.UnionWith(ocBounds); // Factor pushed float child bounds into the overflow area aMetrics.mOverflowAreas.UnionWith(fcBounds); // Let the absolutely positioned container reflow any absolutely positioned // child frames that need to be reflowed, e.g., elements with a percentage // based width/height // We want to do this under either of two conditions: // 1. If we didn't do the incremental reflow above. // 2. If our size changed. // Even though it's the padding edge that's the containing block, we // can use our rect (the border edge) since if the border style // changed, the reflow would have been targeted at us so we'd satisfy // condition 1. // XXX checking oldSize is bogus, there are various reasons we might have // reflowed but our size might not have been changed to what we // asked for (e.g., we ended up being pushed to a new page) // When WillReflowAgainForClearance is true, we will reflow again without // resetting the size. Because of this, we must not reflow our abs-pos children // in that situation --- what we think is our "new size" // will not be our real new size. This also happens to be more efficient. if (HasAbsolutelyPositionedChildren()) { nsAbsoluteContainingBlock* absoluteContainer = GetAbsoluteContainingBlock(); bool haveInterrupt = aPresContext->HasPendingInterrupt(); if (reflowState->WillReflowAgainForClearance() || haveInterrupt) { // Make sure that when we reflow again we'll actually reflow all the abs // pos frames that might conceivably depend on our size (or all of them, // if we're dirty right now and interrupted; in that case we also need // to mark them all with NS_FRAME_IS_DIRTY). Sadly, we can't do much // better than that, because we don't really know what our size will be, // and it might in fact not change on the followup reflow! if (haveInterrupt && (GetStateBits() & NS_FRAME_IS_DIRTY)) { absoluteContainer->MarkAllFramesDirty(); } else { absoluteContainer->MarkSizeDependentFramesDirty(); } } else { nsSize containingBlockSize = CalculateContainingBlockSizeForAbsolutes(*reflowState, nsSize(aMetrics.width, aMetrics.height)); // Mark frames that depend on changes we just made to this frame as dirty: // Now we can assume that the padding edge hasn't moved. // We need to reflow the absolutes if one of them depends on // its placeholder position, or the containing block size in a // direction in which the containing block size might have // changed. bool cbWidthChanged = aMetrics.width != oldSize.width; bool isRoot = !GetContent()->GetParent(); // If isRoot and we have auto height, then we are the initial // containing block and the containing block height is the // viewport height, which can't change during incremental // reflow. bool cbHeightChanged = !(isRoot && NS_UNCONSTRAINEDSIZE == reflowState->ComputedHeight()) && aMetrics.height != oldSize.height; absoluteContainer->Reflow(this, aPresContext, *reflowState, state.mReflowStatus, containingBlockSize.width, containingBlockSize.height, true, cbWidthChanged, cbHeightChanged, &aMetrics.mOverflowAreas); //XXXfr Why isn't this rv (and others in this file) checked/returned? } } // Determine if we need to repaint our border, background or outline CheckInvalidateSizeChange(aMetrics); FinishAndStoreOverflow(&aMetrics); // Clear the float manager pointer in the block reflow state so we // don't waste time translating the coordinate system back on a dead // float manager. if (needFloatManager) state.mFloatManager = nsnull; aStatus = state.mReflowStatus; #ifdef DEBUG // Between when we drain pushed floats and when we complete reflow, // we're allowed to have multiple continuations of the same float on // our floats list, since a first-in-flow might get pushed to a later // continuation of its containing block. But it's not permitted // outside that time. nsLayoutUtils::AssertNoDuplicateContinuations(this, mFloats); if (gNoisyReflow) { IndentBy(stdout, gNoiseIndent); ListTag(stdout); printf(": status=%x (%scomplete) metrics=%d,%d carriedMargin=%d", aStatus, NS_FRAME_IS_COMPLETE(aStatus) ? "" : "not ", aMetrics.width, aMetrics.height, aMetrics.mCarriedOutBottomMargin.get()); if (HasOverflowAreas()) { printf(" overflow-vis={%d,%d,%d,%d}", aMetrics.VisualOverflow().x, aMetrics.VisualOverflow().y, aMetrics.VisualOverflow().width, aMetrics.VisualOverflow().height); printf(" overflow-scr={%d,%d,%d,%d}", aMetrics.ScrollableOverflow().x, aMetrics.ScrollableOverflow().y, aMetrics.ScrollableOverflow().width, aMetrics.ScrollableOverflow().height); } printf("\n"); } if (gLameReflowMetrics) { PRTime end = PR_Now(); PRInt32 ectc = nsLineBox::GetCtorCount(); PRInt32 numLines = mLines.size(); if (!numLines) numLines = 1; PRTime delta, perLineDelta, lines; LL_I2L(lines, numLines); LL_SUB(delta, end, start); LL_DIV(perLineDelta, delta, lines); ListTag(stdout); char buf[400]; PR_snprintf(buf, sizeof(buf), ": %lld elapsed (%lld per line) (%d lines; %d new lines)", delta, perLineDelta, numLines, ectc - ctc); printf("%s\n", buf); } #endif NS_FRAME_SET_TRUNCATION(aStatus, (*reflowState), aMetrics); return rv; }
nsresult nsListBoxBodyFrame::DoInternalPositionChanged(bool aUp, PRInt32 aDelta) { if (aDelta == 0) return NS_OK; nsRefPtr<nsPresContext> presContext(PresContext()); nsBoxLayoutState state(presContext); // begin timing how long it takes to scroll a row PRTime start = PR_Now(); nsWeakFrame weakThis(this); mContent->GetDocument()->FlushPendingNotifications(Flush_Layout); if (!weakThis.IsAlive()) { return NS_OK; } { nsAutoScriptBlocker scriptBlocker; PRInt32 visibleRows = 0; if (mRowHeight) visibleRows = GetAvailableHeight()/mRowHeight; if (aDelta < visibleRows) { PRInt32 loseRows = aDelta; if (aUp) { // scrolling up, destroy rows from the bottom downwards ReverseDestroyRows(loseRows); mRowsToPrepend += aDelta; mLinkupFrame = nsnull; } else { // scrolling down, destroy rows from the top upwards DestroyRows(loseRows); mRowsToPrepend = 0; } } else { // We have scrolled so much that all of our current frames will // go off screen, so blow them all away. Weeee! nsIFrame *currBox = mFrames.FirstChild(); nsCSSFrameConstructor* fc = presContext->PresShell()->FrameConstructor(); fc->BeginUpdate(); while (currBox) { nsIFrame *nextBox = currBox->GetNextSibling(); RemoveChildFrame(state, currBox); currBox = nextBox; } fc->EndUpdate(); } // clear frame markers so that CreateRows will re-create mTopFrame = mBottomFrame = nsnull; mYPosition = mCurrentIndex*mRowHeight; mScrolling = true; presContext->PresShell()-> FrameNeedsReflow(this, nsIPresShell::eResize, NS_FRAME_HAS_DIRTY_CHILDREN); } if (!weakThis.IsAlive()) { return NS_OK; } // Flush calls CreateRows // XXXbz there has to be a better way to do this than flushing! presContext->PresShell()->FlushPendingNotifications(Flush_Layout); if (!weakThis.IsAlive()) { return NS_OK; } mScrolling = false; VerticalScroll(mYPosition); PRTime end = PR_Now(); PRTime difTime; LL_SUB(difTime, end, start); PRInt32 newTime; LL_L2I(newTime, difTime); newTime /= aDelta; // average old and new mTimePerRow = (newTime + mTimePerRow)/2; return NS_OK; }
int main(int argc, char** argv) { if (3 != argc) { printf("usage: CvtURL url utf8\n"); return -1; } char* characterSetName = argv[2]; nsString* cset = ConvertCharacterSetName(characterSetName); if (NS_PTR_TO_INT32(cset) < 0) { printf("illegal character set name: '%s'\n", characterSetName); return -1; } // Create url object char* urlName = argv[1]; nsIURI* url; nsresult rv; rv = NS_NewURI(&url, urlName); if (NS_OK != rv) { printf("invalid URL: '%s'\n", urlName); return -1; } // Get an input stream from the url nsresult ec; nsIInputStream* in; ec = NS_OpenURI(&in, url); if (nsnull == in) { printf("open of url('%s') failed: error=%x\n", urlName, ec); return -1; } // Translate the input using the argument character set id into // unicode nsCOMPtr<nsIConverterInputStream> uin = do_CreateInstance("@mozilla.org/intl/converter-input-stream;1", &rv); if (NS_SUCCEEDED(rv)) rv = uin->Init(in, cset->get(), 4096); if (NS_FAILED(rv)) { printf("can't create converter input stream: %d\n", rv); return -1; } // Read the input and write some output PRTime start = PR_Now(); PRInt32 count = 0; for (;;) { PRUnichar buf[1000]; PRUint32 nb; ec = uin->Read(buf, 0, 1000, &nb); if (NS_FAILED(ec)) { printf("i/o error: %d\n", ec); break; } if (nb == 0) break; // EOF count += nb; } PRTime end = PR_Now(); PRTime conversion, ustoms; LL_I2L(ustoms, 1000); LL_SUB(conversion, end, start); LL_DIV(conversion, conversion, ustoms); char buf[500]; PR_snprintf(buf, sizeof(buf), "converting and discarding %d bytes took %lldms", count, conversion); puts(buf); // Release the objects in->Release(); url->Release(); return 0; }
int main(int argc, char** argv) { /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt; PR_STDIO_INIT(); opt = PL_CreateOptState(argc, argv, "d"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = PR_TRUE; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); #ifdef XP_MAC SetupMacPrintfLog("timetest.log"); debug_mode = PR_TRUE; #endif /* Testing zero PRTime (the epoch) */ { PRTime t; PRExplodedTime et; LL_I2L(t, 0); if (debug_mode) printf("The NSPR epoch is:\n"); PR_ExplodeTime(t, PR_LocalTimeParameters, &et); printExplodedTime(&et); if (debug_mode) printf("\n"); PR_ExplodeTime(t, PR_GMTParameters, &et); printExplodedTime(&et); if (debug_mode) printf("\n\n"); testParseTimeString(t); } /* ************************************************************* ** ** Testing PR_Now(), PR_ExplodeTime, and PR_ImplodeTime ** on the current time ** ************************************************************* */ { PRTime t1, t2; PRExplodedTime et; if (debug_mode) { printf("*********************************************\n"); printf("** **\n"); printf("** Testing PR_Now(), PR_ExplodeTime, and **\n"); printf("** PR_ImplodeTime on the current time **\n"); printf("** **\n"); printf("*********************************************\n\n"); } t1 = PR_Now(); /* First try converting to UTC */ PR_ExplodeTime(t1, PR_GMTParameters, &et); if (et.tm_params.tp_gmt_offset || et.tm_params.tp_dst_offset) { if (debug_mode) printf("ERROR: UTC has nonzero gmt or dst offset.\n"); else failed_already=1; return 1; } if (debug_mode) printf("Current UTC is "); printExplodedTime(&et); if (debug_mode) printf("\n"); t2 = PR_ImplodeTime(&et); if (LL_NE(t1, t2)) { if (debug_mode) printf("ERROR: Explode and implode are NOT inverse.\n"); else printf("FAIL\n"); return 1; } /* Next, try converting to local (US Pacific) time */ PR_ExplodeTime(t1, PR_LocalTimeParameters, &et); if (debug_mode) printf("Current local time is "); printExplodedTime(&et); if (debug_mode) printf("\n"); if (debug_mode) printf("GMT offset is %ld, DST offset is %ld\n", et.tm_params.tp_gmt_offset, et.tm_params.tp_dst_offset); t2 = PR_ImplodeTime(&et); if (LL_NE(t1, t2)) { if (debug_mode) printf("ERROR: Explode and implode are NOT inverse.\n"); return 1; } if (debug_mode) printf("Please examine the results\n"); testParseTimeString(t1); } /* ******************************************* ** ** Testing PR_NormalizeTime() ** ******************************************* */ /* July 4, 2001 is Wednesday */ { PRExplodedTime et; if (debug_mode) { printf("\n"); printf("**********************************\n"); printf("** **\n"); printf("** Testing PR_NormalizeTime() **\n"); printf("** **\n"); printf("**********************************\n\n"); } et.tm_year = 2001; et.tm_month = 7 - 1; et.tm_mday = 4; et.tm_hour = 0; et.tm_min = 0; et.tm_sec = 0; et.tm_usec = 0; et.tm_params = PR_GMTParameters(&et); PR_NormalizeTime(&et, PR_GMTParameters); if (debug_mode) printf("July 4, 2001 is %s.\n", dayOfWeek[et.tm_wday]); if (et.tm_wday == 3) { if (debug_mode) printf("PASS\n"); } else { if (debug_mode) printf("ERROR: It should be Wednesday\n"); else failed_already=1; return 1; } testParseTimeString(PR_ImplodeTime(&et)); /* June 12, 1997 23:00 PST == June 13, 1997 00:00 PDT */ et.tm_year = 1997; et.tm_month = 6 - 1; et.tm_mday = 12; et.tm_hour = 23; et.tm_min = 0; et.tm_sec = 0; et.tm_usec = 0; et.tm_params.tp_gmt_offset = -8 * 3600; et.tm_params.tp_dst_offset = 0; PR_NormalizeTime(&et, PR_USPacificTimeParameters); if (debug_mode) { printf("Thu Jun 12, 1997 23:00:00 PST is "); } printExplodedTime(&et); if (debug_mode) printf(".\n"); if (et.tm_wday == 5) { if (debug_mode) printf("PASS\n"); } else { if (debug_mode) printf("ERROR: It should be Friday\n"); else failed_already=1; return 1; } testParseTimeString(PR_ImplodeTime(&et)); /* Feb 14, 1997 00:00:00 PDT == Feb 13, 1997 23:00:00 PST */ et.tm_year = 1997; et.tm_month = 2 - 1; et.tm_mday = 14; et.tm_hour = 0; et.tm_min = 0; et.tm_sec = 0; et.tm_usec = 0; et.tm_params.tp_gmt_offset = -8 * 3600; et.tm_params.tp_dst_offset = 3600; PR_NormalizeTime(&et, PR_USPacificTimeParameters); if (debug_mode) { printf("Fri Feb 14, 1997 00:00:00 PDT is "); } printExplodedTime(&et); if (debug_mode) printf(".\n"); if (et.tm_wday == 4) { if (debug_mode) printf("PASS\n"); } else { if (debug_mode) printf("ERROR: It should be Thursday\n"); else failed_already=1; return 1; } testParseTimeString(PR_ImplodeTime(&et)); /* What time is Nov. 7, 1996, 18:29:23 PDT? */ et.tm_year = 1996; et.tm_month = 11 - 1; et.tm_mday = 7; et.tm_hour = 18; et.tm_min = 29; et.tm_sec = 23; et.tm_usec = 0; et.tm_params.tp_gmt_offset = -8 * 3600; /* PDT */ et.tm_params.tp_dst_offset = 3600; PR_NormalizeTime(&et, PR_LocalTimeParameters); if (debug_mode) printf("Nov 7 18:29:23 PDT 1996 is "); printExplodedTime(&et); if (debug_mode) printf(".\n"); testParseTimeString(PR_ImplodeTime(&et)); /* What time is Oct. 7, 1995, 18:29:23 PST? */ et.tm_year = 1995; et.tm_month = 10 - 1; et.tm_mday = 7; et.tm_hour = 18; et.tm_min = 29; et.tm_sec = 23; et.tm_params.tp_gmt_offset = -8 * 3600; /* PST */ et.tm_params.tp_dst_offset = 0; PR_NormalizeTime(&et, PR_LocalTimeParameters); if (debug_mode) printf("Oct 7 18:29:23 PST 1995 is "); printExplodedTime(&et); if (debug_mode) printf(".\n"); testParseTimeString(PR_ImplodeTime(&et)); if (debug_mode) printf("Please examine the results\n"); } /* ************************************************************** ** ** Testing range of years ** ************************************************************** */ { PRExplodedTime et1, et2; PRTime ttt; PRTime secs; if (debug_mode) { printf("\n"); printf("***************************************\n"); printf("** **\n"); printf("** Testing range of years **\n"); printf("** **\n"); printf("***************************************\n\n"); } /* April 4, 1917 GMT */ et1.tm_usec = 0; et1.tm_sec = 0; et1.tm_min = 0; et1.tm_hour = 0; et1.tm_mday = 4; et1.tm_month = 4 - 1; et1.tm_year = 1917; et1.tm_params = PR_GMTParameters(&et1); PR_NormalizeTime(&et1, PR_LocalTimeParameters); secs = PR_ImplodeTime(&et1); if (LL_GE_ZERO(secs)) { if (debug_mode) printf("ERROR: April 4, 1917 GMT returns a nonnegative second count\n"); failed_already = 1; return 1; } PR_ExplodeTime(secs, PR_LocalTimeParameters, &et2); if (!explodedTimeIsEqual(&et1, &et2)) { if (debug_mode) printf("ERROR: PR_ImplodeTime and PR_ExplodeTime are not inverse for April 4, 1917 GMT\n"); failed_already=1; return 1; } ttt = PR_ImplodeTime(&et1); testParseTimeString( ttt ); if (debug_mode) printf("Test passed for April 4, 1917\n"); /* July 4, 2050 */ et1.tm_usec = 0; et1.tm_sec = 0; et1.tm_min = 0; et1.tm_hour = 0; et1.tm_mday = 4; et1.tm_month = 7 - 1; et1.tm_year = 2050; et1.tm_params = PR_GMTParameters(&et1); PR_NormalizeTime(&et1, PR_LocalTimeParameters); secs = PR_ImplodeTime(&et1); if (!LL_GE_ZERO(secs)) { if (debug_mode) printf("ERROR: July 4, 2050 GMT returns a negative second count\n"); failed_already = 1; return 1; } PR_ExplodeTime(secs, PR_LocalTimeParameters, &et2); if (!explodedTimeIsEqual(&et1, &et2)) { if (debug_mode) printf("ERROR: PR_ImplodeTime and PR_ExplodeTime are not inverse for July 4, 2050 GMT\n"); failed_already=1; return 1; } testParseTimeString(PR_ImplodeTime(&et1)); if (debug_mode) printf("Test passed for July 4, 2050\n"); } /* ************************************************************** ** ** Stress test * ** Go through four years, starting from ** 00:00:00 PST Jan. 1, 1993, incrementing ** every 10 minutes. ** ************************************************************** */ { PRExplodedTime et, et1, et2; PRInt64 usecPer10Min; int day, hour, min; PRTime usecs; int dstInEffect = 0; if (debug_mode) { printf("\n"); printf("*******************************************************\n"); printf("** **\n"); printf("** Stress test **\n"); printf("** Starting from midnight Jan. 1, 1993 PST, **\n"); printf("** going through four years in 10-minute increment **\n"); printf("** **\n"); printf("*******************************************************\n\n"); } LL_I2L(usecPer10Min, 600000000L); /* 00:00:00 PST Jan. 1, 1993 */ et.tm_usec = 0; et.tm_sec = 0; et.tm_min = 0; et.tm_hour = 0; et.tm_mday = 1; et.tm_month = 0; et.tm_year = 1993; et.tm_params.tp_gmt_offset = -8 * 3600; et.tm_params.tp_dst_offset = 0; usecs = PR_ImplodeTime(&et); for (day = 0; day < 4 * 365 + 1; day++) { for (hour = 0; hour < 24; hour++) { for (min = 0; min < 60; min += 10) { LL_ADD(usecs, usecs, usecPer10Min); PR_ExplodeTime(usecs, PR_USPacificTimeParameters, &et1); et2 = et; et2.tm_usec += 600000000L; PR_NormalizeTime(&et2, PR_USPacificTimeParameters); if (!explodedTimeIsEqual(&et1, &et2)) { if (debug_mode) printf("ERROR: componentwise comparison failed\n"); printExplodedTime(&et1); if (debug_mode) printf("\n"); printExplodedTime(&et2); if (debug_mode) printf("\n"); failed_already=1; return 1; } if (LL_NE(usecs, PR_ImplodeTime(&et1))) { if (debug_mode) printf("ERROR: PR_ExplodeTime and PR_ImplodeTime are not inverse\n"); printExplodedTime(&et1); if (debug_mode) printf("\n"); failed_already=1; return 1; } testParseTimeString(usecs); if (!dstInEffect && et1.tm_params.tp_dst_offset) { dstInEffect = 1; if (debug_mode) printf("DST changeover from "); printExplodedTime(&et); if (debug_mode) printf(" to "); printExplodedTime(&et1); if (debug_mode) printf(".\n"); } else if (dstInEffect && !et1.tm_params.tp_dst_offset) { dstInEffect = 0; if (debug_mode) printf("DST changeover from "); printExplodedTime(&et); if (debug_mode) printf(" to "); printExplodedTime(&et1); if (debug_mode) printf(".\n"); } et = et1; } } } if (debug_mode) printf("Test passed\n"); } /* Same stress test, but with PR_LocalTimeParameters */ { PRExplodedTime et, et1, et2; PRInt64 usecPer10Min; int day, hour, min; PRTime usecs; int dstInEffect = 0; if (debug_mode) { printf("\n"); printf("*******************************************************\n"); printf("** **\n"); printf("** Stress test **\n"); printf("** Starting from midnight Jan. 1, 1993 PST, **\n"); printf("** going through four years in 10-minute increment **\n"); printf("** **\n"); printf("*******************************************************\n\n"); } LL_I2L(usecPer10Min, 600000000L); /* 00:00:00 PST Jan. 1, 1993 */ et.tm_usec = 0; et.tm_sec = 0; et.tm_min = 0; et.tm_hour = 0; et.tm_mday = 1; et.tm_month = 0; et.tm_year = 1993; et.tm_params.tp_gmt_offset = -8 * 3600; et.tm_params.tp_dst_offset = 0; usecs = PR_ImplodeTime(&et); for (day = 0; day < 4 * 365 + 1; day++) { for (hour = 0; hour < 24; hour++) { for (min = 0; min < 60; min += 10) { LL_ADD(usecs, usecs, usecPer10Min); PR_ExplodeTime(usecs, PR_LocalTimeParameters, &et1); et2 = et; et2.tm_usec += 600000000L; PR_NormalizeTime(&et2, PR_LocalTimeParameters); if (!explodedTimeIsEqual(&et1, &et2)) { if (debug_mode) printf("ERROR: componentwise comparison failed\n"); printExplodedTime(&et1); if (debug_mode) printf("\n"); printExplodedTime(&et2); if (debug_mode) printf("\n"); return 1; } if (LL_NE(usecs, PR_ImplodeTime(&et1))) { printf("ERROR: PR_ExplodeTime and PR_ImplodeTime are not inverse\n"); printExplodedTime(&et1); if (debug_mode) printf("\n"); failed_already=1; return 1; } testParseTimeString(usecs); if (!dstInEffect && et1.tm_params.tp_dst_offset) { dstInEffect = 1; if (debug_mode) printf("DST changeover from "); printExplodedTime(&et); if (debug_mode) printf(" to "); printExplodedTime(&et1); if (debug_mode) printf(".\n"); } else if (dstInEffect && !et1.tm_params.tp_dst_offset) { dstInEffect = 0; if (debug_mode) printf("DST changeover from "); printExplodedTime(&et); if (debug_mode) printf(" to "); printExplodedTime(&et1); if (debug_mode) printf(".\n"); } et = et1; } } } if (debug_mode) printf("Test passed\n"); } /* Same stress test, but with PR_LocalTimeParameters and going backward */ { PRExplodedTime et, et1, et2; PRInt64 usecPer10Min; int day, hour, min; PRTime usecs; int dstInEffect = 0; if (debug_mode) { printf("\n"); printf("*******************************************************\n"); printf("** **\n"); printf("** Stress test **\n"); printf("** Starting from midnight Jan. 1, 1997 PST, **\n"); printf("** going back four years in 10-minute increment **\n"); printf("** **\n"); printf("*******************************************************\n\n"); } LL_I2L(usecPer10Min, 600000000L); /* 00:00:00 PST Jan. 1, 1997 */ et.tm_usec = 0; et.tm_sec = 0; et.tm_min = 0; et.tm_hour = 0; et.tm_mday = 1; et.tm_month = 0; et.tm_year = 1997; et.tm_params.tp_gmt_offset = -8 * 3600; et.tm_params.tp_dst_offset = 0; usecs = PR_ImplodeTime(&et); for (day = 0; day < 4 * 365 + 1; day++) { for (hour = 0; hour < 24; hour++) { for (min = 0; min < 60; min += 10) { LL_SUB(usecs, usecs, usecPer10Min); PR_ExplodeTime(usecs, PR_LocalTimeParameters, &et1); et2 = et; et2.tm_usec -= 600000000L; PR_NormalizeTime(&et2, PR_LocalTimeParameters); if (!explodedTimeIsEqual(&et1, &et2)) { if (debug_mode) printf("ERROR: componentwise comparison failed\n"); printExplodedTime(&et1); if (debug_mode) printf("\n"); printExplodedTime(&et2); if (debug_mode) printf("\n"); return 1; } if (LL_NE(usecs, PR_ImplodeTime(&et1))) { if (debug_mode) printf("ERROR: PR_ExplodeTime and PR_ImplodeTime are not inverse\n"); printExplodedTime(&et1); if (debug_mode) printf("\n"); failed_already=1; return 1; } testParseTimeString(usecs); if (!dstInEffect && et1.tm_params.tp_dst_offset) { dstInEffect = 1; if (debug_mode) printf("DST changeover from "); printExplodedTime(&et); if (debug_mode) printf(" to "); printExplodedTime(&et1); if (debug_mode) printf(".\n"); } else if (dstInEffect && !et1.tm_params.tp_dst_offset) { dstInEffect = 0; if (debug_mode) printf("DST changeover from "); printExplodedTime(&et); if (debug_mode) printf(" to "); printExplodedTime(&et1); if (debug_mode) printf(".\n"); } et = et1; } } } } if (failed_already) return 1; else return 0; }
// This is the function that looks for the first folder to purge. It also // applies retention settings to any folder that hasn't had retention settings // applied in mMinDelayBetweenPurges minutes (default, 8 hours). // However, if we've spent more than .5 seconds in this loop, don't // apply any more retention settings because it might lock up the UI. // This might starve folders later on in the hierarchy, since we always // start at the top, but since we also apply retention settings when you // open a folder, or when you compact all folders, I think this will do // for now, until we have a cleanup on shutdown architecture. nsresult nsMsgPurgeService::PerformPurge() { PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("performing purge")); nsresult rv; nsCOMPtr <nsIMsgAccountManager> accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv,rv); bool keepApplyingRetentionSettings = true; nsCOMPtr<nsISupportsArray> allServers; rv = accountManager->GetAllServers(getter_AddRefs(allServers)); if (NS_SUCCEEDED(rv) && allServers) { PRUint32 numServers; rv = allServers->Count(&numServers); PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("%d servers", numServers)); nsCOMPtr<nsIMsgFolder> folderToPurge; PRIntervalTime startTime = PR_IntervalNow(); PRInt32 purgeIntervalToUse; PRTime oldestPurgeTime = 0; // we're going to pick the least-recently purged folder // apply retention settings to folders that haven't had retention settings // applied in mMinDelayBetweenPurges minutes (default 8 hours) // Because we get last purge time from the folder cache, // this code won't open db's for folders until it decides it needs // to apply retention settings, and since nsIMsgFolder::ApplyRetentionSettings // will close any db's it opens, this code won't leave db's open. for (PRUint32 serverIndex=0; serverIndex < numServers; serverIndex++) { nsCOMPtr <nsIMsgIncomingServer> server = do_QueryElementAt(allServers, serverIndex, &rv); if (NS_SUCCEEDED(rv) && server) { if (keepApplyingRetentionSettings) { nsCOMPtr <nsIMsgFolder> rootFolder; rv = server->GetRootFolder(getter_AddRefs(rootFolder)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr <nsISupportsArray> childFolders = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = rootFolder->ListDescendents(childFolders); PRUint32 cnt = 0; childFolders->Count(&cnt); nsCOMPtr<nsISupports> supports; nsCOMPtr<nsIUrlListener> urlListener; nsCOMPtr<nsIMsgFolder> childFolder; for (PRUint32 index = 0; index < cnt; index++) { childFolder = do_QueryElementAt(childFolders, index); if (childFolder) { PRUint32 folderFlags; (void) childFolder->GetFlags(&folderFlags); if (folderFlags & nsMsgFolderFlags::Virtual) continue; PRTime curFolderLastPurgeTime = 0; nsCString curFolderLastPurgeTimeString, curFolderUri; rv = childFolder->GetStringProperty("LastPurgeTime", curFolderLastPurgeTimeString); if (NS_FAILED(rv)) continue; // it is ok to fail, go on to next folder if (!curFolderLastPurgeTimeString.IsEmpty()) { PRInt64 theTime; PR_ParseTimeString(curFolderLastPurgeTimeString.get(), PR_FALSE, &theTime); curFolderLastPurgeTime = theTime; } childFolder->GetURI(curFolderUri); PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("%s curFolderLastPurgeTime=%s (if blank, then never)", curFolderUri.get(), curFolderLastPurgeTimeString.get())); // check if this folder is due to purge // has to have been purged at least mMinDelayBetweenPurges minutes ago // we don't want to purge the folders all the time - once a day is good enough PRInt64 minDelayBetweenPurges(mMinDelayBetweenPurges); PRInt64 microSecondsPerMinute(60000000); PRTime nextPurgeTime = curFolderLastPurgeTime + (minDelayBetweenPurges * microSecondsPerMinute); if (nextPurgeTime < PR_Now()) { PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("purging %s", curFolderUri.get())); childFolder->ApplyRetentionSettings(); } PRIntervalTime elapsedTime; LL_SUB(elapsedTime, PR_IntervalNow(), startTime); // check if more than 500 milliseconds have elapsed in this purge process if (PR_IntervalToMilliseconds(elapsedTime) > 500) { keepApplyingRetentionSettings = PR_FALSE; break; } } } } nsCString type; nsresult rv = server->GetType(type); NS_ENSURE_SUCCESS(rv, rv); nsCAutoString contractid(NS_MSGPROTOCOLINFO_CONTRACTID_PREFIX); contractid.Append(type); nsCOMPtr<nsIMsgProtocolInfo> protocolInfo = do_GetService(contractid.get(), &rv); NS_ENSURE_SUCCESS(rv, PR_FALSE); nsCString realHostName; server->GetRealHostName(realHostName); PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("[%d] %s (%s)", serverIndex, realHostName.get(), type.get())); nsCOMPtr <nsISpamSettings> spamSettings; rv = server->GetSpamSettings(getter_AddRefs(spamSettings)); NS_ENSURE_SUCCESS(rv, rv); PRInt32 spamLevel; spamSettings->GetLevel(&spamLevel); PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("[%d] spamLevel=%d (if 0, don't purge)", serverIndex, spamLevel)); if (!spamLevel) continue; // check if we are set up to purge for this server // if not, skip it. bool purgeSpam; spamSettings->GetPurge(&purgeSpam); PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("[%d] purgeSpam=%s (if false, don't purge)", serverIndex, purgeSpam ? "true" : "false")); if (!purgeSpam) continue; // check if the spam folder uri is set for this server // if not skip it. nsCString junkFolderURI; rv = spamSettings->GetSpamFolderURI(getter_Copies(junkFolderURI)); NS_ENSURE_SUCCESS(rv,rv); PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("[%d] junkFolderURI=%s (if empty, don't purge)", serverIndex, junkFolderURI.get())); if (junkFolderURI.IsEmpty()) continue; // if the junk folder doesn't exist // because the folder pane isn't built yet, for example // skip this account nsCOMPtr<nsIMsgFolder> junkFolder; GetExistingFolder(junkFolderURI, getter_AddRefs(junkFolder)); PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("[%d] %s exists? %s (if doesn't exist, don't purge)", serverIndex, junkFolderURI.get(), junkFolder ? "true" : "false")); if (!junkFolder) continue; PRTime curJunkFolderLastPurgeTime = 0; nsCString curJunkFolderLastPurgeTimeString; rv = junkFolder->GetStringProperty("curJunkFolderLastPurgeTime", curJunkFolderLastPurgeTimeString); if (NS_FAILED(rv)) continue; // it is ok to fail, junk folder may not exist if (!curJunkFolderLastPurgeTimeString.IsEmpty()) { PRInt64 theTime; PR_ParseTimeString(curJunkFolderLastPurgeTimeString.get(), PR_FALSE, &theTime); curJunkFolderLastPurgeTime = theTime; } PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("[%d] %s curJunkFolderLastPurgeTime=%s (if blank, then never)", serverIndex, junkFolderURI.get(), curJunkFolderLastPurgeTimeString.get())); // check if this account is due to purge // has to have been purged at least mMinDelayBetweenPurges minutes ago // we don't want to purge the folders all the time PRTime nextPurgeTime = curJunkFolderLastPurgeTime + mMinDelayBetweenPurges * 60000000 /* convert mMinDelayBetweenPurges to into microseconds */; if (nextPurgeTime < PR_Now()) { PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("[%d] last purge greater than min delay", serverIndex)); nsCOMPtr <nsIMsgIncomingServer> junkFolderServer; rv = junkFolder->GetServer(getter_AddRefs(junkFolderServer)); NS_ENSURE_SUCCESS(rv,rv); bool serverBusy = false; bool serverRequiresPassword = true; bool passwordPromptRequired; bool canSearchMessages = false; junkFolderServer->GetPasswordPromptRequired(&passwordPromptRequired); junkFolderServer->GetServerBusy(&serverBusy); junkFolderServer->GetServerRequiresPasswordForBiff(&serverRequiresPassword); junkFolderServer->GetCanSearchMessages(&canSearchMessages); // Make sure we're logged on before doing the search (assuming we need to be) // and make sure the server isn't already in the middle of downloading new messages // and make sure a search isn't already going on PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("[%d] (search in progress? %s)", serverIndex, mSearchSession ? "true" : "false")); PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("[%d] (server busy? %s)", serverIndex, serverBusy ? "true" : "false")); PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("[%d] (serverRequiresPassword? %s)", serverIndex, serverRequiresPassword ? "true" : "false")); PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("[%d] (passwordPromptRequired? %s)", serverIndex, passwordPromptRequired ? "true" : "false")); if (canSearchMessages && !mSearchSession && !serverBusy && (!serverRequiresPassword || !passwordPromptRequired)) { PRInt32 purgeInterval; spamSettings->GetPurgeInterval(&purgeInterval); if ((oldestPurgeTime == 0) || (curJunkFolderLastPurgeTime < oldestPurgeTime)) { PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("[%d] purging! searching for messages older than %d days", serverIndex, purgeInterval)); oldestPurgeTime = curJunkFolderLastPurgeTime; purgeIntervalToUse = purgeInterval; folderToPurge = junkFolder; // if we've never purged this folder, do it... if (curJunkFolderLastPurgeTime == 0) break; } } else { NS_ASSERTION(canSearchMessages, "unexpected, you should be able to search"); PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("[%d] not a good time for this server, try again later", serverIndex)); } } else { PR_LOG(MsgPurgeLogModule, PR_LOG_ALWAYS, ("[%d] last purge too recent", serverIndex)); } } } if (folderToPurge) rv = SearchFolderToPurge(folderToPurge, purgeIntervalToUse); } // set up timer to check accounts again SetupNextPurge(); return rv; }
nsresult nsMsgSearchOfflineMail::Search (bool *aDone) { nsresult err = NS_OK; NS_ENSURE_ARG(aDone); nsresult dbErr = NS_OK; nsCOMPtr<nsIMsgDBHdr> msgDBHdr; nsMsgSearchBoolExpression *expressionTree = nsnull; const PRUint32 kTimeSliceInMS = 200; *aDone = false; // Try to open the DB lazily. This will set up a parser if one is required if (!m_db) err = OpenSummaryFile (); if (!m_db) // must be reparsing. return err; // Reparsing is unnecessary or completed if (NS_SUCCEEDED(err)) { if (!m_listContext) dbErr = m_db->EnumerateMessages (getter_AddRefs(m_listContext)); if (NS_SUCCEEDED(dbErr) && m_listContext) { PRIntervalTime startTime = PR_IntervalNow(); while (!*aDone) // we'll break out of the loop after kTimeSliceInMS milliseconds { nsCOMPtr<nsISupports> currentItem; dbErr = m_listContext->GetNext(getter_AddRefs(currentItem)); if(NS_SUCCEEDED(dbErr)) { msgDBHdr = do_QueryInterface(currentItem, &dbErr); } if (NS_FAILED(dbErr)) *aDone = true; //###phil dbErr is dropped on the floor. just note that we did have an error so we'll clean up later else { bool match = false; nsAutoString nullCharset, folderCharset; GetSearchCharsets(nullCharset, folderCharset); NS_ConvertUTF16toUTF8 charset(folderCharset); // Is this message a hit? err = MatchTermsForSearch (msgDBHdr, m_searchTerms, charset.get(), m_scope, m_db, &expressionTree, &match); // Add search hits to the results list if (NS_SUCCEEDED(err) && match) { AddResultElement (msgDBHdr); } PRIntervalTime elapsedTime; LL_SUB(elapsedTime, PR_IntervalNow(), startTime); // check if more than kTimeSliceInMS milliseconds have elapsed in this time slice started if (PR_IntervalToMilliseconds(elapsedTime) > kTimeSliceInMS) break; } } } } else *aDone = true; // we couldn't open up the DB. This is an unrecoverable error so mark the scope as done. delete expressionTree; // in the past an error here would cause an "infinite" search because the url would continue to run... // i.e. if we couldn't open the database, it returns an error code but the caller of this function says, oh, // we did not finish so continue...what we really want is to treat this current scope as done if (*aDone) CleanUpScope(); // Do clean up for end-of-scope processing return err; }