Авторизуйтесь или зарегистрируйтесь, чтобы создать новую тему

Программизм. Серия 3

AgentRX
201
[Удален] 23.11.2010 17:29 | #
trophim:

Большое спасибо, завтра буду пробовать И, соответственно, писать благодарности... или гневные отзывы :-). 

P.S. Кстати, почему вы не используете CSmartInterface везде, где это необходимо? Или это зависит от стиля конкретного разработчика? 

1. CSmartInterface вставляет вызовы деструктора на каждом return. Нет смысла использовать его, если он нужен для пары строк кода.

2. Не все интерфейсы имеют методы Release()

TeamWox SaaS Agent: как бесплатно и быстро строить SaaS фермы

Вышла в свет новая версия TeamWox SaaS Agent, которая теперь позволяет бесплатно строить SaaS фермы с сотнями копий систем групповой работы TeamWox как провайдерам, так и независимым поставщикам.

trophim
70
trophim 23.11.2010 23:43 | #
AgentRX:

1. CSmartInterface вставляет вызовы деструктора на каждом return. Нет смысла использовать его, если он нужен для пары строк кода.

2. Не все интерфейсы имеют методы Release()


Ну, я спрашивал именно про те случаи, где он нужен. А что, вызов деструктора - это ультра-тяжелая операция? Да он в релизе вообще заинлайнится (как и все методы класса CSmartInterface). По сути эффект будет таков: в коде у вас не будет лишней строки с явным вызовом Release (а CSmartInterface не позволит вам забыть о ее вызове), а на сгенерированный код это вообще никак не повлияет (в плане быстродействия). Вызов release вручную - это похоже на преждевременную оптимизацию... В конце концов, профайлер покажет кто тормозит больше всех и я не думаю что CSmart с его смехотворными издержками будет на первых позициях.

Впрочем, так и до 'священных войн' недалеко =) По этому вопросу можем не продолжать.

Мне б вот еще про индексацию и поиск вопрос осветить. Расскажите, а?

AgentRX
201
[Удален] 24.11.2010 14:22 | #

3. Что необходимо делать для поддержки поиска (при помощи встроенного поиска)? Я так понимаю что для того, чтобы работал поиск по тексту, то везде где модуль использует текст, его необходимо 'скормить' внутреннему индексатору.

Для этого вам необходимо реализовать интерфейс "ISearchClient" и отдавать объект при запросе модуля GetInterface. Рассмотрим на примере реализации в модуле Board, входящего в состав SDK:

Класс CBoardSearch:

//+------------------------------------------------------------------+
//| Класс для реиндексации поиска                                    |
//+------------------------------------------------------------------+
class CBoardSearch : public ISearchClient
  {
...
   TWRESULT          Reindex(ISearchManager *search_mngr);
   TWRESULT          FillResult(const Context *context, ISearchResult *result);
...

Метод Reindex(ISearchManager *search_mngr);

Вызывается поисковиком для реиндексации всех элементов. Это происходит, например, когда нажимают ссылку "Реиндексация" и запускают ее процесс:

 

 

Интерфейс ISearchManager служит для сбора данных об объектах. Сами же объекты заполняются с помощью интерфейса ISearchIndexer. Чтобы получить объект ISearchIndexer необходимо у него вызвать метод GetSearchIndexer.

Далее в цикле нужно заполнить данные об объекте и занести объект в ISearchManager с помощью метода Insert: 

TWRESULT CBoardManager::SearchReindex(ISearchManager *search_manager)
  {
   CSmartInterface<ISearchIndexer> indexer;
...
   if(RES_FAILED(res=search_manager->GetSearchIndexer(&indexer)) || indexer==NULL)
      ReturnErrorExt(res,NULL,"failed get search indexer");
...
   while(m_work && sql->QueryFetch())
     {
      indexer->Clear();
      //---
      indexer->AddText(SEARCH_PLAIN_TEXT,record.subject,2.0f);
...
     //--- добавим автора
      indexer->AddPermission(record.author_id);
      indexer->AddAuthor(record.author_id, 1.0f);
      //--- добавим всех у кого есть права - т.е. тех кто может читать категорию
      lock=m_cache_sync;
...
      //--- найдем категорию и добавим пользователей как разрешенных для просмотра информации
      for(int i=0,size=(int)m_categories.Size();i<size;i++)
         if(m_categories[i].id==record.category_id)
           {
            for(int j=0;j<m_categories[i].perms_count;j++)
              {
               if(permission_count<_countof(permissions))
                  permissions[permission_count++]=m_categories[i].perms[j].user_id;
               //---
               indexer->AddPermission(m_categories[i].perms[j].user_id);
              }
            break;
           }
...  
      //--- добавляем проиндексированные данные
      indexer->SetDateTime(record.date_create);
      search_manager->Insert(TWX_BOARD,SEARCH_GENERIC,record.id,0,indexer);

Метод FillResult(const Context *context, ISearchResult *result);

Служит для подготовки вывода результата поиска. То есть когда пользователь нашел данные в вашем модуле и они должны быть показаны. Контекст, передаваемый в метод, содержит пользователя.

Интерфейс ISearchResult содержит методы для установки тех или иных свойств результата:

 

TWRESULT CBoardManager::SearchFillResult(const Context *context,ISearchResult *result)
  {
...
   const SearchResult *data=result->GetResult();
   if(data==NULL || data->module_id!=TWX_BOARD) ReturnErrorExt(RES_E_INVALID_ARGS,context,"failed parameters for search result");
...
//---
   if(data->record2==0)
     {
      message_id=data->record1;
     }
   else
      if(data->record1==BOARD_COMMENT_SEARCH_ID && data->record2>0)
        {
         m_comments_manager->SearchFillResult(context,result,data->record2,comment_url,_countof(url),&message_id);
        }
...
//--- найдем сообщение
   if(BoardRecord* record=m_cache.FindFirst(PMessages(message_id)))
     {
...
      result->SetTitle(record->subject);
      //---
      if(comment_url[0]!=0)
         StringCchPrintf(url,_countof(url),L"/board/%I64d?%s",message_id,comment_url);
      else
         StringCchPrintf(url,_countof(url),L"/board/%I64d",message_id);
      //--- если это не комментарий добавим в содержимое 
      if(data->record2==0)
        {
         //---
         if(record->description_id>0)
           {
            //--- добавим описание
            if(RES_SUCCEEDED(m_files_manager->FileInfoGet(NULL,record->description_id,&file_info)) && file_info.size>0 && (file_info.size%2)==0)
              {
               wchar_t description_stat[512]={0};
               //---
               if(file_info.size>sizeof(description_stat))
                 {
                  UINT64   len        =file_info.size;
                  wchar_t *description=new wchar_t[size_t(len/sizeof(wchar_t))];
                  //---
                  if(description==NULL) ReturnErrorExt(RES_E_OUT_OF_MEMORY,context,"failed not enough memory for description content");
                  //---
                  if(RES_SUCCEEDED(m_files_manager->FileRead(NULL,record->description_id,description,&len,0)))
                     result->AddText(SEARCH_PLAIN_TEXT,description,int(len/sizeof(wchar_t)));
                  //---
                  delete []description;
                 }
               else
                 {
                  UINT64 len=file_info.size;
                  if(RES_SUCCEEDED(m_files_manager->FileRead(NULL,record->description_id,&description_stat,&len,0)))
                     result->AddText(SEARCH_PLAIN_TEXT,description_stat,int(len/sizeof(wchar_t)));
                 }
              }
           }
         //---
         if(record->content_id>0)
            m_comments_manager->SearchFillResult(context,result,record->content_id,NULL,0,NULL);
        }
      //---
      result->SetUrl(url);
      //--- в цикле получим все элементы
      for(int i=0,size=(int)m_categories.Size();i<size;i++)
         if(m_categories[i].id==record->category_id)
           {
            StringCchPrintf(signature,_countof(signature),L"<a href=\"/board/category/%I64d\">%s</a>",record->category_id,m_categories[i].name);
            //---
            result->SetSignature(signature);
           }

Если у вас изменились какие-либо данные и необходимо переиндексировать их (не весь модуль), то для этого используется интерфейс ISearchManager. Его реализацию можно получить через метод GetInterface сервера. А дальше все также как и было описано выше в функции Reindex.

 

Для более подробной информации смотрите модуль Board, входящий в состав SDK. 

К списку тем  | 12

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий