r38767 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r38766‎ | r38767 | r38768 >
Date:10:59, 7 August 2008
Author:mkroetzsch
Status:old
Tags:
Comment:
Fixed the utterly broken update job generation and execution during saving
Modified paths:
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_DataValueFactory.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_Factbox.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_Hooks.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/jobs/SMW_UpdateJob.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2.php (modified) (history)

Diff [purge]

Index: trunk/extensions/SemanticMediaWiki/includes/SMW_Hooks.php
@@ -15,6 +15,7 @@
1616 function smwfParserHook(&$parser, &$text) {
1717 global $smwgStoreAnnotations, $smwgTempStoreAnnotations, $smwgStoreActive;
1818 SMWFactbox::initStorage($parser->getTitle()); // be sure we have our title, strange things happen in parsing
 19+ SMWFactbox::setWritelock(true); // disallow changes to the title object by other hooks!
1920
2021 // store the results if enabled (we have to parse them in any case, in order to
2122 // clean the wiki source for further processing)
@@ -58,6 +59,7 @@
5960 'ExportRDF/' . $parser->getTitle()->getPrefixedText(), 'xmlmime=rdf'
6061 )) . "\" />");
6162
 63+ SMWFactbox::setWritelock(false); // free Factbox again (the hope of course is that it is only reset after the data we just gathered was processed; but this then might be okay, e.g. if some jobs are processed)
6264 return true; // always return true, in order not to stop MW's hook processing!
6365 }
6466
@@ -140,6 +142,7 @@
141143 // The hashes of all values of both arrays are taken, then sorted
142144 // and finally concatenated, thus creating one long hash out of each
143145 // of the data value arrays. These are compared.
 146+
144147 $values = array();
145148 foreach($dv1 as $v) $values[] = $v->getHash();
146149 sort($values);
@@ -148,8 +151,8 @@
149152 foreach($dv2 as $v) $values[] = $v->getHash();
150153 sort($values);
151154 $dv2hash = implode("___", $values);
152 -
153 - return ($dv1hash == $dv2hash);
 155+
 156+ return ($dv1hash == $dv2hash);
154157 }
155158
156159 /**
@@ -159,7 +162,7 @@
160163 * conversion factors have changed. If so, it triggers SMWUpdateJobs for the relevant articles,
161164 * which then asynchronously update the semantic data in the database.
162165 *
163 - * Known Bug -- TODO
 166+ * Known bug/limitation -- TODO
164167 * Updatejobs are triggered when a property or type definition has
165168 * changed, so that all affected pages get updated. However, if a page
166169 * uses a property but the given value caused an error, then there is
@@ -169,43 +172,49 @@
170173 function smwfSaveDataForTitle($title) {
171174 global $smwgEnableUpdateJobs;
172175 $namespace = $title->getNamespace();
 176+ $processSemantics = smwfIsSemanticsProcessed($namespace);
 177+ if ($processSemantics) {
 178+ $newdata = SMWFactbox::$semdata;
 179+ } else { // nothing stored, use empty container
 180+ $dv = SMWDataValueFactory::newTypeIDValue('_wpg');
 181+ $dv->setValues($title->getDBkey(), $title->getNamespace());
 182+ $newdata = new SMWSemanticData($dv);
 183+ }
173184
174185 // Check if the semantic data has been changed.
175186 // Sets the updateflag to true if so.
 187+ // Careful: storage access must happen *before* the storage update;
 188+ // even finding uses of a property fails after its type was changed.
176189 $updatejobflag = false;
 190+ $jobs = array();
177191 if ($smwgEnableUpdateJobs && ($namespace == SMW_NS_PROPERTY) ) {
178192 // if it is a property, then we need to check if the type or
179 - // the allowed values have been changed
 193+ // the allowed values have been changed
180194 $oldtype = smwfGetStore()->getSpecialValues($title, SMW_SP_HAS_TYPE);
181 - $newtype = SMWFactbox::$semdata->getPropertyValues(SMW_SP_HAS_TYPE);
182 -
183 - if (smwfEqualDatavalues($oldtype, $newtype)) {
 195+ $newtype = $newdata->getPropertyValues(SMW_SP_HAS_TYPE);
 196+
 197+ if (!smwfEqualDatavalues($oldtype, $newtype)) {
184198 $updatejobflag = true;
185199 } else {
186200 $oldvalues = smwfGetStore()->getSpecialValues($title, SMW_SP_POSSIBLE_VALUE);
187 - $newvalues = SMWFactbox::$semdata->getPropertyValues(SMW_SP_POSSIBLE_VALUE);
188 - $updatejobflag = smwfEqualDatavalues($oldvalues, $newvalues);
 201+ $newvalues = $newdata->getPropertyValues(SMW_SP_POSSIBLE_VALUE);
 202+ $updatejobflag = !smwfEqualDatavalues($oldvalues, $newvalues);
189203 }
190 - } elseif ($smwgEnableUpdateJobs && ($namespace == SMW_NS_TYPE) ) {
191 - // if it is a type we need to check if the conversion factors have been changed
192 - $oldfactors = smwfGetStore()->getSpecialValues($title, SMW_SP_CONVERSION_FACTOR);
193 - $newfactors = SMWFactbox::$semdata->getPropertyValues(SMW_SP_CONVERSION_FACTOR);
194 - $updatejobflag = smwfEqualDatavalues($oldfactors, $newfactors);
195 - }
196204
197 - // Actually store semantic data
198 - SMWFactbox::storeData(smwfIsSemanticsProcessed($title->getNamespace()));
199 -
200 - // Trigger relevant Updatejobs if necessary
201 - if ($updatejobflag) {
202 - $jobs = array();
203 - $store = smwfGetStore();
204 - if ($namespace == SMW_NS_PROPERTY) {
205 - $subjects = $store->getAllPropertySubjects($title);
 205+ if ($updatejobflag) {
 206+ $subjects = smwfGetStore()->getAllPropertySubjects($title);
206207 foreach ($subjects as $subject) {
207208 $jobs[] = new SMWUpdateJob($subject);
208209 }
209 - } elseif ($namespace == SMW_NS_TYPE) {
 210+ }
 211+ } elseif ($smwgEnableUpdateJobs && ($namespace == SMW_NS_TYPE) ) {
 212+ // if it is a type we need to check if the conversion factors have been changed
 213+ $oldfactors = smwfGetStore()->getSpecialValues($title, SMW_SP_CONVERSION_FACTOR);
 214+ $newfactors = $newdata->getPropertyValues(SMW_SP_CONVERSION_FACTOR);
 215+ $updatejobflag = !smwfEqualDatavalues($oldfactors, $newfactors);
 216+ if ($updatejobflag) {
 217+ $store = smwfGetStore();
 218+ /// FIXME: this would kill large wikis! Use incremental updates!
210219 $dv = SMWDataValueFactory::newSpecialValue(SMW_SP_HAS_TYPE,$title->getDBkey());
211220 $subjects = $store->getSpecialSubjects(SMW_SP_HAS_TYPE, $dv);
212221 foreach ($subjects as $valueofpropertypagestoupdate) {
@@ -216,6 +225,13 @@
217226 }
218227 }
219228 }
 229+ }
 230+
 231+ // Actually store semantic data
 232+ SMWFactbox::storeData($processSemantics);
 233+
 234+ // Trigger relevant Updatejobs if necessary
 235+ if ($updatejobflag) {
220236 Job::batchInsert($jobs); ///NOTE: this only happens if $smwgEnableUpdateJobs was true above
221237 }
222238 return true;
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_Factbox.php
@@ -36,12 +36,19 @@
3737 static protected $m_blocked = false;
3838
3939 /**
 40+ * True *while* the Factbox is used for writing, prevents
 41+ * broken submethods of MW and extensions to screw up our
 42+ * subject title due to illegal $wgTitle uses in parsing.
 43+ */
 44+ static protected $m_writelock = false;
 45+
 46+ /**
4047 * Initialisation method. Must be called before anything else happens.
4148 */
4249 static function initStorage($title) {
4350 // reset only if title exists, is new and is not the notorious
4451 // NO TITLE thing the MW parser creates
45 - if ( $title === NULL || $title->getText() == 'NO TITLE' ) return;
 52+ if ( SMWFactbox::$m_writelock || $title === NULL || $title->getText() == 'NO TITLE' ) return;
4653 if ( (SMWFactbox::$semdata === NULL) ||
4754 (SMWFactbox::$semdata->getSubject()->getDBkey() != $title->getDBkey()) ||
4855 (SMWFactbox::$semdata->getSubject()->getNamespace() != $title->getNamespace()) ) {
@@ -64,7 +71,7 @@
6572 SMWFactbox::$m_printed = false;
6673 }
6774 }
68 -
 75+
6976 /**
7077 * Blocks the next rendering of the Factbox
7178 */
@@ -73,6 +80,15 @@
7481 }
7582
7683 /**
 84+ * Set the writlock (true while the Factbox is used for writing,
 85+ * ensures that our title object cannot be changed by cross-firing
 86+ * hooks).
 87+ */
 88+ static function setWriteLock($value) {
 89+ SMWFactbox::$m_writelock = $value;
 90+ }
 91+
 92+ /**
7793 * True if the respective article is newly created, but always false until
7894 * an article is actually saved.
7995 */
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore.php
@@ -930,6 +930,11 @@
931931 if (count($up_nary_longstrings) > 0) {
932932 $db->insert( 'smw_nary_longstrings', $up_nary_longstrings, 'SMW::updateNAryLongData');
933933 }
 934+
 935+ if ($subject->getNamespace() == SMW_NS_PROPERTY) { // be sure that this is not invalid after update
 936+ SMWDataValueFactory::clearTypeCache($subject);
 937+ }
 938+
934939 wfProfileOut("SMWSQLStore::updateData (SMW)");
935940 }
936941
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2.php
@@ -675,6 +675,7 @@
676676 ///FIXME: if a property page is deleted, more pages may need to be updated by jobs!
677677 ///TODO: who is responsible for these updates? Some update jobs are currently created in SMW_Hooks, some internally in the store
678678 ///TODO: Possibly delete ID here (at least for non-properties/categories, if not used in any place in rels2)
 679+ ///FIXME: clean internal caches here
679680 wfProfileOut('SMWSQLStore2::deleteSubject (SMW)');
680681 }
681682
@@ -838,6 +839,12 @@
839840 $db->insert( 'smw_conc2', $up_conc2, 'SMW::updateConc2Data');
840841 }
841842
 843+ $this->m_semdata[$sid] = clone $data; // update cache, important if jobs are directly following this call
 844+ $this->m_sdstate[$sid] = 0xFFFFFFFF; // everything that one can know
 845+ if ($subject->getNamespace() == SMW_NS_PROPERTY) { // be sure that this is not invalid after update
 846+ SMWDataValueFactory::clearTypeCache($subject->getTitle());
 847+ }
 848+
842849 wfProfileOut("SMWSQLStore2::updateData (SMW)");
843850 }
844851
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DataValueFactory.php
@@ -225,6 +225,17 @@
226226 }
227227
228228 /**
 229+ * Signal the class that the type of some property has changed. Clearing this
 230+ * is crucial to let subsequent jobs work properly.
 231+ */
 232+ static public function clearTypeCache(Title $property) {
 233+ $propertyname = $property->getText();
 234+ if (array_key_exists($propertyname, SMWDataValueFactory::$m_typebyproperty)) {
 235+ unset(SMWDataValueFactory::$m_typebyproperty[$propertyname]);
 236+ }
 237+ }
 238+
 239+ /**
229240 * Gather all available datatypes and label<=>id<=>datatype associations. This method
230241 * is called before most methods of this factory.
231242 */
Index: trunk/extensions/SemanticMediaWiki/includes/jobs/SMW_UpdateJob.php
@@ -56,7 +56,7 @@
5757 wfProfileOut( __METHOD__.'-parse' );
5858 wfProfileIn( __METHOD__.'-update' );
5959
60 - SMWFactbox::storeData(true); /// FIXME: why is this just fixed to "true"?
 60+ SMWFactbox::storeData(smwfIsSemanticsProcessed($this->title->getNamespace()));
6161 wfProfileOut( __METHOD__.'-update' );
6262 wfProfileOut('SMWUpdateJob::run (SMW)');
6363 return true;

Status & tagging log