| 16 |
|
|
| 17 |
#include "section_list.h" |
#include "section_list.h" |
| 18 |
#include "log.h" |
#include "log.h" |
|
#include "io.h" |
|
| 19 |
#include "trie_dict.h" |
#include "trie_dict.h" |
| 20 |
#include <stdio.h> |
#include <stdio.h> |
| 21 |
#include <string.h> |
#include <string.h> |
| 26 |
#include <sys/shm.h> |
#include <sys/shm.h> |
| 27 |
#include <sys/ipc.h> |
#include <sys/ipc.h> |
| 28 |
|
|
| 29 |
#define ARTICLE_BLOCK_PER_SHM 50 // sizeof(ARTICLE_BLOCK) * ARTICLE_BLOCK_PER_SHM is the size of each shm segment to allocate |
// ARTICLE_BLOCK_PER_SHM * ARTICLE_BLOCK_SHM_COUNT_LIMIT should be |
| 30 |
#define ARTICLE_BLOCK_SHM_COUNT_LIMIT 256 |
// no less than BBS_article_block_limit_per_section * BBS_max_section, |
| 31 |
|
// in order to allocate enough memory for blocks |
| 32 |
|
#define ARTICLE_BLOCK_PER_SHM 400 // sizeof(ARTICLE_BLOCK) * ARTICLE_BLOCK_PER_SHM is the size of each shm segment to allocate |
| 33 |
|
#define ARTICLE_BLOCK_SHM_COUNT_LIMIT 256 // limited by length (8-bit) of proj_id in ftok(path, proj_id) |
| 34 |
|
|
| 35 |
struct article_block_shm_t |
struct article_block_shm_t |
| 36 |
{ |
{ |
| 251 |
p_section->article_count = 0; |
p_section->article_count = 0; |
| 252 |
p_section->delete_count = 0; |
p_section->delete_count = 0; |
| 253 |
|
|
| 254 |
|
p_section->p_article_head = NULL; |
| 255 |
|
p_section->p_article_tail = NULL; |
| 256 |
|
|
| 257 |
if (trie_dict_set(p_trie_dict_section_data, sname, index) != 1) |
if (trie_dict_set(p_trie_dict_section_data, sname, index) != 1) |
| 258 |
{ |
{ |
| 259 |
log_error("trie_dict_set(section_data, %s, %d) error\n", sname, index); |
log_error("trie_dict_set(section_data, %s, %d) error\n", sname, index); |
| 293 |
p_section->article_count = 0; |
p_section->article_count = 0; |
| 294 |
p_section->delete_count = 0; |
p_section->delete_count = 0; |
| 295 |
|
|
| 296 |
|
p_section->p_article_head = NULL; |
| 297 |
|
p_section->p_article_tail = NULL; |
| 298 |
|
|
| 299 |
return 0; |
return 0; |
| 300 |
} |
} |
| 301 |
|
|
| 302 |
SECTION_DATA *section_data_find_by_name(const char *sname) |
SECTION_DATA *section_data_find_section_by_name(const char *sname) |
| 303 |
{ |
{ |
| 304 |
int64_t index; |
int64_t index; |
| 305 |
|
|
| 318 |
return (p_section_data_pool + index); |
return (p_section_data_pool + index); |
| 319 |
} |
} |
| 320 |
|
|
| 321 |
int section_data_append_article(SECTION_DATA *p_section, const ARTICLE *p_article) |
int section_data_append_article(SECTION_DATA *p_section, const ARTICLE *p_article_src) |
| 322 |
{ |
{ |
| 323 |
ARTICLE_BLOCK *p_block; |
ARTICLE_BLOCK *p_block; |
| 324 |
int32_t last_aid = 0; |
int32_t last_aid = 0; |
| 325 |
|
ARTICLE *p_article; |
| 326 |
ARTICLE *p_topic_head; |
ARTICLE *p_topic_head; |
| 327 |
ARTICLE *p_topic_tail; |
ARTICLE *p_topic_tail; |
| 328 |
|
|
| 329 |
if (p_section == NULL || p_article == NULL) |
if (p_section == NULL || p_article_src == NULL) |
| 330 |
{ |
{ |
| 331 |
log_error("section_data_append_article() NULL pointer error\n"); |
log_error("section_data_append_article() NULL pointer error\n"); |
| 332 |
return -1; |
return -1; |
| 363 |
else |
else |
| 364 |
{ |
{ |
| 365 |
p_section->p_tail_block->p_next_block = p_block; |
p_section->p_tail_block->p_next_block = p_block; |
| 366 |
last_aid = p_section->p_tail_block->articles[BBS_article_limit_per_block - 1].aid; |
last_aid = p_section->p_article_tail->aid; |
| 367 |
} |
} |
| 368 |
p_section->p_tail_block = p_block; |
p_section->p_tail_block = p_block; |
| 369 |
p_section->p_block[p_section->block_count] = p_block; |
p_section->p_block[p_section->block_count] = p_block; |
| 372 |
else |
else |
| 373 |
{ |
{ |
| 374 |
p_block = p_section->p_tail_block; |
p_block = p_section->p_tail_block; |
| 375 |
last_aid = p_block->articles[p_block->article_count - 1].aid; |
last_aid = p_section->p_article_tail->aid; |
| 376 |
} |
} |
| 377 |
|
|
| 378 |
// AID of articles should be strictly ascending |
// AID of articles should be strictly ascending |
| 379 |
if (p_article->aid <= last_aid) |
if (p_article_src->aid <= last_aid) |
| 380 |
{ |
{ |
| 381 |
log_error("section_data_append_article(aid=%d) error: last_aid=%d\n", p_article->aid, last_aid); |
log_error("section_data_append_article(aid=%d) error: last_aid=%d\n", p_article_src->aid, last_aid); |
| 382 |
return -3; |
return -3; |
| 383 |
} |
} |
| 384 |
|
|
| 385 |
if (p_block->article_count == 0) |
if (p_block->article_count == 0) |
| 386 |
{ |
{ |
| 387 |
p_section->block_head_aid[p_section->block_count - 1] = p_article->aid; |
p_section->block_head_aid[p_section->block_count - 1] = p_article_src->aid; |
| 388 |
} |
} |
| 389 |
|
|
| 390 |
if (p_article->tid != 0) |
if (p_article_src->tid != 0) |
| 391 |
{ |
{ |
| 392 |
p_topic_head = section_data_search_article(p_section, p_article->tid); |
p_topic_head = section_data_find_article_by_aid(p_section, p_article_src->tid); |
| 393 |
if (p_topic_head == NULL) |
if (p_topic_head == NULL) |
| 394 |
{ |
{ |
| 395 |
log_error("search head of topic (aid=%d) error\n", p_article->tid); |
log_error("search head of topic (aid=%d) error\n", p_article_src->tid); |
| 396 |
return -4; |
return -4; |
| 397 |
} |
} |
| 398 |
|
|
| 399 |
p_topic_tail = section_data_search_article(p_section, p_topic_head->prior_aid); |
p_topic_tail = p_topic_head->p_topic_prior; |
| 400 |
if (p_topic_tail == NULL) |
if (p_topic_tail == NULL) |
| 401 |
{ |
{ |
| 402 |
log_error("search tail of topic (aid=%d) error\n", p_topic_head->prior_aid); |
log_error("tail of topic (aid=%d) is NULL\n", p_article_src->tid); |
| 403 |
return -4; |
return -4; |
| 404 |
} |
} |
| 405 |
} |
} |
| 409 |
p_topic_tail = p_topic_head; |
p_topic_tail = p_topic_head; |
| 410 |
} |
} |
| 411 |
|
|
| 412 |
|
p_article = &(p_block->articles[p_block->article_count]); |
| 413 |
|
|
| 414 |
// Copy article data |
// Copy article data |
| 415 |
p_block->articles[p_block->article_count] = *p_article; |
*p_article = *p_article_src; |
| 416 |
|
|
| 417 |
// Link appended article as tail node of topic bi-directional list; |
// Link appended article as tail node of article bi-directional list |
| 418 |
p_block->articles[p_block->article_count].prior_aid = p_topic_tail->aid; |
if (p_section->p_article_head == NULL) |
| 419 |
p_block->articles[p_block->article_count].next_aid = p_topic_head->aid; |
{ |
| 420 |
p_topic_head->prior_aid = p_article->aid; |
p_section->p_article_head = p_article; |
| 421 |
p_topic_tail->next_aid = p_article->aid; |
p_section->p_article_tail = p_article; |
| 422 |
|
} |
| 423 |
|
p_article->p_prior = p_section->p_article_tail; |
| 424 |
|
p_article->p_next = p_section->p_article_head; |
| 425 |
|
p_section->p_article_head->p_prior = p_article; |
| 426 |
|
p_section->p_article_tail->p_next = p_article; |
| 427 |
|
p_section->p_article_tail = p_article; |
| 428 |
|
|
| 429 |
|
// Link appended article as tail node of topic bi-directional list |
| 430 |
|
p_article->p_topic_prior = p_topic_tail; |
| 431 |
|
p_article->p_topic_next = p_topic_head; |
| 432 |
|
p_topic_head->p_topic_prior = p_article; |
| 433 |
|
p_topic_tail->p_topic_next = p_article; |
| 434 |
|
|
| 435 |
p_block->article_count++; |
p_block->article_count++; |
| 436 |
p_section->article_count++; |
p_section->article_count++; |
| 438 |
return 0; |
return 0; |
| 439 |
} |
} |
| 440 |
|
|
| 441 |
ARTICLE *section_data_search_article(SECTION_DATA *p_section, int32_t aid) |
ARTICLE *section_data_find_article_by_aid(SECTION_DATA *p_section, int32_t aid) |
| 442 |
{ |
{ |
| 443 |
ARTICLE *p_article; |
ARTICLE *p_article; |
| 444 |
ARTICLE_BLOCK *p_block; |
ARTICLE_BLOCK *p_block; |
| 448 |
|
|
| 449 |
if (p_section == NULL) |
if (p_section == NULL) |
| 450 |
{ |
{ |
| 451 |
log_error("section_data_append_article() NULL pointer error\n"); |
log_error("section_data_find_article_by_aid() NULL pointer error\n"); |
| 452 |
return NULL; |
return NULL; |
| 453 |
} |
} |
| 454 |
|
|
| 507 |
return p_article; |
return p_article; |
| 508 |
} |
} |
| 509 |
|
|
| 510 |
|
ARTICLE *section_data_find_article_by_index(SECTION_DATA *p_section, int index) |
| 511 |
|
{ |
| 512 |
|
ARTICLE *p_article; |
| 513 |
|
ARTICLE_BLOCK *p_block; |
| 514 |
|
|
| 515 |
|
if (p_section == NULL) |
| 516 |
|
{ |
| 517 |
|
log_error("section_data_find_article_by_index() NULL pointer error\n"); |
| 518 |
|
return NULL; |
| 519 |
|
} |
| 520 |
|
|
| 521 |
|
if (index < 0 || index >= p_section->article_count) |
| 522 |
|
{ |
| 523 |
|
log_error("section_data_find_article_by_index(%d) is out of boundary [0, %d)\n", index, p_section->article_count); |
| 524 |
|
return NULL; |
| 525 |
|
} |
| 526 |
|
|
| 527 |
|
p_block = p_section->p_block[index / BBS_article_limit_per_block]; |
| 528 |
|
p_article = &(p_block->articles[index % BBS_article_limit_per_block]); |
| 529 |
|
|
| 530 |
|
return p_article; |
| 531 |
|
} |
| 532 |
|
|
| 533 |
int section_data_mark_del_article(SECTION_DATA *p_section, int32_t aid) |
int section_data_mark_del_article(SECTION_DATA *p_section, int32_t aid) |
| 534 |
{ |
{ |
| 535 |
ARTICLE *p_article; |
ARTICLE *p_article; |
| 536 |
|
|
| 537 |
p_article = section_data_search_article(p_section, aid); |
if (p_section == NULL) |
| 538 |
|
{ |
| 539 |
|
log_error("section_data_mark_del_article() NULL pointer error\n"); |
| 540 |
|
return -2; |
| 541 |
|
} |
| 542 |
|
|
| 543 |
|
p_article = section_data_find_article_by_aid(p_section, aid); |
| 544 |
if (p_article == NULL) |
if (p_article == NULL) |
| 545 |
{ |
{ |
| 546 |
return -1; // Not found |
return -1; // Not found |