From 0347768811284f62ab5f885f689f3028a71fe48b Mon Sep 17 00:00:00 2001 From: Joachim Lingner Date: Wed, 15 Sep 2010 10:00:35 +0200 Subject: jl160 #i114509# installation hangs when installing on nfs volume --- jvmfwk/source/elements.cxx | 93 ++++++++++++++++++++++++++++++++++++---------- jvmfwk/source/elements.hxx | 28 ++++++++++++++ 2 files changed, 102 insertions(+), 19 deletions(-) (limited to 'jvmfwk') diff --git a/jvmfwk/source/elements.cxx b/jvmfwk/source/elements.cxx index c4e44f7ac375..606929375915 100644 --- a/jvmfwk/source/elements.cxx +++ b/jvmfwk/source/elements.cxx @@ -51,16 +51,16 @@ using namespace osl; namespace jfw { -rtl::OString getElementUpdated() +rtl::OString getElement(::rtl::OString const & docPath, + xmlChar const * pathExpression, bool bThrowIfEmpty) { //Prepare the xml document and context - rtl::OString sSettingsPath = jfw::getVendorSettingsPath(); - OSL_ASSERT(sSettingsPath.getLength() > 0); - jfw::CXmlDocPtr doc(xmlParseFile(sSettingsPath.getStr())); + OSL_ASSERT(docPath.getLength() > 0); + jfw::CXmlDocPtr doc(xmlParseFile(docPath.getStr())); if (doc == NULL) throw FrameworkException( JFW_E_ERROR, - rtl::OString("[Java framework] Error in function getElementUpdated " + rtl::OString("[Java framework] Error in function getElement " "(elements.cxx)")); jfw::CXPathContextPtr context(xmlXPathNewContext(doc)); @@ -68,20 +68,42 @@ rtl::OString getElementUpdated() (xmlChar*) NS_JAVA_FRAMEWORK) == -1) throw FrameworkException( JFW_E_ERROR, - rtl::OString("[Java framework] Error in function getElementUpdated " + rtl::OString("[Java framework] Error in function getElement " "(elements.cxx)")); + CXPathObjectPtr pathObj; - pathObj = xmlXPathEvalExpression( - (xmlChar*)"/jf:javaSelection/jf:updated/text()", context); + pathObj = xmlXPathEvalExpression(pathExpression, context); + rtl::OString sValue; if (xmlXPathNodeSetIsEmpty(pathObj->nodesetval)) - throw FrameworkException( - JFW_E_ERROR, - rtl::OString("[Java framework] Error in function getElementUpdated " - "(elements.cxx)")); - rtl::OString sValue = (sal_Char*) pathObj->nodesetval->nodeTab[0]->content; + { + if (bThrowIfEmpty) + throw FrameworkException( + JFW_E_ERROR, + rtl::OString("[Java framework] Error in function getElement " + "(elements.cxx)")); + } + else + { + sValue = (sal_Char*) pathObj->nodesetval->nodeTab[0]->content; + } return sValue; } +rtl::OString getElementUpdated() +{ + return getElement(jfw::getVendorSettingsPath(), + (xmlChar*)"/jf:javaSelection/jf:updated/text()", true); +} + +// Use only in INSTALL mode !!! +rtl::OString getElementModified() +{ + //The modified element is only written in INSTALL mode. + //That is NodeJava::m_layer = INSTALL + return getElement(jfw::getInstallSettingsPath(), + (xmlChar*)"/jf:java/jf:modified/text()", false); +} + void createSettingsStructure(xmlDoc * document, bool * bNeedsSave) { @@ -579,6 +601,21 @@ void NodeJava::write() const xmlAddChild(jreLocationsNode, nodeCrLf); } } + + if (INSTALL == m_layer) + { + //now write the current system time + ::TimeValue curTime = {0,0}; + if (::osl_getSystemTime(& curTime)) + { + rtl::OUString sSeconds = + rtl::OUString::valueOf((sal_Int64) curTime.Seconds); + xmlNewTextChild( + root,NULL, (xmlChar*) "modified", CXmlCharPtr(sSeconds)); + xmlNode * nodeCrLf = xmlNewText((xmlChar*) "\n"); + xmlAddChild(root, nodeCrLf); + } + } if (xmlSaveFormatFile(sSettingsPath.getStr(), docUser, 1) == -1) throw FrameworkException(JFW_E_ERROR, sExcMsg); } @@ -721,7 +758,7 @@ jfw::FileStatus NodeJava::checkSettingsFileStatus() const File::RC rc_stat = item.getFileStatus(stat); if (File::E_None == rc_stat) { - //ToDo we remove the file and create it shortly after. This + // This //function may be called multiple times when a java is started. //If the expiretime is too small then we may loop because everytime //the file is deleted and we need to search for a java again. @@ -732,20 +769,27 @@ jfw::FileStatus NodeJava::checkSettingsFileStatus() const //that after removing the file and shortly later creating it again //did not change the creation time. That is the newly created file //had the creation time of the former file. -// ::TimeValue time = stat.getCreationTime(); - ::TimeValue modTime = stat.getModifyTime(); + // ::TimeValue modTime = stat.getModifyTime(); ::TimeValue curTime = {0,0}; + ret = FILE_OK; if (sal_True == ::osl_getSystemTime(& curTime)) { - if ( curTime.Seconds - modTime.Seconds > + //get the modified time recorded in the element + sal_uInt32 modified = getModifiedTime(); + OSL_ASSERT(modified <= curTime.Seconds); + //Only if modified has a valued then NodeJava::write was called, + //then the xml structure was filled with data. + + if ( modified && curTime.Seconds - modified > BootParams::getInstallDataExpiration()) { #if OSL_DEBUG_LEVEL >=2 + fprintf(stderr, "[Java framework] Settings file is %d seconds old. \n", + (int)( curTime.Seconds - modified)); rtl::OString s = rtl::OUStringToOString(sURL, osl_getThreadTextEncoding()); - fprintf(stderr, "[Java framework] Deleting settings file at \n%s\n", s.getStr()); + fprintf(stderr, "[Java framework] Settings file is exspired. Deleting settings file at \n%s\n", s.getStr()); #endif //delete file -// File::RC rc_rem = File::remove(sURL); File f(sURL); if (File::E_None == f.open(OpenFlag_Write | OpenFlag_Read) && File::E_None == f.setPos(0, 0) @@ -1083,6 +1127,17 @@ JavaInfo * CNodeJavaInfo::makeJavaInfo() const return pInfo; } +sal_uInt32 NodeJava::getModifiedTime() const +{ + sal_uInt32 ret = 0; + if (m_layer != INSTALL) + { + OSL_ASSERT(0); + return ret; + } + rtl::OString modTimeSeconds = getElementModified(); + return (sal_uInt32) modTimeSeconds.toInt64(); +} //================================================================================ MergedSettings::MergedSettings(): diff --git a/jvmfwk/source/elements.hxx b/jvmfwk/source/elements.hxx index a4ca1a83fc3d..ec0e06dc5bab 100644 --- a/jvmfwk/source/elements.hxx +++ b/jvmfwk/source/elements.hxx @@ -195,6 +195,34 @@ private: */ boost::optional< ::std::vector< ::rtl::OUString> > m_JRELocations; + /** Only in INSTALL mode. Then NodeJava.write writes a element + which contains the seconds value of the TimeValue (osl/time.h), obtained + with osl_getSystemTime. + It returns 0 if the value cannot be obtained. + This is used to fix the problem that the modified time of the settings + file is incorrect because it resides on an NFS volume where the NFS + server and NFS client do not have the same system time. For example if + the server time is ahead of the client time then checkSettingsFileStatus + deleted the settings. So even if javaldx determined a Java + (jfw_findAndSelectJRE) then jfw_startVM returned a JFW_E_NO_SELECT. Then + it looked again for a java by calling jfw_findAndSelectJRE, which + returned a JFW_E_NONE. But the following jfw_startVM returned again + JFW_E_NO_SELECT. So it looped. (see issue i114509) + + NFS server and NFS client should have the same time. It is common + practise to enforce this in networks. We actually should not work + around a malconfigured network. We must however, make sure that we do + not loop. Maybe a better approach is, that: + - assume that mtime and system time are reliable + - checkSettingsFile uses system time and mtime of the settings file, + instset of using getModifiedTime. + - allow a small error margin + - jfw_startVM must return a JFW_E_EXPIRED_SETTINGS + - XJavaVM::startVM should prevent the loop by processing the new return+ value + + */ + sal_uInt32 getModifiedTime() const; + public: NodeJava(Layer theLayer = USER_OR_INSTALL); -- cgit