News:

Want to get involved in developing SMF, then why not lend a hand on our github!

Main Menu

grandchild new posts did not add into parent board after 2 lelvels

Started by julia_yl, February 14, 2010, 05:36:19 PM

Previous topic - Next topic

julia_yl

SMF 2.0 RC2
as the title it could not count new posts from grandchild to grandparent?
only child add to parent?

Arantor

It does that for performance reasons - it is intentional, not a bug.

To change it is a change to the code.

julia_yl

Ince install, never changed a cold, should I install again?
I am bothered by the total calculate to be lost from grandchild. :'(

Arantor

Reinstalling won't change a thing. It is how the code is deliberately and intentionally written for performance reasons. IT IS NOT A BUG.

That said, it is possible to change if you want to slow your forum down by editing Subs-BoardIndex.php.

julia_yl

well, how can I fix it? any resolvent?
or show any board of grandchild in here that be counted upto grandparent , more than 3 generation?
:'(

Arantor

There probably is, by untangling the logic in Subs-BoardIndex, but seriously the extra overhead of doing it is surprisingly large, and is to be AVOIDED IF AT ALL POSSIBLE.

It may be possible - though FIRMLY UNTESTED - to simply remove the skip rule:
// Found a child of a child - skip.
else
continue;

julia_yl

Thanks ,but does not work  :'(
// Found a child of a child - skip.
      //else  //by julia because of board total could not count more than 3 generation
         //continue; by julia

Arantor


Caltan

Hi, I  know this thread is a little old, but it's the most recent I can find on this topic.

By "doesn't work," in my case commenting out those lines changes nothing, even after clearing forum cache and recounting all forum totals.  The main board index only shows 2 posts in a forum, when there are 3 -- two in child forums and one in a grandchild forum. 

I understand that changing this is a significant performance hit; regardless, I would like to evaluate the performance stresses for myself (since infinite subforum nesting is one of the draws of the software), so I just need to know what code to change.  I'm totally comfortable doing so, I just need to know what and where. :)

Arantor

Well the real stress depends on how many boards you have; it's relatively predictable because instead of natural subselect of boards, and associated joins to the topic, messages and members tables, you do a table scan.

So how many boards do you have total? And how many do you have that are affected by this?

Caltan

Twenty top-level forums, twenty-one child forums, and a dozen grandchild forums spread over the board (no more than three grandchildren per child; several have only one).  It's a directory system with strict lines of delineation for sorting purposes, and once there are a certain percentage of posts I'm not sure that counting grandchildren will be necessary; however, as it's just opening and activity breeds activity, it's important to show all the posts extant at first glance right now.

Arantor

That's 2 levels, not > 2 levels, which should work provided all boards have 'count posts' marked on them.

Caltan

Except that I do and it does not.  "Count posts" is checked for every forum, and "Count child's posts in parent's totals" is also checked globally.

The structure goes like so:  Forum --> Subforum (2 topics) --> Sub-Subforum (1 topic, 2 posts).
Forum, on the main index, shows 2 topics only, and the most recent post listed is from Subforum, not the more recent reply within Sub-Subforum.

Arantor



Arantor

Looks like you also need to modify:
WHERE {query_see_board}' . (empty($boardIndexOptions['countChildPosts']) ? (empty($boardIndexOptions['base_level']) ? '' : '
AND b.child_level >= {int:child_level}') : '
AND b.child_level BETWEEN ' . $boardIndexOptions['base_level'] . ' AND ' . ($boardIndexOptions['base_level'] + 1)),


to
WHERE {query_see_board}',


Mods: please move this to 2.0 support; it is not a bug in SMF.

Caltan

Awesome.  This doesn't affect the last post display, unfortunately, so I stuck with just changing ['base_level'] + 1 to  ['base_level'] + 2 to fix the global post count, which was all I really had to have.  Thanks!

sene1983

Quote from: Arantor on April 08, 2010, 10:00:43 AM
Looks like you also need to modify:
WHERE {query_see_board}' . (empty($boardIndexOptions['countChildPosts']) ? (empty($boardIndexOptions['base_level']) ? '' : '
AND b.child_level >= {int:child_level}') : '
AND b.child_level BETWEEN ' . $boardIndexOptions['base_level'] . ' AND ' . ($boardIndexOptions['base_level'] + 1)),


to
WHERE {query_see_board}',


Mods: please move this to 2.0 support; it is not a bug in SMF.

its really very good. exactly i was looking for this code. thank you very much Arantor.

but, at the right (unread posts), if last post is in sub of sub forum, notting shown. how can i change this?
for example:



as u see, no last post at my board.
could u help me?


devoetbalkantine

I have also tried this but like I figured out earlier this week I am not capable of making this work. I would like to know (Maybe Arantor knows) how to make topics in 3rd layer sections (grandchild boards) visible on the index page.

I want to test it on a test forum first, just to see how it works but I don't know which scipts to edit and where.

Arantor

Having actually now spent some time studying the code more deeply (since I want to remove the limitation myself), I understand know *why* it's limited. It's because the method of handling board access is very slow, and the child_level limit cuts down how slow that part of it is. The way to fixing it means reshaping how several key tables and core structures are implemented in SMF, which is non trivial.

RF-FH

Here is what I did to make it work. It's more a quick'n dirty hack than a modification, but it works fine and performance remains the same for me.
Tested with 2.0 RC5

I copied the full content of the file so you can see all the changes. To explain the changes:

I changed
AND b.child_level BETWEEN ' . $boardIndexOptions['base_level'] . ' AND ' . ($boardIndexOptions['base_level'] + 1)),

at line 76 to

AND b.child_level BETWEEN ' . $boardIndexOptions['base_level'] . ' AND ' . ($boardIndexOptions['base_level'] + 2)),

and I added


/** added by FH in order to also show last posts of grand children at board index **/
if($parent_map[$row_board['id_parent']][0]['last_post']['timestamp'] < forum_time(true, $row_board['poster_time'])) {
censorText($row_board['subject']);
$row_board['short_subject'] = shorten_subject($row_board['subject'], 24);
$this_last_post = array(
'id' => $row_board['id_msg'],
'time' => $row_board['poster_time'] > 0 ? timeformat($row_board['poster_time']) : $txt['not_applicable'],
'timestamp' => forum_time(true, $row_board['poster_time']),
'subject' => $row_board['short_subject'],
'member' => array(
'id' => $row_board['id_member'],
'username' => $row_board['poster_name'] != '' ? $row_board['poster_name'] : $txt['not_applicable'],
'name' => $row_board['real_name'],
'href' => $row_board['poster_name'] != '' && !empty($row_board['id_member']) ? $scripturl . '?action=profile;u=' . $row_board['id_member'] : '',
'link' => $row_board['poster_name'] != '' ? (!empty($row_board['id_member']) ? '<a href="' . $scripturl . '?action=profile;u=' . $row_board['id_member'] . '">' . $row_board['real_name'] . '</a>' : $row_board['real_name']) : $txt['not_applicable'],
),
'start' => 'msg' . $row_board['new_from'],
'topic' => $row_board['id_topic']
);

// Provide the href and link.
if ($row_board['subject'] != '')
{
$this_last_post['href'] = $scripturl . '?topic=' . $row_board['id_topic'] . '.msg' . ($user_info['is_guest'] ? $row_board['id_msg'] : $row_board['new_from']) . (empty($row_board['is_read']) ? ';boardseen' : '') . '#new';
$this_last_post['link'] = '<a href="' . $this_last_post['href'] . '" title="' . $row_board['subject'] . '">' . $row_board['short_subject'] . '</a>';
}
else
{
$this_last_post['href'] = '';
$this_last_post['link'] = $txt['not_applicable'];
}
$parent_map[$row_board['id_parent']][0]['last_post'] = $this_last_post;
}
/** end **/


After line 227


Here's the full file:
Sources/Subs-BoardIndex.php
<?php
/**********************************************************************************
* Subs-BoardIndex.php                                                             *
***********************************************************************************
* SMF: Simple Machines Forum                                                      *
* Open-Source Project Inspired by Zef Hemel ([email protected])                    *
* =============================================================================== *
* Software Version:           SMF 2.0 RC5                                         *
* Software by:                Simple Machines (http://www.simplemachines.org)     *
* Copyright 2006-2010 by:     Simple Machines LLC (http://www.simplemachines.org) *
*           2001-2006 by:     Lewis Media (http://www.lewismedia.com)             *
* Support, News, Updates at:  http://www.simplemachines.org                       *
***********************************************************************************
* This program is free software; you may redistribute it and/or modify it under   *
* the terms of the provided license as published by Simple Machines LLC.          *
*                                                                                 *
* This program is distributed in the hope that it is and will be useful, but      *
* WITHOUT ANY WARRANTIES; without even any implied warranty of MERCHANTABILITY    *
* or FITNESS FOR A PARTICULAR PURPOSE.                                            *
*                                                                                 *
* See the "license.txt" file for details of the Simple Machines license.          *
* The latest version can always be found at http://www.simplemachines.org.        *
**********************************************************************************/

if (!defined('SMF'))
die('Hacking attempt...');
/* This file currently only contains one function to collect the data needed to
show a list of boards for the board index and the message index.

array getBoardIndex(array boardIndexOptions)
- Fetches a list of boards and (optional) categories including
  statistical information, child boards and moderators.
- Used by both the board index (main data) and the message index (child
  boards).
- Depending on the include_categories setting returns an associative
  array with categories->boards->child_boards or an associative array
  with boards->child_boards.
*/

function getBoardIndex($boardIndexOptions)
{
global $smcFunc$scripturl$user_info$modSettings$txt;
global $settings$context;

// For performance, track the latest post while going through the boards.
if (!empty($boardIndexOptions['set_latest_post']))
$latest_post = array(
'timestamp' => 0,
'ref' => 0,
);

// Find all boards and categories, as well as related information.  This will be sorted by the natural order of boards and categories, which we control.
$result_boards $smcFunc['db_query']('boardindex_fetch_boards''
SELECT' 
. ($boardIndexOptions['include_categories'] ? '
c.id_cat, c.name AS cat_name,' 
'') . '
b.id_board, b.name AS board_name, b.description,
CASE WHEN b.redirect != {string:blank_string} THEN 1 ELSE 0 END AS is_redirect,
b.num_posts, b.num_topics, b.unapproved_posts, b.unapproved_topics, b.id_parent,
IFNULL(m.poster_time, 0) AS poster_time, IFNULL(mem.member_name, m.poster_name) AS poster_name,
m.subject, m.id_topic, IFNULL(mem.real_name, m.poster_name) AS real_name,
. ($user_info['is_guest'] ? ' 1 AS is_read, 0 AS new_from,' '
(IFNULL(lb.id_msg, 0) >= b.id_msg_updated) AS is_read, IFNULL(lb.id_msg, -1) + 1 AS new_from,' 
. ($boardIndexOptions['include_categories'] ? '
c.can_collapse, IFNULL(cc.id_member, 0) AS is_collapsed,' 
'')) . '
IFNULL(mem.id_member, 0) AS id_member, m.id_msg,
IFNULL(mods_mem.id_member, 0) AS id_moderator, mods_mem.real_name AS mod_real_name
FROM {db_prefix}boards AS b' 
. ($boardIndexOptions['include_categories'] ? '
LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat)' 
'') . '
LEFT JOIN {db_prefix}messages AS m ON (m.id_msg = b.id_last_msg)
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)' 
. ($user_info['is_guest'] ? '' '
LEFT JOIN {db_prefix}log_boards AS lb ON (lb.id_board = b.id_board AND lb.id_member = {int:current_member})' 
. ($boardIndexOptions['include_categories'] ? '
LEFT JOIN {db_prefix}collapsed_categories AS cc ON (cc.id_cat = c.id_cat AND cc.id_member = {int:current_member})' 
'')) . '
LEFT JOIN {db_prefix}moderators AS mods ON (mods.id_board = b.id_board)
LEFT JOIN {db_prefix}members AS mods_mem ON (mods_mem.id_member = mods.id_member)
WHERE {query_see_board}' 
. (empty($boardIndexOptions['countChildPosts']) ? (empty($boardIndexOptions['base_level']) ? '' '
AND b.child_level >= {int:child_level}'
) : '
AND b.child_level BETWEEN ' 
$boardIndexOptions['base_level'] . ' AND ' . ($boardIndexOptions['base_level'] + 2)),
array(
'current_member' => $user_info['id'],
'child_level' => $boardIndexOptions['base_level'],
'blank_string' => '',
)
);

// Start with an empty array.
if ($boardIndexOptions['include_categories'])
$categories = array();
else
$this_category = array();

// Run through the categories and boards (or only boards)....
while ($row_board $smcFunc['db_fetch_assoc']($result_boards))
{
if ($boardIndexOptions['include_categories'])
{

$ignoreThisBoard in_array($row_board['id_board'], $user_info['ignoreboards']);
$row_board['is_read'] = !empty($row_board['is_read']) || $ignoreThisBoard '1' '0';
// Haven't set this category yet.
if (empty($categories[$row_board['id_cat']]))
{
$categories[$row_board['id_cat']] = array(
'id' => $row_board['id_cat'],
'name' => $row_board['cat_name'],
'is_collapsed' => isset($row_board['can_collapse']) && $row_board['can_collapse'] == && $row_board['is_collapsed'] > 0,
'can_collapse' => isset($row_board['can_collapse']) && $row_board['can_collapse'] == 1,
'collapse_href' => isset($row_board['can_collapse']) ? $scripturl '?action=collapse;c=' $row_board['id_cat'] . ';sa=' . ($row_board['is_collapsed'] > 'expand;' 'collapse;') . $context['session_var'] . '=' $context['session_id'] . '#c' $row_board['id_cat'] : '',
'collapse_image' => isset($row_board['can_collapse']) ? '<img src="' $settings['images_url'] . '/' . ($row_board['is_collapsed'] > 'expand.gif" alt="+"' 'collapse.gif" alt="-"') . ' />' '',
'href' => $scripturl '#c' $row_board['id_cat'],
'boards' => array(),
'new' => false
);
$categories[$row_board['id_cat']]['link'] = '<a id="c' $row_board['id_cat'] . '" href="' . (isset($row_board['can_collapse']) ? $categories[$row_board['id_cat']]['collapse_href'] : $categories[$row_board['id_cat']]['href']) . '">' $row_board['cat_name'] . '</a>';
}

// If this board has new posts in it (and isn't the recycle bin!) then the category is new.
if (empty($modSettings['recycle_enable']) || $modSettings['recycle_board'] != $row_board['id_board'])
$categories[$row_board['id_cat']]['new'] |= empty($row_board['is_read']) && $row_board['poster_name'] != '';

// Avoid showing category unread link where it only has redirection boards.
$categories[$row_board['id_cat']]['show_unread'] = !empty($categories[$row_board['id_cat']]['show_unread']) ? : !$row_board['is_redirect'];

// Collapsed category - don't do any of this.
if ($categories[$row_board['id_cat']]['is_collapsed'])
continue;

// Let's save some typing.  Climbing the array might be slower, anyhow.
$this_category = &$categories[$row_board['id_cat']]['boards'];
}

// This is a parent board.
if ($row_board['id_parent'] == $boardIndexOptions['parent_id'])
{
// Is this a new board, or just another moderator?
if (!isset($this_category[$row_board['id_board']]))
{
// Not a child.
$isChild false;

$this_category[$row_board['id_board']] = array(
'new' => empty($row_board['is_read']),
'id' => $row_board['id_board'],
'name' => $row_board['board_name'],
'description' => $row_board['description'],
'moderators' => array(),
'link_moderators' => array(),
'children' => array(),
'link_children' => array(),
'children_new' => false,
'topics' => $row_board['num_topics'],
'posts' => $row_board['num_posts'],
'is_redirect' => $row_board['is_redirect'],
'unapproved_topics' => $row_board['unapproved_topics'],
'unapproved_posts' => $row_board['unapproved_posts'] - $row_board['unapproved_topics'],
'can_approve_posts' => !empty($user_info['mod_cache']['ap']) && ($user_info['mod_cache']['ap'] == array(0) || in_array($row_board['id_board'], $user_info['mod_cache']['ap'])),
'href' => $scripturl '?board=' $row_board['id_board'] . '.0',
'link' => '<a href="' $scripturl '?board=' $row_board['id_board'] . '.0">' $row_board['board_name'] . '</a>'
);
}
if (!empty($row_board['id_moderator']))
{
$this_category[$row_board['id_board']]['moderators'][$row_board['id_moderator']] = array(
'id' => $row_board['id_moderator'],
'name' => $row_board['mod_real_name'],
'href' => $scripturl '?action=profile;u=' $row_board['id_moderator'],
'link' => '<a href="' $scripturl '?action=profile;u=' $row_board['id_moderator'] . '" title="' $txt['board_moderator'] . '">' $row_board['mod_real_name'] . '</a>'
);
$this_category[$row_board['id_board']]['link_moderators'][] = '<a href="' $scripturl '?action=profile;u=' $row_board['id_moderator'] . '" title="' $txt['board_moderator'] . '">' $row_board['mod_real_name'] . '</a>';
}
}
// Found a child board.... make sure we've found its parent and the child hasn't been set already.
elseif (isset($this_category[$row_board['id_parent']]['children']) && !isset($this_category[$row_board['id_parent']]['children'][$row_board['id_board']]))
{
// A valid child!
$isChild true;

$this_category[$row_board['id_parent']]['children'][$row_board['id_board']] = array(
'id' => $row_board['id_board'],
'name' => $row_board['board_name'],
'description' => $row_board['description'],
'new' => empty($row_board['is_read']) && $row_board['poster_name'] != '',
'topics' => $row_board['num_topics'],
'posts' => $row_board['num_posts'],
'is_redirect' => $row_board['is_redirect'],
'unapproved_topics' => $row_board['unapproved_topics'],
'unapproved_posts' => $row_board['unapproved_posts'] - $row_board['unapproved_topics'],
'can_approve_posts' => !empty($user_info['mod_cache']['ap']) && ($user_info['mod_cache']['ap'] == array(0) || in_array($row_board['id_board'], $user_info['mod_cache']['ap'])),
'href' => $scripturl '?board=' $row_board['id_board'] . '.0',
'link' => '<a href="' $scripturl '?board=' $row_board['id_board'] . '.0">' $row_board['board_name'] . '</a>'
);

// Counting child board posts is... slow :/.
if (!empty($boardIndexOptions['countChildPosts']) && !$row_board['is_redirect'])
{
$this_category[$row_board['id_parent']]['posts'] += $row_board['num_posts'];
$this_category[$row_board['id_parent']]['topics'] += $row_board['num_topics'];
}

// Does this board contain new boards?
$this_category[$row_board['id_parent']]['children_new'] |= empty($row_board['is_read']);

// This is easier to use in many cases for the theme....
$this_category[$row_board['id_parent']]['link_children'][] = &$this_category[$row_board['id_parent']]['children'][$row_board['id_board']]['link'];
}
// Child of a child... just add it on...
elseif (!empty($boardIndexOptions['countChildPosts']))
{
if (!isset($parent_map))
$parent_map = array();

if (!isset($parent_map[$row_board['id_parent']]))
foreach ($this_category as $id => $board)
{
if (!isset($board['children'][$row_board['id_parent']]))
continue;

$parent_map[$row_board['id_parent']] = array(&$this_category[$id], &$this_category[$id]['children'][$row_board['id_parent']]);
$parent_map[$row_board['id_board']] = array(&$this_category[$id], &$this_category[$id]['children'][$row_board['id_parent']]);

break;
}

if (isset($parent_map[$row_board['id_parent']]) && !$row_board['is_redirect'])
{
$parent_map[$row_board['id_parent']][0]['posts'] += $row_board['num_posts'];
$parent_map[$row_board['id_parent']][0]['topics'] += $row_board['num_topics'];
$parent_map[$row_board['id_parent']][1]['posts'] += $row_board['num_posts'];
$parent_map[$row_board['id_parent']][1]['topics'] += $row_board['num_topics'];

/** added by FH in order to also show last posts of grand children at board index **/
if($parent_map[$row_board['id_parent']][0]['last_post']['timestamp'] < forum_time(true$row_board['poster_time'])) {
censorText($row_board['subject']);
$row_board['short_subject'] = shorten_subject($row_board['subject'], 24);
$this_last_post = array(
'id' => $row_board['id_msg'],
'time' => $row_board['poster_time'] > timeformat($row_board['poster_time']) : $txt['not_applicable'],
'timestamp' => forum_time(true$row_board['poster_time']),
'subject' => $row_board['short_subject'],
'member' => array(
'id' => $row_board['id_member'],
'username' => $row_board['poster_name'] != '' $row_board['poster_name'] : $txt['not_applicable'],
'name' => $row_board['real_name'],
'href' => $row_board['poster_name'] != '' && !empty($row_board['id_member']) ? $scripturl '?action=profile;u=' $row_board['id_member'] : '',
'link' => $row_board['poster_name'] != '' ? (!empty($row_board['id_member']) ? '<a href="' $scripturl '?action=profile;u=' $row_board['id_member'] . '">' $row_board['real_name'] . '</a>' $row_board['real_name']) : $txt['not_applicable'],
),
'start' => 'msg' $row_board['new_from'],
'topic' => $row_board['id_topic']
);

// Provide the href and link.
if ($row_board['subject'] != '')
{
$this_last_post['href'] = $scripturl '?topic=' $row_board['id_topic'] . '.msg' . ($user_info['is_guest'] ? $row_board['id_msg'] : $row_board['new_from']) . (empty($row_board['is_read']) ? ';boardseen' '') . '#new';
$this_last_post['link'] = '<a href="' $this_last_post['href'] . '" title="' $row_board['subject'] . '">' $row_board['short_subject'] . '</a>';
}
else
{
$this_last_post['href'] = '';
$this_last_post['link'] = $txt['not_applicable'];
}
$parent_map[$row_board['id_parent']][0]['last_post'] = $this_last_post;
}
/** end **/

continue;
}

continue;
}
// Found a child of a child - skip.
else
continue;

// Prepare the subject, and make sure it's not too long.
censorText($row_board['subject']);
$row_board['short_subject'] = shorten_subject($row_board['subject'], 24);
$this_last_post = array(
'id' => $row_board['id_msg'],
'time' => $row_board['poster_time'] > timeformat($row_board['poster_time']) : $txt['not_applicable'],
'timestamp' => forum_time(true$row_board['poster_time']),
'subject' => $row_board['short_subject'],
'member' => array(
'id' => $row_board['id_member'],
'username' => $row_board['poster_name'] != '' $row_board['poster_name'] : $txt['not_applicable'],
'name' => $row_board['real_name'],
'href' => $row_board['poster_name'] != '' && !empty($row_board['id_member']) ? $scripturl '?action=profile;u=' $row_board['id_member'] : '',
'link' => $row_board['poster_name'] != '' ? (!empty($row_board['id_member']) ? '<a href="' $scripturl '?action=profile;u=' $row_board['id_member'] . '">' $row_board['real_name'] . '</a>' $row_board['real_name']) : $txt['not_applicable'],
),
'start' => 'msg' $row_board['new_from'],
'topic' => $row_board['id_topic']
);

// Provide the href and link.
if ($row_board['subject'] != '')
{
$this_last_post['href'] = $scripturl '?topic=' $row_board['id_topic'] . '.msg' . ($user_info['is_guest'] ? $row_board['id_msg'] : $row_board['new_from']) . (empty($row_board['is_read']) ? ';boardseen' '') . '#new';
$this_last_post['link'] = '<a href="' $this_last_post['href'] . '" title="' $row_board['subject'] . '">' $row_board['short_subject'] . '</a>';
}
else
{
$this_last_post['href'] = '';
$this_last_post['link'] = $txt['not_applicable'];
}

// Set the last post in the parent board.
if ($row_board['id_parent'] == $boardIndexOptions['parent_id'] || ($isChild && !empty($row_board['poster_time']) && $this_category[$row_board['id_parent']]['last_post']['timestamp'] < forum_time(true$row_board['poster_time']))) {
$this_category[$isChild $row_board['id_parent'] : $row_board['id_board']]['last_post'] = $this_last_post;
}
// Just in the child...?
if ($isChild)
{
$this_category[$row_board['id_parent']]['children'][$row_board['id_board']]['last_post'] = $this_last_post;

// If there are no posts in this board, it really can't be new...
$this_category[$row_board['id_parent']]['children'][$row_board['id_board']]['new'] &= $row_board['poster_name'] != '';
}
// No last post for this board?  It's not new then, is it..?
elseif (!$isGrandChild && $row_board['poster_name'] == '')
$this_category[$row_board['id_board']]['new'] = false;

// Determine a global most recent topic.
if (!empty($boardIndexOptions['set_latest_post']) && !empty($row_board['poster_time']) && $row_board['poster_time'] > $latest_post['timestamp'] && !$ignoreThisBoard)
$latest_post = array(
'timestamp' => $row_board['poster_time'],
'ref' => &$this_category[$isChild $row_board['id_parent'] : $row_board['id_board']]['last_post'],
);
}
$smcFunc['db_free_result']($result_boards);

// By now we should know the most recent post...if we wanna know it that is.
if (!empty($boardIndexOptions['set_latest_post']) && !empty($latest_post['ref']))
$context['latest_post'] = $latest_post['ref'];

return $boardIndexOptions['include_categories'] ? $categories $this_category;
}

?>

Arantor

So, how many boards do you have, exactly?

Oh, and if you made it work, why is there still a continue on the case of child of a child being detected?

RF-FH

Quote from: Arantor on April 01, 2011, 04:28:13 AM
So, how many boards do you have, exactly?

Not much, but since retrieving the boards is in O(n) and the posts of the subboards are counted anyway I highly doubt that performance is influenced very much.

Quote from: Arantor on April 01, 2011, 04:28:13 AM
Oh, and if you made it work, why is there still a continue on the case of child of a child being detected?

That's a remnant of a prior implementation of SMF I guess. It's completely useless, you can delete it or leave it there. The if-elseif cascades cover all possibilities.
EDIT: I'm not sure about that, but for me it made no difference if I deleted the last 2 lines of the if-elseif cascade
Edit²: typos -.-

Arantor

QuoteNot much, but since retrieving the boards is in O(n)

Are you sure about that? Evaluating board access when not using the limit in the SQL should push it above O(n) time given that it's based on a FIND_IN_SET against a string.

Quoteand the posts of the subboards is counted

Not normally, no, because the query has a limiter in it specifically to cut the number of boards pulled, which I see you've extended but only by one level, rather than to arbitrary depth.

RF-FH

Quote from: Arantor on April 01, 2011, 04:35:57 AM
QuoteNot much, but since retrieving the boards is in O(n)

Are you sure about that? Evaluating board access when not using the limit in the SQL should push it above O(n) time given that it's based on a FIND_IN_SET against a string.

Yes, that's true, but if you don't have much subsub-boards you don't change O(n) to something like O(n log(n)) which would be the next greater cap.
I agree that my hack might cause serious performance issues on large boards with many subboards and many users, but on our small forum with 5 grandchild-boards (now I counted them ^^) there's absolutely no measurable difference in performance.

Quote from: Arantor on April 01, 2011, 04:35:57 AM
Quoteand the posts of the subboards is counted

Not normally, no, because the query has a limiter in it specifically to cut the number of boards pulled, which I see you've extended but only by one level, rather than to arbitrary depth.

Yes, if you also want to count posts from grand-grand childs you'd have to raise the level again. And then it definitely will get much slower.

Also, if I'd have known that SMF doesn't support counting posts in grandchild boards (I absolutely understand the performance argument) I would've chosen another design for the forum - but now it's too late and that's why I implemented the hack.

Arantor

Yeah, for a few boards it's not a significant handicap in performance terms, but the board access is really only part of the problem. A non trivial part of it is the fact it also gathers the board moderators in the same query, which may be a LEFT JOIN resulting in null columns or potentially many rows being added to the query.

That particular little gem is bred out of the mentality that one large query is 'better' than two or three smaller ones, which is often untrue.

RF-FH

Quote from: Arantor on April 01, 2011, 05:00:08 AM
Yeah, for a few boards it's not a significant handicap in performance terms, but the board access is really only part of the problem. A non trivial part of it is the fact it also gathers the board moderators in the same query, which may be a LEFT JOIN resulting in null columns or potentially many rows being added to the query.

Yes, that's would be a big problem on very large boards, but if anyone wants to try out my hack he could just change the limit from "+1" to "+6" and check if performance got worse in the first place.

Quote from: Arantor on April 01, 2011, 05:00:08 AM
That particular little gem is bred out of the mentality that one large query is 'better' than two or three smaller ones, which is often untrue.

I agree, but if you'd have to fire a query for every single board in order to get the children of the board and then map the children into the array structure SMF uses I think you'd also lose a lot of time (and the code wouldn't be as neat as it's now).

Arantor

QuoteI agree, but if you'd have to fire a query for every single board in order to get the children of the board and then map the children into the array structure SMF uses I think you'd also lose a lot of time (and the code wouldn't be as neat as it's now)

Or collate all the board ids into an array and query the board moderators table on its own using WHERE bm.id_board IN (list of boards) which should be faster.

Mind you, I'd personally start by rewriting how board access works anyway to not have the FIND_IN_SET and instead to use a properly indexed table to achieve it...

Illori

it is not possible to do due to the issues that have been stated already in this thread. it will never be a default feature of smf, and it will never be an approved mod.

Arantor

Eh? Of course it's possible. The above proves it's possible.

Default feature of SMF? Possibly if the code is rewritten to deal with this limitation.

Never be an approved mod? Why not? There's no technical reason why it shouldn't be approved if someone wants to submit it.

Illori

well from what i gathered from what you have said, it would put more stress on a server and therefore would not be possible. if that is the case then adding it to the mod site would not be a good idea.

Arantor

It would put more stress on the server if the other things weren't fixed alongside it. Which means a more serious overhaul of SMF, which is possible to do in a mod, but I don't see it happened. Unlikely != impossible ;)

If you rewrite the way the board access is done (which I did in a mod 18 months ago anyway, to prove it could be done amongst other things), rewrite how board moderators are loaded and reduce the gargantuan array shifting that goes on (which is possible), there's no reason why it should be any slower, and likely would even be faster.

RF-FH

Quote from: Illori on April 01, 2011, 06:04:58 AM
it is not possible to do due to the issues that have been stated already in this thread. it will never be a default feature of smf, and it will never be an approved mod.

My hack was not meant to be a proper mod, nor was it even meant to be useful at all. I just wanted to share my work because I think that there are many people who miss that feature. Of course everyone who uses not approved mods is using them on his own risk - especially if the author states that it's more of a hack than a modification.

And as Arantor already said: If you'd change the way the boards are fetched from the database you could also negate the performance issues this feature would cause. I'm not deep enough into SMF coding, so everything I can contribute to this topic at the moment is my little hack.

Advertisement: