searchengine/cpix/tsrc/cpixunittest/src/asynctests.cpp
changeset 0 671dee74050a
child 3 ae3f1779f6da
equal deleted inserted replaced
-1:000000000000 0:671dee74050a
       
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 #include <wchar.h>
       
    19 #include <stddef.h>
       
    20 #include <unistd.h>
       
    21 
       
    22 #include <pthread.h>
       
    23 
       
    24 #include <algorithm>
       
    25 #include <iostream>
       
    26 #include <string>
       
    27 
       
    28 #include "cpixtools.h"
       
    29 
       
    30 #include "itk.h"
       
    31 
       
    32 #include "cpix_async.h"
       
    33 
       
    34 #include "config.h"
       
    35 #include "suggestion.h"
       
    36 #include "testutils.h"
       
    37 #include "testcorpus.h"
       
    38 #include "setupsentry.h"
       
    39 
       
    40 
       
    41 // TODO PROPER, EXAMPLARY error clearing (cpix_ClearError())
       
    42 
       
    43 
       
    44 bool AddField(cpix_Document * doc,
       
    45               const wchar_t * name,
       
    46               const wchar_t * value,
       
    47               int             flags)
       
    48 {
       
    49     bool
       
    50         rv = false;
       
    51 
       
    52     cpix_Field
       
    53         field;
       
    54 
       
    55     cpix_Field_initialize(&field,
       
    56                           name,
       
    57                           value,
       
    58                           flags);
       
    59 
       
    60     if (cpix_Succeeded(&field))
       
    61         {
       
    62             cpix_Document_add(doc,
       
    63                               &field);
       
    64 
       
    65             if (cpix_Succeeded(doc))
       
    66                 {
       
    67                     rv = true;
       
    68                 }
       
    69             else
       
    70                 {
       
    71                     cpix_Field_release(&field);
       
    72                 }
       
    73         }
       
    74 
       
    75     return rv;
       
    76 }
       
    77 
       
    78 
       
    79 cpix_Document * CreateSmsDoc(Itk::TestMgr  * testMgr,
       
    80                              size_t          docUid,
       
    81                              const wchar_t * body,
       
    82                              Cpt::Mutex    & cpixMutex)
       
    83 {
       
    84     using namespace std;
       
    85 
       
    86     wstring 
       
    87         docUidStr = GetItemId(docUid); 
       
    88     cpix_Result
       
    89         result;
       
    90 
       
    91     Cpt::SyncRegion
       
    92         sr(cpixMutex);
       
    93 
       
    94     cpix_Document
       
    95         * doc = cpix_Document_create(&result,
       
    96                                      docUidStr.c_str(),
       
    97                                      SMSAPPCLASS,
       
    98                                      body,
       
    99                                      NULL);
       
   100     ITK_ASSERT(testMgr,
       
   101                cpix_Succeeded(&result),
       
   102                "Failed to create document for SMS");
       
   103 
       
   104     bool
       
   105         success = AddField(doc,
       
   106                            LTO_FIELD,
       
   107                           L"+3585554444",
       
   108                           cpix_STORE_YES | cpix_INDEX_UNTOKENIZED);
       
   109 
       
   110     if (success)
       
   111         {
       
   112             success = AddField(doc,
       
   113                                LBODY_FIELD,
       
   114                                body,
       
   115                                cpix_STORE_NO | cpix_INDEX_TOKENIZED);
       
   116         }
       
   117 
       
   118     if (!success)
       
   119         {
       
   120             cpix_Document_destroy(doc);
       
   121 
       
   122             ITK_ASSERT(testMgr,
       
   123                        false,
       
   124                        "Could not add field(s) to SMS doc");
       
   125         }
       
   126 
       
   127     return doc;
       
   128 }
       
   129                               
       
   130 
       
   131 // TODO these SyncedAdd operations must evolve to lock on Itk::TestMgr
       
   132 // * instance (or have a synced Itk::TestMgr derivant class)
       
   133 
       
   134 
       
   135 
       
   136 /**
       
   137  * Reports the CPIX error if the last operation on cpix_Obj
       
   138  * failed. Also clears the error status on cpix_Obj (necessary for
       
   139  * error info lifetime mgmt).
       
   140  *
       
   141  * @return if the last operation cpix_Obj was successful, that is,
       
   142  * it's return valus is equivalent to calling
       
   143  * cpix_Succeeded(cpix_Obj). (But note, that this call clears the
       
   144  * error status, thus a cpix_Succeeded(cpix_Obj) call after a call to
       
   145  * this function will alsways return true).
       
   146  */
       
   147 template <typename CPIX_OBJ>
       
   148 bool ReportIfFailed(Itk::TestMgr * testMgr,
       
   149                     CPIX_OBJ     * cpix_Obj,
       
   150                     Cpt::Mutex   & cpixMutex)
       
   151 {
       
   152     bool
       
   153         succeeded = true;
       
   154 
       
   155     if (cpix_Failed(cpix_Obj))
       
   156         {
       
   157             succeeded = false;
       
   158 
       
   159             wchar_t
       
   160                 buffer[256];
       
   161 
       
   162             Cpt::SyncRegion
       
   163                 sr(cpixMutex);
       
   164 
       
   165             cpix_Error_report(cpix_Obj->err_,
       
   166                               buffer,
       
   167                               sizeof(buffer) / sizeof(wchar_t));
       
   168             ITK_MSG(testMgr,
       
   169                     "CPIX failure: %S",
       
   170                     buffer);
       
   171             cpix_ClearError(cpix_Obj);
       
   172         }
       
   173 
       
   174     return succeeded;
       
   175 }
       
   176 
       
   177 
       
   178 
       
   179 /**
       
   180  * Adds an SMS item to an index using the async API, but it is used as
       
   181  * a sync API here.
       
   182  */
       
   183 class SyncedAdd
       
   184 {
       
   185     Cpt::SyncQueue<cpix_JobId>   q_;
       
   186 
       
   187     Cpt::Mutex                 & cpixMutex_;
       
   188 
       
   189 public:
       
   190     
       
   191     SyncedAdd(Cpt::Mutex & cpixMutex)
       
   192         : q_(1),
       
   193           cpixMutex_(cpixMutex)
       
   194     {
       
   195         ;
       
   196     }
       
   197 
       
   198 
       
   199     void call(cpix_IdxDb    * idxDb,
       
   200               cpix_Document * doc,
       
   201               cpix_Analyzer * analyzer,
       
   202               Itk::TestMgr  * testMgr)
       
   203     {
       
   204         cpix_JobId
       
   205             jobId;
       
   206 
       
   207         {
       
   208             Cpt::SyncRegion
       
   209                 sr(cpixMutex_);
       
   210 
       
   211             jobId = cpix_IdxDb_asyncAdd(idxDb,
       
   212                                         doc,
       
   213                                         analyzer,
       
   214                                         this,
       
   215                                         &callback);
       
   216         }
       
   217 
       
   218         ITK_ASSERT(testMgr,
       
   219                    ReportIfFailed(testMgr,
       
   220                                   idxDb,
       
   221                                   cpixMutex_),
       
   222                    "Making async call failed");
       
   223 
       
   224         cpix_JobId
       
   225             jobId2;
       
   226 
       
   227         bool 
       
   228             couldGet = q_.get(&jobId2);
       
   229         
       
   230         ITK_ASSERT(testMgr,
       
   231                    jobId == jobId2,
       
   232                    "Messed up callback!");
       
   233 
       
   234         if (couldGet)
       
   235             {
       
   236                 {
       
   237                     Cpt::SyncRegion
       
   238                         sr(cpixMutex_);
       
   239                     
       
   240                     cpix_IdxDb_asyncAddResults(idxDb,
       
   241                                                jobId);
       
   242                 }
       
   243 
       
   244                 ITK_EXPECT(testMgr,
       
   245                            ReportIfFailed(testMgr,
       
   246                                           idxDb,
       
   247                                           cpixMutex_),
       
   248                            "Synced addition failed");
       
   249 
       
   250                 if (cpix_Succeeded(idxDb))
       
   251                     {
       
   252                         ITK_MSG(testMgr,
       
   253                                 "Indexed");
       
   254                     }
       
   255             }
       
   256         else
       
   257             {
       
   258                 ITK_ASSERT(testMgr,
       
   259                            false,
       
   260                            "Could not get result from async call");
       
   261             }
       
   262     }
       
   263      
       
   264 
       
   265 private:
       
   266     static void callback(void       * cookie,
       
   267                          cpix_JobId   jobId)
       
   268     {
       
   269         SyncedAdd
       
   270             * this_ = reinterpret_cast<SyncedAdd*>(cookie);
       
   271 
       
   272         this_->q_.put(jobId);
       
   273     }
       
   274 };
       
   275 
       
   276 
       
   277 
       
   278 /**
       
   279  * Deletes an SMS item from an index using the async API, but it is used as
       
   280  * a sync API here.
       
   281  */
       
   282 class SyncedDel
       
   283 {
       
   284     Cpt::SyncQueue<cpix_JobId>   q_;
       
   285     Cpt::Mutex                 & cpixMutex_;
       
   286 
       
   287 
       
   288 public:
       
   289     
       
   290     SyncedDel(Cpt::Mutex & cpixMutex)
       
   291         : q_(1),
       
   292           cpixMutex_(cpixMutex)
       
   293     {
       
   294         ;
       
   295     }
       
   296 
       
   297 
       
   298     void call(cpix_IdxDb    * idxDb,
       
   299               const wchar_t * docUid,
       
   300               Itk::TestMgr  * testMgr)
       
   301     {
       
   302         cpix_JobId
       
   303             jobId;
       
   304 
       
   305         {
       
   306             Cpt::SyncRegion
       
   307                 sr(cpixMutex_);
       
   308 
       
   309             jobId = cpix_IdxDb_asyncDeleteDocuments(idxDb,
       
   310                                                     docUid,
       
   311                                                     this,
       
   312                                                     &callback);
       
   313         }
       
   314 
       
   315         ITK_ASSERT(testMgr,
       
   316                    ReportIfFailed(testMgr,
       
   317                                   idxDb,
       
   318                                   cpixMutex_),
       
   319                    "could not make async call");
       
   320 
       
   321         cpix_JobId
       
   322             jobId2;
       
   323 
       
   324         bool
       
   325             couldGet = q_.get(&jobId2);
       
   326 
       
   327         ITK_ASSERT(testMgr,
       
   328                    jobId == jobId2,
       
   329                    "Messed up callback");
       
   330 
       
   331         if (couldGet)
       
   332             {
       
   333                 int32_t
       
   334                     rv;
       
   335 
       
   336                 {
       
   337                     Cpt::SyncRegion
       
   338                         sr(cpixMutex_);
       
   339 
       
   340                     rv = cpix_IdxDb_asyncDeleteDocumentsResults(idxDb,
       
   341                                                                 jobId);
       
   342                 }
       
   343 
       
   344                 ITK_EXPECT(testMgr,
       
   345                            ReportIfFailed(testMgr,
       
   346                                           idxDb,
       
   347                                           cpixMutex_),
       
   348                            "Synced delete failed");
       
   349 
       
   350                 if (cpix_Succeeded(idxDb))
       
   351                     {
       
   352                         ITK_MSG(testMgr,
       
   353                                 "Deleted %d",
       
   354                                 rv);
       
   355                     }
       
   356             }
       
   357         else
       
   358             {
       
   359                 ITK_ASSERT(testMgr,
       
   360                            false,
       
   361                            "Could not get result from async call");
       
   362             }
       
   363     }
       
   364      
       
   365 
       
   366 private:
       
   367     static void callback(void       * cookie,
       
   368                          cpix_JobId   jobId)
       
   369     {
       
   370         SyncedDel
       
   371             * this_ = reinterpret_cast<SyncedDel*>(cookie);
       
   372 
       
   373         this_->q_.put(jobId);
       
   374     }
       
   375 };
       
   376 
       
   377 
       
   378 
       
   379 /**
       
   380  * Updates an SMS item to an index using the async API, but it is used as
       
   381  * a sync API here.
       
   382  */
       
   383 class SyncedUpdate
       
   384 {
       
   385     Cpt::SyncQueue<cpix_JobId>   q_;
       
   386 
       
   387     Cpt::Mutex                 & cpixMutex_;
       
   388 
       
   389 public:
       
   390     
       
   391     SyncedUpdate(Cpt::Mutex & cpixMutex)
       
   392         : q_(1),
       
   393           cpixMutex_(cpixMutex)
       
   394     {
       
   395         ;
       
   396     }
       
   397 
       
   398 
       
   399     void call(cpix_IdxDb    * idxDb,
       
   400               cpix_Document * doc,
       
   401               cpix_Analyzer * analyzer,
       
   402               Itk::TestMgr  * testMgr)
       
   403     {
       
   404         cpix_JobId
       
   405             jobId;
       
   406 
       
   407         {
       
   408             Cpt::SyncRegion
       
   409                 sr(cpixMutex_);
       
   410 
       
   411             jobId = cpix_IdxDb_asyncUpdate(idxDb,
       
   412                                            doc,
       
   413                                            analyzer,
       
   414                                            this,
       
   415                                            &callback);
       
   416         }
       
   417 
       
   418         ITK_ASSERT(testMgr,
       
   419                    ReportIfFailed(testMgr,
       
   420                                   idxDb,
       
   421                                   cpixMutex_),
       
   422                    "Could not make async call");
       
   423 
       
   424         cpix_JobId
       
   425             jobId2;
       
   426 
       
   427         bool
       
   428             couldGet = q_.get(&jobId2);
       
   429 
       
   430         ITK_ASSERT(testMgr,
       
   431                    jobId == jobId2,
       
   432                    "Messed up callback");
       
   433 
       
   434         if (couldGet)
       
   435             {
       
   436                 {
       
   437                     Cpt::SyncRegion
       
   438                         sr(cpixMutex_);
       
   439                     cpix_IdxDb_asyncUpdateResults(idxDb,
       
   440                                                   jobId);
       
   441                 }
       
   442                     
       
   443                 ITK_EXPECT(testMgr,
       
   444                            ReportIfFailed(testMgr,
       
   445                                           idxDb,
       
   446                                           cpixMutex_),
       
   447                            "Synced update failed");
       
   448 
       
   449                 if (cpix_Succeeded(idxDb))
       
   450                     {
       
   451                         ITK_MSG(testMgr,
       
   452                                 "Updated");
       
   453                     }
       
   454             }
       
   455         else
       
   456             {
       
   457                 ITK_ASSERT(testMgr,
       
   458                            false,
       
   459                            "Could not get result from async call");
       
   460             }
       
   461     }
       
   462      
       
   463 
       
   464 private:
       
   465     static void callback(void       * cookie,
       
   466                          cpix_JobId   jobId)
       
   467     {
       
   468         SyncedUpdate
       
   469             * this_ = reinterpret_cast<SyncedUpdate*>(cookie);
       
   470 
       
   471         this_->q_.put(jobId);
       
   472     }
       
   473 };
       
   474 
       
   475 
       
   476 
       
   477 class SyncedHousekeep
       
   478 {
       
   479     Cpt::SyncQueue<cpix_JobId>   q_;
       
   480     Cpt::Mutex                 & cpixMutex_;
       
   481 
       
   482 
       
   483 public:
       
   484     SyncedHousekeep(Cpt::Mutex & cpixMutex)
       
   485         : q_(1),
       
   486           cpixMutex_(cpixMutex)
       
   487     {
       
   488         ;
       
   489     }
       
   490 
       
   491 
       
   492     void call(Itk::TestMgr   * testMgr)
       
   493     {
       
   494         cpix_JobId
       
   495             jobId;
       
   496 
       
   497         cpix_Result
       
   498             result;
       
   499 
       
   500         {
       
   501             Cpt::SyncRegion
       
   502                 sr(cpixMutex_);
       
   503 
       
   504             jobId = cpix_asyncDoHousekeeping(&result,
       
   505                                              this,
       
   506                                              &callback);
       
   507         }
       
   508 
       
   509         ITK_ASSERT(testMgr,
       
   510                    ReportIfFailed(testMgr,
       
   511                                   &result,
       
   512                                   cpixMutex_),
       
   513                    "Performing async housekeeping failed");
       
   514 
       
   515         cpix_JobId
       
   516             jobId2;
       
   517 
       
   518         bool
       
   519             couldGet = q_.get(&jobId2);
       
   520 
       
   521         ITK_ASSERT(testMgr,
       
   522                    jobId == jobId2,
       
   523                    "Messed up callback!");
       
   524 
       
   525         if (couldGet)
       
   526             {
       
   527                 {
       
   528                     Cpt::SyncRegion
       
   529                         sr(cpixMutex_);
       
   530 
       
   531                     cpix_asyncDoHousekeepingResults(&result,
       
   532                                                     jobId);
       
   533 
       
   534                     ITK_EXPECT(testMgr,
       
   535                                ReportIfFailed(testMgr,
       
   536                                               &result,
       
   537                                               cpixMutex_),
       
   538                                "Synced doHousekeeping failed");
       
   539 
       
   540                     if (cpix_Succeeded(&result))
       
   541                         {
       
   542                             ITK_MSG(testMgr,
       
   543                                     "Housekeeping done");
       
   544                         }
       
   545                 }
       
   546             }
       
   547         else
       
   548             {
       
   549                 ITK_ASSERT(testMgr,
       
   550                            false,
       
   551                            "Could not get result from async call");
       
   552             }
       
   553     }
       
   554 
       
   555 
       
   556 
       
   557 private:
       
   558     static void callback(void               * cookie,
       
   559                          cpix_JobId           jobId)
       
   560     {
       
   561         SyncedHousekeep
       
   562             * this_ = reinterpret_cast<SyncedHousekeep*>(cookie);
       
   563 
       
   564         this_->q_.put(jobId);
       
   565     }
       
   566 
       
   567 
       
   568 };
       
   569 
       
   570 
       
   571 
       
   572 class SyncedDoc
       
   573 {
       
   574     Cpt::SyncQueue<cpix_JobId>   q_;
       
   575 
       
   576     Cpt::Mutex                 & cpixMutex_;
       
   577 
       
   578 public:
       
   579     SyncedDoc(Cpt::Mutex & cpixMutex)
       
   580         : q_(1),
       
   581           cpixMutex_(cpixMutex)
       
   582     {
       
   583         ;
       
   584     }
       
   585 
       
   586 
       
   587     bool call(cpix_Hits     * hits,
       
   588               int32_t         index,
       
   589               cpix_Document * target,
       
   590               Itk::TestMgr  * testMgr,
       
   591               bool            cancel)
       
   592     {
       
   593         bool
       
   594             rv = false;
       
   595 
       
   596         cpix_JobId
       
   597             jobId;
       
   598 
       
   599         {
       
   600             Cpt::SyncRegion
       
   601                 sr(cpixMutex_);
       
   602 
       
   603             jobId = cpix_Hits_asyncDoc(hits,
       
   604                                        index,
       
   605                                        target,
       
   606                                        this,
       
   607                                        &callback);
       
   608         }
       
   609         
       
   610         ITK_ASSERT(testMgr,
       
   611                    ReportIfFailed(testMgr,
       
   612                                   hits,
       
   613                                   cpixMutex_),
       
   614                    "Could not make async doc retrieval");
       
   615 
       
   616         if (cancel)
       
   617             {
       
   618                 cpix_CancelAction
       
   619                     cancelAction = cpix_CANCEL_ERROR;
       
   620 
       
   621                 {
       
   622                     Cpt::SyncRegion
       
   623                         sr(cpixMutex_);
       
   624                     
       
   625                     cancelAction = cpix_Hits_cancelDoc(hits,
       
   626                                                        jobId);
       
   627                 }
       
   628 
       
   629                 ReportIfFailed(testMgr,
       
   630                                hits,
       
   631                                cpixMutex_);
       
   632 
       
   633                 ITK_MSG(testMgr,
       
   634                         "Doc retrieval CANCELLED (%d)",
       
   635                         cancelAction);
       
   636 
       
   637                 // !!! Even if we did call cancel(), the callback
       
   638                 //     might have hitted us before the cancel()
       
   639                 //     returned.  we have to clear the status, but we
       
   640                 //     must not collect any results.
       
   641                 if (q_.full())
       
   642                     {
       
   643                         ITK_MSG(testMgr,
       
   644                                 "Clearing cancelled callback status...\n");
       
   645                         cpix_JobId
       
   646                             jobId2;
       
   647                         
       
   648                         bool
       
   649                             couldGet = q_.get(&jobId2);
       
   650                         
       
   651                         ITK_ASSERT(testMgr,
       
   652                                    jobId = jobId2,
       
   653                                    "Messed up callback");
       
   654                         ITK_MSG(testMgr,
       
   655                                 "... clearing cancelled callback status done\n");
       
   656                     }
       
   657             }
       
   658         else
       
   659             {
       
   660                 cpix_JobId
       
   661                     jobId2;
       
   662 
       
   663                 bool
       
   664                     couldGet = q_.get(&jobId2);
       
   665 
       
   666                 ITK_ASSERT(testMgr,
       
   667                            jobId == jobId2,
       
   668                            "Messed up callback");
       
   669 
       
   670                 if (couldGet)
       
   671                     {
       
   672                         {
       
   673                             Cpt::SyncRegion
       
   674                                 sr(cpixMutex_);
       
   675                             
       
   676                             cpix_Hits_asyncDocResults(hits,
       
   677                                                       jobId);
       
   678                         }
       
   679 
       
   680                         ITK_EXPECT(testMgr,
       
   681                                    ReportIfFailed(testMgr,
       
   682                                                   hits,
       
   683                                                   cpixMutex_),
       
   684                                    "Synced doc retrieval failed");
       
   685 
       
   686                         if (cpix_Succeeded(hits))
       
   687                             {
       
   688                                 ITK_MSG(testMgr,
       
   689                                         "Doc is retrieved");
       
   690                                 rv = true;
       
   691                             }
       
   692                     }
       
   693                 else
       
   694                     {
       
   695                         // not assert: this can happen
       
   696                         ITK_MSG(testMgr,
       
   697                                 false,
       
   698                                 "Could not get result from async hit doc");
       
   699                     }
       
   700             }
       
   701 
       
   702         return rv;
       
   703     }
       
   704 
       
   705 private:
       
   706     static void callback(void       * cookie,
       
   707                          cpix_JobId   jobId)
       
   708     {
       
   709         SyncedDoc
       
   710             * this_ = reinterpret_cast<SyncedDoc*>(cookie);
       
   711 
       
   712         this_->q_.put(jobId);
       
   713     }
       
   714 
       
   715 };
       
   716 
       
   717 
       
   718 
       
   719 
       
   720 
       
   721 class SyncedSearch
       
   722 {
       
   723     Cpt::SyncQueue<cpix_JobId>    q_;
       
   724 
       
   725     SyncedDoc                     syncedDoc_;
       
   726 
       
   727     cpix_Document                 targetDoc_;
       
   728 
       
   729     Cpt::Mutex                  & cpixMutex_;
       
   730 
       
   731 public:
       
   732     
       
   733     SyncedSearch(Cpt::Mutex & cpixMutex)
       
   734         : q_(1),
       
   735           syncedDoc_(cpixMutex),
       
   736           cpixMutex_(cpixMutex)
       
   737     {
       
   738         ;
       
   739     }
       
   740 
       
   741     void call(cpix_IdxSearcher  * searcher,
       
   742               cpix_Query        * query,
       
   743               Itk::TestMgr      * testMgr,
       
   744               bool                cancel)
       
   745     {
       
   746         // cancel = false;
       
   747 
       
   748         cpix_JobId
       
   749             jobId;
       
   750 
       
   751         {
       
   752             Cpt::SyncRegion
       
   753                 sr(cpixMutex_);
       
   754 
       
   755             jobId = cpix_IdxSearcher_asyncSearch(searcher,
       
   756                                                  query,
       
   757                                                  this,
       
   758                                                  &callback);
       
   759         }
       
   760 
       
   761         ITK_ASSERT(testMgr,
       
   762                    ReportIfFailed(testMgr,
       
   763                                   searcher,
       
   764                                   cpixMutex_),
       
   765                    "Could not make async call");
       
   766 
       
   767         if (cancel)
       
   768             {
       
   769                 cpix_CancelAction
       
   770                     cancelAction = cpix_CANCEL_ERROR;
       
   771 
       
   772                 {
       
   773                     Cpt::SyncRegion
       
   774                         sr(cpixMutex_);
       
   775 
       
   776                     cancelAction = cpix_IdxSearcher_cancelSearch(searcher,
       
   777                                                                  jobId);
       
   778                 }
       
   779 
       
   780                 ReportIfFailed(testMgr,
       
   781                                searcher,
       
   782                                cpixMutex_);
       
   783                 ITK_MSG(testMgr,
       
   784                         "Search/terms query CANCELLED (%d)",
       
   785                         cancelAction);
       
   786 
       
   787                 // !!! Even if we did call cancel(), the callback
       
   788                 //     might have hitted us before the cancel()
       
   789                 //     returned.  we have to clear the status, but we
       
   790                 //     must not collect any results.
       
   791                 if (q_.full())
       
   792                     {
       
   793                         ITK_MSG(testMgr,
       
   794                                 "Clearing cancelled callback status...\n");
       
   795                         cpix_JobId
       
   796                             jobId2;
       
   797                         
       
   798                         bool
       
   799                             couldGet = q_.get(&jobId2);
       
   800                         
       
   801                         ITK_ASSERT(testMgr,
       
   802                                    jobId = jobId2,
       
   803                                    "Messed up callback");
       
   804                         ITK_MSG(testMgr,
       
   805                                 "... clearing cancelled callback status done\n");
       
   806                     }
       
   807             }
       
   808         else
       
   809             {
       
   810 
       
   811                 cpix_JobId
       
   812                     jobId2;
       
   813 
       
   814                 bool
       
   815                     couldGet = q_.get(&jobId2);
       
   816 
       
   817                 ITK_ASSERT(testMgr,
       
   818                            jobId = jobId2,
       
   819                            "Messed up callback");
       
   820 
       
   821                 if (couldGet)
       
   822                     {
       
   823                         cpix_Hits
       
   824                             * hits = NULL;
       
   825 
       
   826                         {
       
   827                             Cpt::SyncRegion
       
   828                                 sr(cpixMutex_);
       
   829                             
       
   830                             hits = cpix_IdxSearcher_asyncSearchResults(searcher,
       
   831                                                                        jobId);
       
   832                         }
       
   833 
       
   834                         ITK_EXPECT(testMgr,
       
   835                                    ReportIfFailed(testMgr,
       
   836                                                   searcher,
       
   837                                                   cpixMutex_),
       
   838                                    "Synced search failed");
       
   839 
       
   840                         if (cpix_Succeeded(searcher))
       
   841                             {
       
   842                                 ITK_MSG(testMgr,
       
   843                                         "Search/terms query SUCCEEDED");
       
   844 
       
   845                                 printSome(hits,
       
   846                                           testMgr);
       
   847                             }
       
   848 
       
   849                         {
       
   850                             Cpt::SyncRegion
       
   851                                 sr(cpixMutex_);
       
   852                             cpix_Hits_destroy(hits);
       
   853                         }
       
   854                     }
       
   855                 else
       
   856                     {
       
   857                         ITK_ASSERT(testMgr,
       
   858                                    false,
       
   859                                    "Could not get result from async call");
       
   860                     }
       
   861             }
       
   862     }
       
   863      
       
   864 
       
   865 private:
       
   866 
       
   867     
       
   868     void printSome(cpix_Hits    * hits,
       
   869                    Itk::TestMgr * testMgr)
       
   870     {
       
   871         int32_t
       
   872             length;
       
   873 
       
   874         {
       
   875             Cpt::SyncRegion
       
   876                 sr(cpixMutex_);
       
   877 
       
   878             length = cpix_Hits_length(hits);
       
   879         }
       
   880 
       
   881         ITK_MSG(testMgr,
       
   882                 "Num of hits: %d",
       
   883                 length);
       
   884 
       
   885         enum 
       
   886         { 
       
   887             // The setup of havig SOME=10 and cancelling doc retrieval
       
   888             // operations for doc indexes on the condition "(i%4) ==
       
   889             // 1" is special because this way
       
   890             //
       
   891             // (a) sooner or later there is going to be an indexing
       
   892             //     operation during doc enumeration, invalidating the
       
   893             //     hits
       
   894             //
       
   895             // (b) the last doc retrieval (index 9) is cancelled,
       
   896             //     after which this hits is destroyed
       
   897             //
       
   898             // (c) this situation previously has crashed CPix
       
   899             SOME = 10
       
   900         };
       
   901 
       
   902         for (int32_t i = 0; i < SOME && i < length; ++i)
       
   903             {
       
   904                 bool
       
   905                     succeeded = syncedDoc_.call(hits,
       
   906                                                 i,
       
   907                                                 &targetDoc_,
       
   908                                                 testMgr,
       
   909                                                 (i%4) == 1); // cancel or not
       
   910 
       
   911                 if (succeeded)
       
   912                     {
       
   913                         Cpt::SyncRegion
       
   914                             sr(cpixMutex_);
       
   915 
       
   916                         PrintHit(&targetDoc_,
       
   917                                  testMgr);
       
   918                     }
       
   919             }
       
   920     }
       
   921 
       
   922 
       
   923 
       
   924     static void callback(void       * cookie,
       
   925                          cpix_JobId   jobId)
       
   926     {
       
   927         SyncedSearch
       
   928             * this_ = reinterpret_cast<SyncedSearch*>(cookie);
       
   929 
       
   930         this_->q_.put(jobId);
       
   931     }
       
   932     
       
   933 
       
   934 };
       
   935 
       
   936 
       
   937 
       
   938 
       
   939 
       
   940 
       
   941 class ASyncContext : public Itk::ITestContext
       
   942 {
       
   943 private:
       
   944     cpix_IdxDb       * idxDb1_;
       
   945     cpix_IdxDb       * idxDb2_;
       
   946     cpix_IdxSearcher * searcher1_;
       
   947     cpix_IdxSearcher * searcher2_;
       
   948     cpix_Analyzer    * analyzerI_; // for indexing thread
       
   949     cpix_Analyzer    * analyzerQ_; // for query thread
       
   950     cpix_QueryParser * queryParser_;
       
   951     cpix_Query       * searchQuery_;
       
   952     cpix_Query       * termsQuery_;
       
   953     
       
   954     LineTestCorpusRef  corpus_;
       
   955 
       
   956     /* OBS
       
   957     // TODO currently protecting both 
       
   958     //   (a) CPix (non-thread safe) and
       
   959     //   (b) Itk::TestMgr
       
   960     //
       
   961     // turn Itk::TestMgr into protected later, this tempMutex_ is to
       
   962     // be renamed, and it should protect individual calls (async and
       
   963     // sync alike) to cpix within these tests
       
   964     Cpt::Mutex         tempMutex_;
       
   965     */
       
   966 
       
   967     /**
       
   968      * CPix itself is to be invoked from a single thread (API is not
       
   969      * multithreaded). However, for sake of clarity, we test it from
       
   970      * multiple threads (indexing and searching client threads). So
       
   971      * they need to be synchronized - no two threads should be
       
   972      * executing an sync / async call at the same time.
       
   973      */
       
   974     Cpt::Mutex         cpixMutex_;
       
   975 
       
   976     bool               keepIndexing_;
       
   977 
       
   978     Itk::TestMgr     * testMgr_;
       
   979 
       
   980     /**
       
   981      * Statistics POV
       
   982      */
       
   983     struct Stats
       
   984     {
       
   985         std::string    name_;
       
   986         size_t         opCount_;
       
   987         long           opSumMs_;
       
   988 
       
   989         Stats(const char * name)
       
   990             : name_(name),
       
   991               opCount_(0),
       
   992               opSumMs_(0)
       
   993         {
       
   994             ;
       
   995         }
       
   996 
       
   997 
       
   998         void update(Cpt::StopperWatch & stopperWatch)
       
   999         {
       
  1000             ++opCount_;
       
  1001             opSumMs_ += stopperWatch.elapsedMSecs();
       
  1002         }
       
  1003 
       
  1004         
       
  1005         void output(Itk::TestMgr * testMgr)
       
  1006         {
       
  1007             if (opCount_ > 0)
       
  1008                 {
       
  1009                     ITK_REPORT(testMgr,
       
  1010                                name_.c_str(),
       
  1011                                "%ld ops in %ld ms (%.3f ms/op)",
       
  1012                                opCount_,
       
  1013                                opSumMs_,
       
  1014                                static_cast<double>(opSumMs_) 
       
  1015                                / static_cast<double>(opCount_));
       
  1016                 }
       
  1017             else
       
  1018                 {
       
  1019                     ITK_REPORT(testMgr,
       
  1020                                name_.c_str(),
       
  1021                                "%ld ops in %ld ms (### ms/op)",
       
  1022                                opCount_,
       
  1023                                opSumMs_);
       
  1024                 }
       
  1025         }
       
  1026 
       
  1027 
       
  1028         void reset()
       
  1029         {
       
  1030             opCount_ = 0;
       
  1031             opSumMs_ = 0;
       
  1032         }
       
  1033     };
       
  1034 
       
  1035 
       
  1036     // statistics for indexing
       
  1037     Stats              addStats_;
       
  1038     Stats              delStats_;
       
  1039     Stats              updateStats_;
       
  1040 
       
  1041     // statistics for search
       
  1042     Stats              searchStats_;
       
  1043     Stats              termsStats_;
       
  1044 
       
  1045 public:
       
  1046     virtual void setup() throw (Itk::PanicExc)
       
  1047     {
       
  1048         SetupSentry
       
  1049             ss(*this);
       
  1050 
       
  1051         cpix_Result
       
  1052             result;
       
  1053 
       
  1054         cpix_IdxDb_dbgScrapAll(&result);
       
  1055         if (cpix_Failed(&result))
       
  1056             {
       
  1057                 ITK_PANIC("Could not dbg scrapp all indexes");
       
  1058             }
       
  1059 
       
  1060         const Volume
       
  1061             *p = Volumes;
       
  1062 
       
  1063         for (; p->qbac_ != NULL; ++p)
       
  1064             {
       
  1065                 cpix_IdxDb_defineVolume(&result,
       
  1066                                         p->qbac_,
       
  1067                                         p->path_);
       
  1068 
       
  1069                 if (cpix_Failed(&result))
       
  1070                     {
       
  1071                         ITK_PANIC("Could not define volume '%s'",
       
  1072                                   p->qbac_);
       
  1073                     }
       
  1074             }
       
  1075 
       
  1076         cpix_IdxDb_defineVolume(&result,
       
  1077                                 SMS_QBASEAPPCLASS,
       
  1078                                 NULL);
       
  1079 
       
  1080         if (cpix_Failed(&result))
       
  1081             {
       
  1082                 ITK_PANIC("Could not define index for SMS");
       
  1083             }
       
  1084 
       
  1085         idxDb1_ = cpix_IdxDb_openDb(&result,
       
  1086                                     SMS_QBASEAPPCLASS,
       
  1087                                     cpix_IDX_CREATE);
       
  1088         if (cpix_Failed(&result))
       
  1089             {
       
  1090                 ITK_PANIC("Could not open(create) index for SMS");
       
  1091             }
       
  1092 
       
  1093         static const char
       
  1094             sms2Qbac[] = SMS_QBASEAPPCLASS "2";
       
  1095 
       
  1096         cpix_IdxDb_defineVolume(&result,
       
  1097                                 sms2Qbac,
       
  1098                                 NULL);
       
  1099 
       
  1100         if (cpix_Failed(&result))
       
  1101             {
       
  1102                 ITK_PANIC("Could not define index for SMS(2)");
       
  1103             }
       
  1104 
       
  1105         idxDb2_ = cpix_IdxDb_openDb(&result,
       
  1106                                     sms2Qbac,
       
  1107                                     cpix_IDX_CREATE);
       
  1108         if (cpix_Failed(&result))
       
  1109             {
       
  1110                 ITK_PANIC("Could not open(create) index for SMS(2)");
       
  1111             }
       
  1112 
       
  1113         searcher1_ = cpix_IdxSearcher_openDb(&result,
       
  1114                                              "root msg");
       
  1115         if (searcher1_ == NULL)
       
  1116             {
       
  1117                 ITK_PANIC("Could not create searcher");
       
  1118             }
       
  1119 
       
  1120         searcher2_ = cpix_IdxSearcher_openDb(&result,
       
  1121                                              "root");
       
  1122         if (searcher2_ == NULL)
       
  1123             {
       
  1124                 ITK_PANIC("Could not create searcher");
       
  1125             }
       
  1126         
       
  1127         analyzerI_ = cpix_CreateSimpleAnalyzer(&result);
       
  1128         
       
  1129         if (analyzerI_ == NULL)
       
  1130             {
       
  1131                 ITK_PANIC("Could not create analyzer");
       
  1132             }
       
  1133 
       
  1134         analyzerQ_ = cpix_CreateSimpleAnalyzer(&result);
       
  1135         
       
  1136         if (analyzerQ_ == NULL)
       
  1137             {
       
  1138                 ITK_PANIC("Could not create analyzer");
       
  1139             }
       
  1140 
       
  1141         queryParser_ = cpix_QueryParser_create(&result,
       
  1142                                                LCPIX_DEFAULT_FIELD,
       
  1143                                                analyzerQ_);
       
  1144         if (queryParser_ == NULL)
       
  1145             {
       
  1146                 ITK_PANIC("Could not create query parser");
       
  1147             }
       
  1148         
       
  1149         searchQuery_ = cpix_QueryParser_parse(queryParser_,
       
  1150                                               L"happy");
       
  1151         if (cpix_Failed(queryParser_)
       
  1152             || searchQuery_ == NULL)
       
  1153             {
       
  1154                 ITK_PANIC("Could not parse search query");
       
  1155             }
       
  1156 
       
  1157         cpix_QueryParser_destroy(queryParser_);
       
  1158         queryParser_ = NULL;
       
  1159 
       
  1160         queryParser_ = cpix_QueryParser_create(&result,
       
  1161                                                L"SecondaryTokens",
       
  1162                                                analyzerQ_);
       
  1163         if (queryParser_ == NULL)
       
  1164             {
       
  1165                 ITK_PANIC("Could not create query parser");
       
  1166             }
       
  1167 
       
  1168         termsQuery_ = cpix_QueryParser_parse(queryParser_,
       
  1169                                              L"ha* OR _aggregate:happy");
       
  1170         if (cpix_Failed(queryParser_)
       
  1171             || termsQuery_ == NULL)
       
  1172             {
       
  1173                 ITK_PANIC("Could not parse terms query");
       
  1174             }
       
  1175 
       
  1176         ss.setupComplete();
       
  1177     }
       
  1178 
       
  1179 
       
  1180     virtual void tearDown() throw()
       
  1181     {
       
  1182         cleanup();
       
  1183     }
       
  1184 
       
  1185 
       
  1186     virtual ~ASyncContext()
       
  1187     {
       
  1188         cleanup();
       
  1189     }
       
  1190 
       
  1191 
       
  1192     //
       
  1193     // public operations
       
  1194     //
       
  1195     ASyncContext()
       
  1196         : idxDb1_(NULL),
       
  1197           idxDb2_(NULL),
       
  1198           searcher1_(NULL),
       
  1199           searcher2_(NULL),
       
  1200           analyzerI_(NULL),
       
  1201           analyzerQ_(NULL),
       
  1202           queryParser_(NULL),
       
  1203           searchQuery_(NULL),
       
  1204           termsQuery_(NULL),
       
  1205           corpus_(DEFAULT_TEST_CORPUS_PATH),
       
  1206           keepIndexing_(true),
       
  1207           addStats_("adding"),
       
  1208           delStats_("deleting"),
       
  1209           updateStats_("updating"),
       
  1210           searchStats_("searching"),
       
  1211           termsStats_("term-qrying")
       
  1212     {
       
  1213         ;
       
  1214     }
       
  1215 
       
  1216 
       
  1217     
       
  1218     void testSingleThreadIdx(Itk::TestMgr * testMgr)
       
  1219     {
       
  1220         testMgr_ = testMgr;
       
  1221 
       
  1222         // cpix_setLogLevel(CPIX_LL_DEBUG);
       
  1223 
       
  1224         pthread_t
       
  1225             indexerThreadHndl;
       
  1226 
       
  1227         void
       
  1228             * rv;
       
  1229 
       
  1230         int
       
  1231             result = pthread_create(&indexerThreadHndl,
       
  1232                                     NULL,
       
  1233                                     &IndexerThreadFunc,
       
  1234                                     this);
       
  1235         ITK_ASSERT(testMgr,
       
  1236                    result == 0,
       
  1237                    "Could not create POSIX thread for indexing");
       
  1238 
       
  1239         printf("MAIN: Created indexer thread\n");
       
  1240 
       
  1241         printf("MAIN: waiting for worker thread (indexer)\n");
       
  1242 
       
  1243         result = pthread_join(indexerThreadHndl,
       
  1244                               &rv);
       
  1245         
       
  1246         ITK_EXPECT(testMgr,
       
  1247                    result == 0,
       
  1248                    "Could not join indexer thread");
       
  1249 
       
  1250         // cpix_setLogLevel(CPIX_LL_TRACE);
       
  1251 
       
  1252         printStatistics();
       
  1253     }
       
  1254     
       
  1255 
       
  1256 
       
  1257     void testSingleThreadQry(Itk::TestMgr * testMgr)
       
  1258     {
       
  1259         testMgr_ = testMgr;
       
  1260 
       
  1261         // cpix_setLogLevel(CPIX_LL_DEBUG);
       
  1262 
       
  1263         pthread_t
       
  1264             searcherThreadHndl;
       
  1265 
       
  1266         void
       
  1267             * rv;
       
  1268 
       
  1269         int
       
  1270             result = pthread_create(&searcherThreadHndl,
       
  1271                                     NULL,
       
  1272                                     &SearcherThreadFunc,
       
  1273                                     this);
       
  1274         ITK_ASSERT(testMgr,
       
  1275                    result == 0,
       
  1276                    "Could not create POSIX thread for searching");
       
  1277 
       
  1278         printf("MAIN: Created searcher thread\n");
       
  1279 
       
  1280         printf("MAIN: waiting for worker thread (searcher)\n");
       
  1281 
       
  1282         result = pthread_join(searcherThreadHndl,
       
  1283                               &rv);
       
  1284 
       
  1285         ITK_EXPECT(testMgr,
       
  1286                    result == 0,
       
  1287                    "Could not join searcher thread");
       
  1288 
       
  1289         // cpix_setLogLevel(CPIX_LL_TRACE);
       
  1290 
       
  1291         printStatistics();
       
  1292     }
       
  1293 
       
  1294 
       
  1295 
       
  1296     void testMultiThreads(Itk::TestMgr * testMgr)
       
  1297     {
       
  1298         cleanup();
       
  1299         setup();
       
  1300 
       
  1301         testMgr_ = testMgr;
       
  1302 
       
  1303         // cpix_setLogLevel(CPIX_LL_DEBUG);
       
  1304 
       
  1305         pthread_t
       
  1306             indexerThreadHndl,
       
  1307             searcherThreadHndl;
       
  1308 
       
  1309         void
       
  1310             * rv;
       
  1311 
       
  1312         int
       
  1313             result = pthread_create(&indexerThreadHndl,
       
  1314                                     NULL,
       
  1315                                     &IndexerThreadFunc,
       
  1316                                     this);
       
  1317         ITK_ASSERT(testMgr,
       
  1318                    result == 0,
       
  1319                    "Could not create POSIX thread for indexing");
       
  1320 
       
  1321         printf("MAIN: Created indexer thread\n");
       
  1322 
       
  1323         result = pthread_create(&searcherThreadHndl,
       
  1324                                 NULL,
       
  1325                                 &SearcherThreadFunc,
       
  1326                                 this);
       
  1327 
       
  1328         if (result != 0)
       
  1329             {
       
  1330                 keepIndexing_ = false;
       
  1331 
       
  1332                 result = pthread_join(indexerThreadHndl,
       
  1333                                       &rv);
       
  1334                 ITK_EXPECT(testMgr,
       
  1335                            result == 0,
       
  1336                            "Could not force closure of indexer thread");
       
  1337                 ITK_ASSERT(testMgr,
       
  1338                            false,
       
  1339                            "Could not create POSIX thread for searching");
       
  1340             }
       
  1341 
       
  1342 
       
  1343         printf("MAIN: Created searcher thread\n");
       
  1344         
       
  1345         printf("MAIN: waiting for both worker threads\n");
       
  1346 
       
  1347         result = pthread_join(indexerThreadHndl,
       
  1348                               &rv);
       
  1349         
       
  1350         ITK_EXPECT(testMgr,
       
  1351                    result == 0,
       
  1352                    "Could not join indexer thread");
       
  1353 
       
  1354         result = pthread_join(searcherThreadHndl,
       
  1355                               &rv);
       
  1356 
       
  1357         ITK_EXPECT(testMgr,
       
  1358                    result == 0,
       
  1359                    "Could not join searcher thread");
       
  1360 
       
  1361         // cpix_setLogLevel(CPIX_LL_TRACE);
       
  1362 
       
  1363         printStatistics();
       
  1364     }
       
  1365 
       
  1366 
       
  1367 private:
       
  1368     void cleanup()
       
  1369     {
       
  1370         cpix_IdxDb_releaseDb(idxDb1_);
       
  1371         idxDb1_ = NULL;
       
  1372 
       
  1373         cpix_IdxDb_releaseDb(idxDb2_);
       
  1374         idxDb2_ = NULL;
       
  1375         
       
  1376         cpix_IdxSearcher_releaseDb(searcher1_);
       
  1377         searcher1_ = NULL;
       
  1378 
       
  1379         cpix_IdxSearcher_releaseDb(searcher2_);
       
  1380         searcher2_ = NULL;
       
  1381 
       
  1382         cpix_Analyzer_destroy(analyzerI_);
       
  1383         analyzerI_ = NULL;
       
  1384 
       
  1385         cpix_Analyzer_destroy(analyzerQ_);
       
  1386         analyzerQ_ = NULL;
       
  1387 
       
  1388         cpix_QueryParser_destroy(queryParser_);
       
  1389         queryParser_ = NULL;
       
  1390 
       
  1391         cpix_Query_destroy(searchQuery_);
       
  1392         searchQuery_ = NULL;
       
  1393 
       
  1394         cpix_Query_destroy(termsQuery_);
       
  1395         termsQuery_ = NULL;
       
  1396     }
       
  1397 
       
  1398     
       
  1399     void printStatistics()
       
  1400     {
       
  1401         addStats_.output(testMgr_);
       
  1402         delStats_.output(testMgr_);
       
  1403         updateStats_.output(testMgr_);
       
  1404         searchStats_.output(testMgr_);
       
  1405         termsStats_.output(testMgr_);
       
  1406     }
       
  1407 
       
  1408 
       
  1409     void * indexStuff()
       
  1410     {
       
  1411         using namespace std;
       
  1412         using namespace Cpt;
       
  1413 
       
  1414         enum 
       
  1415         { ROUNDS        = 200, 
       
  1416           SAMPLE_START  = 180,
       
  1417           ACTION_PERIOD = 5,
       
  1418         };
       
  1419 
       
  1420         Cpt::StopperWatch
       
  1421             stopperWatch;
       
  1422 
       
  1423         SyncedAdd
       
  1424             syncedAdd(cpixMutex_);
       
  1425         SyncedDel
       
  1426             syncedDel(cpixMutex_);
       
  1427         SyncedUpdate
       
  1428             syncedUpdate(cpixMutex_);
       
  1429         SyncedHousekeep
       
  1430             syncedHousekeep(cpixMutex_);
       
  1431 
       
  1432         try
       
  1433             {
       
  1434                 int
       
  1435                     curId = 0;
       
  1436                 
       
  1437                 for (size_t i = 0; i < ROUNDS && keepIndexing_; ++i)
       
  1438                     {
       
  1439                         if (i == SAMPLE_START)
       
  1440                             {
       
  1441                                 addStats_.reset();
       
  1442                                 delStats_.reset();
       
  1443                                 updateStats_.reset();
       
  1444                             }
       
  1445 
       
  1446                         ++curId;
       
  1447                         std::wstring
       
  1448                             body(corpus_.item(curId));
       
  1449                         
       
  1450                         stopperWatch.reset();
       
  1451 
       
  1452                         cpix_Document
       
  1453                             * doc = CreateSmsDoc(testMgr_,
       
  1454                                                  curId,
       
  1455                                                  body.c_str(),
       
  1456                                                  cpixMutex_);
       
  1457                         
       
  1458                         syncedAdd.call(idxDb1_,
       
  1459                                        doc,
       
  1460                                        analyzerI_,
       
  1461                                        testMgr_);
       
  1462 
       
  1463                         {
       
  1464                             Cpt::SyncRegion
       
  1465                                 sr(cpixMutex_);
       
  1466                             cpix_Document_destroy(doc);
       
  1467                             doc = NULL;
       
  1468                         }
       
  1469 
       
  1470                         addStats_.update(stopperWatch);
       
  1471 
       
  1472                         stopperWatch.reset();
       
  1473 
       
  1474                         doc = CreateSmsDoc(testMgr_,
       
  1475                                            curId,
       
  1476                                            body.c_str(),
       
  1477                                            cpixMutex_);
       
  1478                         
       
  1479                         syncedAdd.call(idxDb2_,
       
  1480                                        doc,
       
  1481                                        analyzerI_,
       
  1482                                        testMgr_);
       
  1483 
       
  1484                         {
       
  1485                             Cpt::SyncRegion
       
  1486                                 sr(cpixMutex_);
       
  1487                             cpix_Document_destroy(doc);
       
  1488                             doc = NULL;
       
  1489                         }
       
  1490 
       
  1491                         addStats_.update(stopperWatch);
       
  1492 
       
  1493                         if (curId % ACTION_PERIOD == 0)
       
  1494                             {
       
  1495                                 stopperWatch.reset();
       
  1496 
       
  1497                                 wstring
       
  1498                                     docUid = GetItemId(curId/ACTION_PERIOD);
       
  1499 
       
  1500                                 syncedDel.call(idxDb1_,
       
  1501                                                docUid.c_str(),
       
  1502                                                testMgr_);
       
  1503 
       
  1504                                 delStats_.update(stopperWatch);
       
  1505 
       
  1506                                 stopperWatch.reset();
       
  1507 
       
  1508                                 doc = CreateSmsDoc(testMgr_,
       
  1509                                                    curId/ACTION_PERIOD,
       
  1510                                                    L"happy bla",
       
  1511                                                    cpixMutex_);
       
  1512 
       
  1513                                 syncedUpdate.call(idxDb2_,
       
  1514                                                   doc,
       
  1515                                                   analyzerI_,
       
  1516                                                   testMgr_);
       
  1517                                 
       
  1518                                 {
       
  1519                                     Cpt::SyncRegion
       
  1520                                         sr(cpixMutex_);
       
  1521                                     cpix_Document_destroy(doc);
       
  1522                                     doc = NULL;
       
  1523                                 }
       
  1524 
       
  1525                                 updateStats_.update(stopperWatch);
       
  1526 
       
  1527                                 ITK_DBGMSG(testMgr_, "+");
       
  1528 
       
  1529                                 syncedHousekeep.call(testMgr_);
       
  1530                             }
       
  1531                         else
       
  1532                             {
       
  1533                                 ITK_DBGMSG(testMgr_, ".");
       
  1534                             }
       
  1535                     }
       
  1536             }
       
  1537         catch (...)
       
  1538             {
       
  1539                 ITK_EXPECT(testMgr_,
       
  1540                            false,
       
  1541                            "INDEXER: Failed indexing\n");
       
  1542                 throw;
       
  1543             }
       
  1544 
       
  1545         syncedHousekeep.call(testMgr_);
       
  1546 
       
  1547         return NULL;
       
  1548     }
       
  1549 
       
  1550 
       
  1551     static void * IndexerThreadFunc(void * p)
       
  1552     {
       
  1553         ASyncContext
       
  1554             * thisPtr = reinterpret_cast<ASyncContext*>(p);
       
  1555         return thisPtr->indexStuff();
       
  1556     }
       
  1557 
       
  1558 
       
  1559     void * searchStuff()
       
  1560     {
       
  1561         using namespace Cpt;
       
  1562 
       
  1563         sleep(43);
       
  1564 
       
  1565         // on emulator, this amount of search happens together with
       
  1566         // indexing/deleting/updating, the rest runs alone, therefore
       
  1567         // distoring statistics (we are interested in how slow
       
  1568         // searching when (a) runs alone ("sq" test case) or when (b) runs mixed
       
  1569         // with indexing ("mt" test case).
       
  1570         enum 
       
  1571         { 
       
  1572             ROUNDS       = 21,
       
  1573             SAMPLE_START = 1
       
  1574         };
       
  1575 
       
  1576         Cpt::StopperWatch
       
  1577             stopperWatch;
       
  1578 
       
  1579         SyncedSearch
       
  1580             syncedSearch(cpixMutex_);
       
  1581 
       
  1582         try
       
  1583             {
       
  1584                 for (size_t i = 0; i < ROUNDS; ++i)
       
  1585                     {
       
  1586                         if (i == SAMPLE_START)
       
  1587                             {
       
  1588                                 searchStats_.reset();
       
  1589                                 termsStats_.reset();
       
  1590                             }
       
  1591 
       
  1592                         stopperWatch.reset();
       
  1593                             syncedSearch.call(searcher1_,
       
  1594                                               searchQuery_,
       
  1595                                               testMgr_,
       
  1596                                               i%2 == 1);
       
  1597 
       
  1598                         searchStats_.update(stopperWatch);
       
  1599 
       
  1600                         stopperWatch.reset();
       
  1601                             syncedSearch.call(searcher2_,
       
  1602                                               termsQuery_,
       
  1603                                               testMgr_,
       
  1604                                               i%2 == 1);
       
  1605 
       
  1606                         termsStats_.update(stopperWatch);
       
  1607                         
       
  1608                         ITK_DBGMSG(testMgr_, ":");
       
  1609                     }
       
  1610             }
       
  1611         catch (...)
       
  1612             {
       
  1613                 ITK_EXPECT(testMgr_,
       
  1614                            false,
       
  1615                            "SEARCHER: Failed searching\n");
       
  1616                 throw;
       
  1617             }
       
  1618 
       
  1619         return NULL;
       
  1620     }
       
  1621 
       
  1622 
       
  1623     static void * SearcherThreadFunc(void * p)
       
  1624     {
       
  1625         ASyncContext
       
  1626             * thisPtr = reinterpret_cast<ASyncContext*>(p);
       
  1627         return thisPtr->searchStuff();
       
  1628     }
       
  1629 
       
  1630 
       
  1631 };
       
  1632 
       
  1633 
       
  1634 
       
  1635 Itk::TesterBase * CreateASyncTests()
       
  1636 {
       
  1637     using namespace Itk;
       
  1638 
       
  1639     ASyncContext
       
  1640         * asyncContext = new ASyncContext();
       
  1641     ContextTester
       
  1642         * contextTester = new ContextTester("async",
       
  1643                                            asyncContext);
       
  1644 
       
  1645 #define TEST "si"
       
  1646     contextTester->add(TEST,
       
  1647                        asyncContext,
       
  1648                        &ASyncContext::testSingleThreadIdx,
       
  1649                        TEST);
       
  1650 #undef TEST
       
  1651 
       
  1652 #define TEST "sq"
       
  1653     contextTester->add(TEST,
       
  1654                        asyncContext,
       
  1655                        &ASyncContext::testSingleThreadQry,
       
  1656                        TEST,
       
  1657                        "CANCELLED"); // cancellation may happen in
       
  1658                                      // different ways
       
  1659 #undef TEST
       
  1660 
       
  1661 #define TEST "mt"
       
  1662     contextTester->add(TEST,
       
  1663                        asyncContext,
       
  1664                        &ASyncContext::testMultiThreads,
       
  1665                        TEST,
       
  1666                        SuiteTester::REDIRECT_ONLY);
       
  1667 #undef TEST
       
  1668 
       
  1669     return contextTester;
       
  1670 }