05
On Tuesday night, thanks to the invaluable efforts of a friend, the problem with How To Use Wiki was identified and solved.
As I mentioned before, the table phpwiki_version stores the contents of the pages, and each version of the same page is identified by a number in the field `version`. I also mentioned that How To Use Wiki had a nonconsecutive set of version numbers in that database. This was not the problem after all. However, the version numbers were related to the error.
Another table, phpwiki_recent, has a field called `latestversion` in which it stores the version number of the latest version of each page. However, for the How To Use Wiki page, this field contained the version number 61, whereas the phpwiki_version table had no version after 60. I changed the value for the page in phpwiki_recent.latestversion to 60, and now the page works fine again.
In addition, the page Php Wiki Documentation, which had been showing the same error message, worked fine after How To Use Wiki was dealt with. I guess the problem with that page was that it dynamically interacted with How To Use Wiki via the Site Map Plugin, which generates output based on the contents of other pages, including, in this case, the page that was broken.
I feared, though, that these two pages weren't the only ones with problems, but I didn't know which other pages were messed up. I have tried to devise a MySQL query to check the phpwiki_recent table for any `latestversion` numbers that aren't in the phpwiki_version database, but I haven't come up with one that works.
Today, by clicking on pages randomly selected from the list of All Pages, I was able to find a whole bunch of calendar entries for How To Use Wiki, almost all of which gave the same error message as before. I arbitrarily picked How To Use Wiki/2004-08-10 for initial scrutiny. As it turns out, this page had no entries at all in the phpwiki_version table, but the phpwiki_recent table listed it with `latestversion` = 1. I reset that to 0. When a page is version 0, then automatically it contains the text "Describe [pagename] here." This case was no different. What was odd, though, is that the links to it looked like links to existing pages, rather than links to pages that don't currently exist, like This Page Should Not Exist, and it still showed up on the list of All Pages.
Therefore, I went to the page using the wiki administrative access and deleted the page. I discovered that sure enough, it had disappeared from the list of All Pages, and so had the dozens of other calendar entries with the same problem. So at present I know of no more pages with that problem, but it would still be nice to come up with a good MySQL query to make sure. It should be something like the following (except it should work):
SELECT phpwiki_recent.id FROM phpwiki_recent WHERE phpwiki_recent.latestversion NOT IN(SELECT phpwiki_version.id, phpwiki_version.version FROM phpwiki_version where phpwiki_recent.id = phpwiki_version.id)
10/20/05:
This problem is beyound my meager sql knowledge.
There are some pages on umcp.org which used to work, but now produce the following error message:
lib/WikiDB.php:597: Fatal[0]: <br />/home/umcp/umcp.org/data/lib/WikiDB.php:597: : Assertion failed <br /> Fatal PhpWiki Error lib/WikiDB.php:597: Fatal[0]: <br />/home/umcp/umcp.org/data/lib/WikiDB.php:597: : Assertion failed <br />
The pages producing this error include the very important "How To Use Wiki" page
(
http://umcp.org/index.php/HowToUseWiki), which is the one I've been investigating
most closely.
In an attempt to deal with this problem, I've been staring at the database backend. The database used for the wiki is designated 'umcp' on the server, mutualaid.org
It consists of several tables:
The tables with the prefix "phpwiki_" appear to be the ones currently in use. The others with corresponding names are the equivalent tables from the previous version of the software, I think.
Anyhow, the table "phpwiki_page" contains the unique name for each page (e.g., "How To Use Wiki") and its corresponding numerical id (in this case, 28). These variables are called `pagename` (of type varchar(100)) and `id` (of type int(11)). I'm using the ` character because it's sql.
So, having determined that "How To Use Wiki" has `id` = 28, I check the table "phpwiki_version" which contains the contents of each saved version of each page. This variable is known as `content`. I search for all pages with `id`=28 and find that there are seemingly valid entries.
A POSSIBLE CLUE
Another variable in the "phpwiki_version" table is `version`, which, as you might expect, is an integer that gets incremented by 1 every time a page is edited (minor edit or no). The most recent version of "How To Use Wiki" is number 60. However, the most recent version before that is not 59 as you would expect, but 57.
Now, I can see how this might cause problems with the Page History function for that
page, or other stuff related to its past versions, but I'm not positive it's the
culprit with the current problem. Interestingly, when I look at the page with all
recorded changes
(
http://umcp.org/index.php/RecentChanges?days=), I find no links to How To Use Wiki,
even though the most recent version, according to the database, was saved on May 4,
2005, well within the time period covered (the "phpwiki_version" table has a
variable called `mtime`, and its value for the most recent version is 1115237566).
I'm not absolutely certain how the discontinuity in version number arose. However, I have a good idea: On occassion, spambots have created huge numbers of bogus pages on the site, requiring administrative action to get rid of those pages. This action consists of going to the database and searching for all table entries with the IP address of the offending spambot and deleting those entries.
Another page that produces the aforementioned error is "Php Wiki Documentation" (
http://umcp.org/index.php/PhpWikiDocumentation). Its database entry has all
previous versions consecutive, no breaks in the order.
line 597 in WikiDB.php is in the following function:
/**
* Get the most recent revision of a page.
*
* @access public
*
* @return WikiDB_PageRevision The current WikiDB_PageRevision object.
*/
function getCurrentRevision() {
$backend = &$this->_wikidb->_backend;
$cache = &$this->_wikidb->_cache;
$pagename = &$this->_pagename;
$backend->lock();
$version = $cache->get_latest_version($pagename);
$revision = $this->getRevision($version);
$backend->unlock();
assert($revision);
return $revision;
}
The line is "assert($revision);" which is where the "assertion failed" error message comes from. The lines above certainly suggest that nonconsecutive version numbers could cause the problem.
Let's look at function get_latest_version (and shouldn't it be called "getLatestVersion"?)
function get_latest_version($pagename) {
if(defined('USECACHE')){
assert (is_string($pagename) && $pagename);
$cache = &$this->_glv_cache;
if (!isset($cache[$pagename])) {
$cache[$pagename] = $this->_backend->get_latest_version($pagename);
if (empty($cache[$pagename]))
$cache[$pagename] = 0;
}
return $cache[$pagename];}
else {
return $this->_backend->get_latest_version($pagename);
}
}
This doesn't make much sense to me. It looks like a recursive function, or something, and anyhow, it doesn't have any obvious reason why it's crapping out.
The GetRevision function follows the "GetCurrentRevision" function, in which the assertion fails. Here it is:
/**
* Get a specific revision of a WikiDB_Page.
*
* @access public
*
* @param integer $version Which revision to get.
*
* @return WikiDB_PageRevision The requested WikiDB_PageRevision object, or
* false if the requested revision does not exist in the {@link WikiDB}.
* Note that version zero of any page always exists.
*/
function getRevision($version) {
$cache = &$this->_wikidb->_cache;
$pagename = &$this->_pagename;
if ($version == 0)
return new WikiDB_PageRevision($this->_wikidb, $pagename, 0);
assert($version > 0);
$vdata = $cache->get_versiondata($pagename, $version);
if (!$vdata)
return false;
return new WikiDB_PageRevision($this->_wikidb, $pagename, $version,
$vdata);
}
So this returns zero when it's asked to look for a version number that is not present in the database. The question then becomes, what version numbers (that aren't there, I guess) is it looking for in the pages with errors, and why?
Further questions: Is this a bug in the software to be fixed? Is it a corrupted database? How to deal with this without having to screw up the whole site?
10/21/05:
A real computer programmer advises me that
The get_latest_version function you put on the diary is not recursive, it's a rapper around
$this->_backend->get_latest_version
which is a different function of the same name which is a member of a different class. that function is returning 0, FALSE or some similar value. Can you find the code of that function?
So far, I haven't found that code. It's not in the file WikiDB.php
Anyhow, one thing I note is that the line that craps out:
assert($revision);
has an argument with a value of 0 or "false".
The argument, $revision, is defined 2 lines up:
$revision = $this->getRevision($version);
Now, looking down at the getRevision function, it looks like it returns something non-zero and non-false if $version==0 (the defaut version number 0 of a page, you may recall, is "Describe [pagename] here."). On the other hand, if $version<>0, then it does the following:
assert($version > 0);
//this line does not crap out, so we may safely assume that $version > 0
$vdata = $cache->get_versiondata($pagename, $version);
if (!$vdata)
return false;
So get_versiondata($pagename,$version) is returning a zero or false value, causing getRevision to return false, causing the fatal error.
The function get_versiondata is another wrapper, and an ugly one:
function get_versiondata($pagename, $version, $need_content = false) {
// FIXME: Seriously ugly hackage
if (defined ('USECACHE')){ //temporary - for debugging
assert(is_string($pagename) && $pagename);
// there is a bug here somewhere which results in an assertion failure at line 105
// of ArchiveCleaner.php It goes away if we use the next line.
$need_content = true;
$nc = $need_content ? '1':'0';
$cache = &$this->_versiondata_cache;
if (!isset($cache[$pagename][$version][$nc])||
!(is_array ($cache[$pagename])) || !(is_array($cache[$pagename][$version]))) {
$cache[$pagename][$version][$nc] =
$this->_backend->get_versiondata($pagename,$version, $need_content);
// If we have retrieved all data, we may as well set the cache for $need_content = false
if($need_content){
$cache[$pagename][$version]['0'] = $cache[$pagename][$version]['1'];
}
}
$vdata = $cache[$pagename][$version][$nc];
}
else
{
$vdata = $this->_backend->get_versiondata($pagename, $version,$need_content);
}
// FIXME: ugly
if ($vdata && !empty($vdata['%pagedata']))
$this->_pagedata_cache[$pagename] = $vdata['%pagedata'];
return $vdata;
}
This doesn't have any "return 0" or "return false" commands, just "return $vdata", so it's presumably the output of "$this->_backend->get_versiondata" that is returning a 0 or "false" value.
So I need to find the code for "$this->_backend->get_latest_version" and for "$this->_backend->get_versiondata". They're not in WikiDB.php
I am now informed, by another real computer programmer:
I'm guessing MySQL got updated and something broke. Phpwiki is mostly object oriented PHP, so that generic wrapper classes get put around the more specific backend code. _backend should be the database backend, you'll see a directory in /home/umcp/umcp.org/data/lib/ that should be something like DB/ or WikiDB/ and which will have a Mysql class that contains a method called get_latest_version.
I will get on this shortly.
As per the above quote, I found the directory /home/umcp/umcp.org/data/lib/WikiDB, which contains the file backend.php, which has the class WikiDB_backend, and the functions get_latest_version and get_versiondata. However, the text of these does little to illuminate the problem, at least to me. Here they are:
/**
* Get the current version number for a page.
*
* @param $pagename string Page name.
* @return int The latest version number for the page. Returns zero if
* no versions of a page exist.
*/
function get_latest_version($pagename) {
trigger_error("virtual", E_USER_ERROR);
}
/**
* Get revision meta-data and content.
*
* @param $pagename string Page name.
* @param $version integer Which version to get.
* @param $want_content boolean
* Indicates the caller really wants the page content. If this
* flag is not set, the backend is free to skip fetching of the
* page content (as that may be expensive). If the backend omits
* the content, the backend might still want to set the value of
* '%content' to the empty string if it knows there's no content.
*
* @return hash The version data, or false if specified version does not
* exist.
*
* Some keys which might be present in the $versiondata hash are:
* <dl>
* <dt> %content
* <dd> This is a pseudo-meta-data element (since it's actually
* the page data, get it?) containing the page content.
* If the content was not fetched, this key may not be present.
* </dl>
* For description of other version meta-data see WikiDB_PageRevision::get().
* @see WikiDB_PageRevision::get
*/
function get_versiondata($pagename, $version, $want_content = false) {
trigger_error("virtual", E_USER_ERROR);
}
The error message that you get for trying to look at one of these nonworking pages does not include the word "virtual", so I don't think that these trigger_error functions are getting used. I still don't see how get_latest_version and get_versiondata work, though, but I will keep at it.
The real functions appear to be in class WikiDB_backend_PearDB (in a file called PearDB.php), which extends class WikiDB_backend. Here, at last, they are:
function get_latest_version($pagename) {
$dbh = &$this->_dbh;
extract($this->_table_names);
return
(int)$dbh->getOne(sprintf("SELECT latestversion"
. " FROM $page_tbl, $recent_tbl"
. " WHERE $page_tbl.id=$recent_tbl.id"
. " AND pagename='%s'",
$dbh->quoteString($pagename)));
}
/**
* Get version data.
*
* @param $version int Which version to get.
*
* @return hash The version data, or false if specified version does not
* exist.
*/
function get_versiondata($pagename, $version, $want_content = false) {
$dbh = &$this->_dbh;
extract($this->_table_names);
assert(!empty($pagename));
assert($version > 0);
//trigger_error("GET_REVISION $pagename $version $want_content", E_USER_NOTICE);
// FIXME: optimization: sometimes don't get page data?
if ($want_content) {
$fields = "*";
}
else {
$fields = ("$page_tbl.*,"
. "mtime,minor_edit,versiondata,"
. "content<>'' AS have_content");
}
$result = $dbh->getRow(sprintf("SELECT $fields"
. " FROM $page_tbl, $version_tbl"
. " WHERE $page_tbl.id=$version_tbl.id"
. " AND pagename='%s'"
. " AND version=%d",
$dbh->quoteString($pagename), $version),
DB_FETCHMODE_ASSOC);
return $this->_extract_version_data($result);
}
<small>P
brazilian singles single malt singles australian singles
singles trips bay area singles
the fist fisting fists large insertions
gaping weird insertions
www xxx xxx older women xxx mature sex
xxx anime spring break xxx
bbw models bbw photos plump plump
chubby girl pics bbw download
latex video latex mode latex style photos latex
latex models sex fetish latex
amateur strippers amateur upskirts hairy amateur amateur radio antennas
voyeur total mature amateur nude
?|
club asia hardcore asian anal asian porn stars asian dvds
asian chat room uk asian dating
tgirls tgirl pics bob\'s tgirls shemaleyum com
frank silvera frank silvera
</small>