HCE project C++ developers source code library  1.1.1
HCE project developer library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
SphinxAdminCommand.cpp
Go to the documentation of this file.
1 #include <fstream>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <dirent.h>
5 #include <errno.h>
6 
7 #include <Poco/JSON/Object.h>
8 #include <Poco/JSON/Array.h>
9 #include <Poco/JSON/JSON.h>
10 #include <Poco/JSON/Stringifier.h>
11 #include <Poco/JSON/Parser.h>
12 #include <Poco/JSON/JSONException.h>
13 #include <Poco/Dynamic/Var.h>
14 #include <Poco/URI.h>
15 #include <Poco/String.h>
16 
17 #include "EncodeDecodeBase64.hpp"
18 #include "SphinxAdminCommand.hpp"
19 #include "SphinxDataSource.hpp"
20 #include "SphinxDataFile.hpp"
21 #include "SphinxSchemaFile.hpp"
22 #include "SphinxError.hpp"
23 #include "ProcExec.hpp"
24 #include "SphinxConfigCreator.hpp"
25 #include "XMLCleaner.hpp"
27 #include "SphinxConfigOptions.hpp"
28 #include "SphinxMessageConst.hpp"
29 
30 namespace HCE
31 {
32 namespace sphinx
33 {
34 //-----------------------------------------------------------------------------
36 : inherited(), fObj(fObj_), resultData(""), message(fObj.getCustomMessage())
37 {
38 }
39 //-----------------------------------------------------------------------------
40 bool SphinxAdminCommand::makeDir(const std::string& path)
41 {
42  bool result = false;
43  mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
44  struct stat st;
45 
46  if (stat(path.c_str(), &st) != 0)
47  {
48  if (mkdir(path.c_str(), mode) != 0)
49  errorMsg = strerror(errno);
50  else
51  result = true;
52  }
53  else if (!S_ISDIR(st.st_mode))
54  {
55  errorMsg = strerror(ENOTDIR);
56  }
57 
58  if (!result)
60 
61  return result;
62 }
63 //-----------------------------------------------------------------------------
64 bool SphinxAdminCommand::cleanDir(const std::string& path)
65 {
66  bool result = false;
67  if (isExistDir(path))
68  {
69  struct dirent* ent = nullptr;
70  DIR* dir = opendir (path.c_str());
71  if (dir != nullptr)
72  {
73  result = true;
74  std::string fileName;
75  while ((ent = readdir (dir)) != nullptr)
76  {
77  fileName = ent->d_name;
78  if (fileName != "." && fileName != "..")
79  {
80  fileName = path+"/"+ent->d_name;
81 
82  if (remove(fileName.c_str())==-1)
83  result = false;
84  }
85  }
86  if (closedir(dir)==-1)
87  result = false;
88  }
89  }
90  if (!result)
91  {
93  errorMsg = strerror(errno);
95  }
96  return result;
97 }
98 //-----------------------------------------------------------------------------
99 bool SphinxAdminCommand::isExistDir(const std::string& path)
100 {
101  bool result = false;
102  DIR* dir = nullptr;
103 
104  dir = opendir (path.c_str());
105  if (dir != nullptr)
106  {
107  if (closedir(dir)==-1)
108  errorMsg = strerror(errno);
109  else
110  result = true;
111  }
112  else
113  {
114  if (errno!=ENOENT)
115  errorMsg = strerror(errno);
116  }
117 
118  return result;
119 }
120 //-----------------------------------------------------------------------------
121 bool SphinxAdminCommand::isExistFile(const std::string& file)
122 {
123  return (access(file.c_str(), F_OK)==0);
124 }
125 //-----------------------------------------------------------------------------
126 bool SphinxAdminCommand::isAllowedString(const std::string& str)
127 {
128  return (str.find_first_not_of(sphinx_admin_command_const::allowedSimbols)==std::string::npos);
129 }
130 //-----------------------------------------------------------------------------
131 bool SphinxAdminCommand::copyFile(const std::string& srcFile, const std::string& dstFile)
132 {
133  bool result = false;
134  try
135  {
136  if (!isExistFile(srcFile))
137  throw Poco::Exception(srcFile+" not exists", ERROR_COPY_FILE);
138 
139  std::string cmd("cp");
140  std::vector<std::string> args = {srcFile, dstFile};
141 
142  std::stringstream outMsg;
143  ProcExec procExec(cmd, args);
144  if (!procExec.exec(outMsg, outMsg))
145  throw Poco::Exception("Copy '"+srcFile+"' to '"+dstFile+"' fail", ERROR_COPY_FILE);
146 
147  if (isExistError(outMsg.str()))
148  throw Poco::Exception(outMsg.str(), ERROR_COPY_FILE);
149 
150  result = true;
151  }
152  catch(Poco::Exception& e)
153  {
154  errorMsg = e.message();
155  errorCode = e.code();
156  }
157  return result;
158 }
159 //-----------------------------------------------------------------------------
160 bool SphinxAdminCommand::moveFile(const std::string& srcFile, const std::string& dstFile)
161 {
162  bool result = false;
163  try
164  {
165  if (!isExistFile(srcFile))
166  throw Poco::Exception(srcFile+" not exists", ERROR_MOVE_FILE);
167 
168  std::string cmd("mv");
169  std::vector<std::string> args = {srcFile, dstFile};
170 
171  std::stringstream outMsg;
172  ProcExec procExec(cmd, args);
173  if (!procExec.exec(outMsg, outMsg))
174  throw Poco::Exception("Move '"+srcFile+"' to '"+dstFile+"' fail", ERROR_MOVE_FILE);
175 
176  if (isExistError(outMsg.str()))
177  throw Poco::Exception(outMsg.str(), ERROR_MOVE_FILE);
178 
179  result = true;
180  }
181  catch(Poco::Exception& e)
182  {
183  errorMsg = e.message();
184  errorCode = e.code();
185  }
186  return result;
187 }
188 //-----------------------------------------------------------------------------
189 bool SphinxAdminCommand::removeFile(const std::string& file)
190 {
191  bool result = false;
192  if (remove(file.c_str())==0)
193  result = true;
194  else
195  {
196  errorMsg = strerror(errno);
198  }
199  return result;
200 }
201 //-----------------------------------------------------------------------------
202 bool SphinxAdminCommand::moveIndexFiles(const std::string& indexFileName, const std::string& srcPath, const std::string& dstPath)
203 {
204  errorMsg.clear();
205  bool result = false;
206 
207  struct dirent *d;
208  DIR* dir = opendir(srcPath.c_str());
209  if (dir != NULL)
210  {
211  result = true;
212  std::string oldName, newName;
213  while((d = readdir(dir)))
214  {
215  oldName = d->d_name;
216  if (oldName.find(indexFileName) != std::string::npos)
217  {
218  oldName = srcPath + "/" + d->d_name;
219  newName = dstPath + "/" + d->d_name;
220  if (!moveFile(oldName, newName))
221  {
222  result = false;
223  break;
224  }
225  }
226  }
227  if (closedir(dir)==-1)
228  {
229  errorMsg.append(" ").append(strerror(errno));
230  result = false;
231  }
232  }
233  return result;
234 }
235 //-----------------------------------------------------------------------------
236 bool SphinxAdminCommand::copyIndexFiles(const std::string& indexFileName, const std::string& srcPath, const std::string& dstPath)
237 {
238  errorMsg.clear();
239  bool result = false;
240 
241  struct dirent *d;
242  DIR* dir = opendir(srcPath.c_str());
243  if (dir != NULL)
244  {
245  result = true;
246  std::string oldName, newName;
247  while((d = readdir(dir)))
248  {
249  oldName = d->d_name;
250  if (oldName.find(indexFileName) != std::string::npos)
251  {
252  oldName = srcPath + "/" + d->d_name;
253  newName = dstPath + "/" + d->d_name;
254  if (!copyFile(oldName, newName))
255  {
256  result = false;
257  break;
258  }
259  }
260  }
261  if (closedir(dir)==-1)
262  {
263  errorMsg.append(" ").append(strerror(errno));
264  result = false;
265  }
266  }
267  return result;
268 }
269 //-----------------------------------------------------------------------------
270 bool SphinxAdminCommand::removeIndexFile(const std::string& indexFileName, const std::string& path)
271 {
272  errorMsg.clear();
273  bool result = false;
274 
275  struct dirent *d;
276  DIR* dir = opendir(path.c_str());
277  if (dir != NULL)
278  {
279  result = true;
280  std::string fileName;
281  std::vector<std::string> files;
282  while((d = readdir(dir)))
283  {
284  fileName = d->d_name;
285  if (fileName.compare(0, indexFileName.length(), indexFileName)==0)
286  {
287  if (!(d->d_name == std::string(".") || d->d_name == std::string("..")))
288  {
289  fileName = path + "/" + d->d_name;
290  files.push_back(fileName);
291  }
293  }
294  }
295  if (closedir(dir)==-1)
296  {
297  errorMsg.append(" ").append(strerror(errno));
298  result = false;
299  }
300  // remove all found index files
301  for (size_t i=0;i<files.size();++i)
302  {
304  if (remove(files[i].c_str())!=0)
305  {
306  result = false;
308  }
309  }
310  }
311  else
313 
314  if (!errorMsg.empty())
316 
317  return result;
318 }
319 //-----------------------------------------------------------------------------
320 bool SphinxAdminCommand::getFileList(const std::string& path, std::vector<std::string>& vFiles, const std::string& ext)
321 {
322  bool result = false;
323  DIR* dir = nullptr;
324 
325  std::string findExtension = "."+ext;
326  dir = opendir (path.c_str());
327  if (dir != nullptr)
328  {
329  struct dirent* ent = nullptr;
330  while ((ent = readdir (dir)) != nullptr)
331  {
332  std::string sourceFileName(ent->d_name);
333  size_t found = sourceFileName.find(findExtension);
334  if (found !=std::string::npos)
335  {
336  sourceFileName = sourceFileName.substr(0, found);
337  vFiles.push_back(sourceFileName);
338  }
339  }
340  if (closedir(dir)==-1)
341  errorMsg = strerror(errno);
342  else
343  result = true;
344  }
345  else
346  errorMsg = strerror(errno);
347 
348  if (!result)
349  {
352  }
353 
354  return result;
355 }
356 //-----------------------------------------------------------------------------
357 bool SphinxAdminCommand::getIndexList(const std::string& path, std::vector<std::string>& vIndexes)
358 {
359  vIndexes.clear();
360  bool result = false;
361  DIR* dir = nullptr;
362  struct dirent* ent = nullptr;
363 
364  dir = opendir (path.c_str());
365  if (dir != nullptr)
366  {
367  std::set<std::string> sIndexes;
368  std::string fileName;
369  while ((ent = readdir (dir)) != nullptr)
370  {
371  if (!(ent->d_name == std::string(".") || ent->d_name == std::string("..")))
372  {
373  fileName = ent->d_name;
374  size_t found = fileName.find_last_of('.');
375  if (found!=std::string::npos)
376  {
377  sIndexes.insert(fileName.substr(0, found));
378  }
379  }
380  }
381  if (closedir(dir)==-1)
382  errorMsg = strerror(errno);
383  else
384  {
385  vIndexes.assign(sIndexes.begin(), sIndexes.end());
386  result = true;
387  }
388  }
389  else
390  errorMsg = strerror(errno);
391 
392  if (!result)
393  {
396  }
397 
398  return result;
399 }
400 //-----------------------------------------------------------------------------
402 {
403  bool result = false;
404 
405  try
406  {
407  if (fObj.getDataDir().empty())
408  throw Poco::Exception(message(message_const::EMPTY_DATA_DIR));
409 
410  std::set<unsigned int> ports;
411  DIR* dir = nullptr;
412  struct dirent* ent = nullptr;
413 
414  dir = opendir (fObj.getDataDir().c_str());
415  if (dir == nullptr)
416  throw Poco::Exception(message(message_const::OPEN_DIR_FAIL, fObj.getDataDir())+message(message_const::ERROR, strerror(errno)));
417 
418  Poco::AutoPtr<SphinxConfigCreator> pConf = nullptr;
419  while ((ent = readdir (dir)) != nullptr)
420  {
421  std::string name = ent->d_name;
422  if (!(name=="."||name==".."))
423  {
424  if (isExistDir(fObj.getDataDir()+"/"+name))
425  {
426  const std::string propFile = fObj.getDataDir()+"/"+ent->d_name+"/"+sphinx_search_const::sphinxPropertyFile;
427 
428  try
429  {
430  pConf = new SphinxConfigCreator(propFile);
431 
432  std::string host;
433  unsigned int port;
435  ports.insert(port);
436  }
437  catch(std::exception& exc)
438  {
440  }
441  }
442  else
443  fObj.log() << message(message_const::TRY_USE_AS_DIRECTORY_WAS_CANCELED) << "'" << fObj.getDataDir() << "/" << name << "'" << std::endl;
444  }
445  }
446 
447  if (closedir(dir)==-1)
448  throw Poco::Exception(message(message_const::CLOSE_DIR_FAIL)+message(message_const::ERROR, strerror(errno)));
449 
451  {
452  std::set<unsigned int>::iterator iter = ports.find(i);
453  if (iter==ports.end())
454  {
455  res = i;
456  break;
457  }
458  }
460  result = true;
461  }
462  catch(Poco::Exception& e)
463  {
464  errorMsg = e.message();
467  }
468  return result;
469 }
470 //-----------------------------------------------------------------------------
471 bool SphinxAdminCommand::makeTrunkConfig(const std::string& trunkName, const std::string& indexName, const std::string& indexFileName,
472  SphinxConfigOptions& configOptions)
473 {
474  bool result = false;
475  const std::string path = fObj.getDataDir()+"/"+indexName;
476  const std::string propFile = path+"/"+sphinx_search_const::sphinxPropertyFile;
477  const std::string sphinxConfigFile = path+"/"+sphinx_search_const::sphinxConfigName;
478  try
479  {
480  Poco::AutoPtr<SphinxConfigCreator> pConf = new SphinxConfigCreator(propFile);
481 
482  // saved for possibility restore
483  configOptions.setCreatedDate(pConf->getUInt64(sphinx_admin_command_const::optionsCreatedDate, 0));
484  pConf->remove(sphinx_admin_command_const::sectionOptions); // remove need to sphinx indexer
485 
486  std::vector<std::string> keys;
487  pConf->keys(keys);
488 
489  for (size_t i=0;i<keys.size();++i)
490  {
491  if (keys[i].find(sphinx_search_const::sourceNameField)!=std::string::npos)
492  {
493  std::string name = keys[i]+"."+sphinx_search_const::xmlpipeCommandNameField;
494  std::string value = "cat "+path+"/"+sphinx_admin_command_const::dataDir+"/"+indexFileName+"."+sphinx_admin_command_const::sourceFileExtension;
495  pConf->setString(name, value);
496  }
497  }
498  std::string name = sphinx_search_const::indexNameField+" "+trunkName+"."+sphinx_search_const::pathNameField;
499  std::string value = path+"/"+trunkName;
500  pConf->setString(name, value);
501 
502  value = fObj.getLogDir()+"/"+indexName+"/"+sphinx_search_const::searchdLogFile;
503  pConf->setString(sphinx_search_const::searchdLogName, value);
504 
505  value = fObj.getRunDir()+"/"+/*indexName+"/"+*/
506  sphinx_search_const::searchdPidFileName+"_"+indexName+"."+
508  pConf->setString(sphinx_search_const::searchdPidName, value);
509 
510  value = fObj.getLogDir()+"/"+indexName+"/"+sphinx_search_const::searchdQueryLogFile;
511  pConf->setString(sphinx_search_const::searchdQueryLogName, value);
512 
513  pConf->save(propFile);
514  pConf->setPropertyFileConfiguration(propFile);
515 
516  std::ofstream ofs(sphinxConfigFile.c_str(), std::fstream::trunc);
517  ofs << *pConf;
518  ofs.close();
519 
520  // apply property options to config
521  writePropertyOptions(*pConf, configOptions);
522  pConf->save(propFile);
523 
524  result = true;
525  }
526  catch(Poco::Exception& e)
527  {
528  errorMsg = e.message();
530  }
531  return result;
532 }
533 //-----------------------------------------------------------------------------
534 bool SphinxAdminCommand::isExistError(const std::string& procExecMsg)
535 {
536  return ((procExecMsg.find(sphinx_admin_command_const::procExecErrorMsg)!=std::string::npos) ||
537  (procExecMsg.find(sphinx_admin_command_const::procExecFatalMsg)!=std::string::npos));
538 }
539 //-----------------------------------------------------------------------------
540 std::string SphinxAdminCommand::getPropertyFileName(const std::string& indexPath, const std::string& branchName)
541 {
543 }
544 //-----------------------------------------------------------------------------
545 std::string SphinxAdminCommand::getConfigFileName(const std::string& indexPath, const std::string& branchName)
546 {
547  return indexPath+"/"+sphinx_admin_command_const::dataDir+"/"+branchName+"_"+sphinx_search_const::branchConfigFile;
548 }
549 //-----------------------------------------------------------------------------
551 {
552  configCreator.setUInt64(sphinx_admin_command_const::optionsMaxDocId, configOptions.getMaxDocId());
553  configCreator.setUInt64(sphinx_admin_command_const::optionsCreatedDate, configOptions.getCreatedDate());
554  configCreator.setUInt64(sphinx_admin_command_const::optionsMergedDate, configOptions.getMergedDate());
555  configCreator.setString(sphinx_admin_command_const::optionsBranches, configOptions.getBranchesAsString());
556 }
557 //-----------------------------------------------------------------------------
558 //-----------------------------------------------------------------------------
559 Poco::SharedPtr<SphinxAdminCommand> SphinxAdminCommandFactory::create(SphinxFunctionalObject& fObj, const std::string& commandString)
560 {
561  Poco::SharedPtr<SphinxAdminCommand> pCmd;
562 
563  if (commandString == "INDEX_CREATE")
564  pCmd = new IndexCreate(fObj);
565  else if (commandString == "INDEX_CHECK")
566  pCmd = new IndexCheck(fObj);
567  else if (commandString == "INDEX_STORE_DATA_FILE")
568  pCmd = new IndexStoreDataFile(fObj);
569  else if (commandString == "INDEX_STORE_SCHEMA_FILE")
570  pCmd = new IndexStoreSchemaFile(fObj);
571  else if (commandString == "INDEX_REBUILD")
572  pCmd = new IndexRebuild(fObj);
573 // else if (commandString == "INDEX_SET_DATA_DIR") // not use
574 // pCmd = new IndexSetDataDir(fObj);
575  else if (commandString == "INDEX_START")
576  pCmd = new IndexStart(fObj);
577  else if (commandString == "INDEX_STOP")
578  pCmd = new IndexStop(fObj);
579  else if (commandString == "INDEX_MERGE")
580  pCmd = new IndexMerge(fObj);
581  else if (commandString == "INDEX_MERGE_TRUNK")
582  pCmd = new IndexMergeTrunk(fObj);
583  else if (commandString == "INDEX_DELETE_DATA_FILE")
584  pCmd = new IndexDeleteDataFile(fObj);
585  else if (commandString == "INDEX_DELETE_SCHEMA_FILE")
586  pCmd = new IndexDeleteSchemaFile(fObj);
587  else if (commandString == "INDEX_APPEND_DATA_FILE")
588  pCmd = new IndexAppendDataFile(fObj);
589  else if (commandString == "INDEX_DELETE_DOC")
590  pCmd = new IndexDeleteDoc(fObj);
591  else if (commandString == "INDEX_DELETE_DOC_NUMBER")
592  pCmd = new IndexDeleteDocNumber(fObj);
593  else if (commandString == "INDEX_PACK_DOC_DATA")
594  pCmd = new IndexPackDocData(fObj);
595  else if (commandString == "INDEX_REMOVE")
596  pCmd = new IndexRemove(fObj);
597  else if (commandString == "INDEX_COPY")
598  pCmd = new IndexCopy(fObj);
599  else if (commandString == "INDEX_RENAME")
600  pCmd = new IndexRename(fObj);
601  else if (commandString == "INDEX_SET_CONFIG_VAR")
602  pCmd = new IndexSetConfigVar(fObj);
603  else if (commandString == "INDEX_GET_CONFIG_VAR")
604  pCmd = new IndexGetConfigVar(fObj);
605  else if (commandString == "INDEX_CHECK_SCHEMA")
606  pCmd = new IndexCheckSchema(fObj);
607  else if (commandString == "INDEX_STATUS_SEARCHD")
608  pCmd = new IndexStatusSearchd(fObj);
609  else if (commandString == "INDEX_STATUS")
610  pCmd = new IndexStatus(fObj);
611  else if (commandString == "INDEX_MAX_DOC_ID")
612  pCmd = new IndexMaxDocId(fObj);
613  else if (commandString == "INDEX_DATA_LIST")
614  pCmd = new IndexDataList(fObj);
615  else if (commandString == "INDEX_BRANCHES_LIST")
616  pCmd = new IndexBranchesList(fObj);
617  else if (commandString == "INDEX_BRANCHES_INFO")
618  pCmd = new IndexBranchesInfo(fObj);
619  else if (commandString == "INDEX_BRANCHES_STATUS")
620  pCmd = new IndexBranchesStatus(fObj);
621  else if (commandString == "INDEX_CONNECT")
622  pCmd = new IndexConnect(fObj);
623  else if (commandString == "INDEX_DISCONNECT")
624  pCmd = new IndexDisconnect(fObj);
625 
626  return pCmd;
627 }
628 //-----------------------------------------------------------------------------
629 //-----------------------------------------------------------------------------
631 :inherited(fObj), indexName("")
632 {
633 }
634 //-----------------------------------------------------------------------------
635 bool IndexCreate::serialize(std::string& json)
636 {
637  _isError = true;
638  errorMsg.clear();
639  try
640  {
641  Poco::JSON::Object::Ptr obj = new Poco::JSON::Object();
643 
644  std::stringstream ostr;
645  Poco::JSON::Stringifier::stringify(obj, ostr);
646  json = ostr.str();
647 
648  _isError = false;
649  }
650  catch(std::exception& e)
651  {
652  errorMsg = e.what();
654  }
655  return !_isError;
656 }
657 //-----------------------------------------------------------------------------
658 bool IndexCreate::unserialize(const std::string& json)
659 {
660  indexName.clear();
661  errorMsg.clear();
662  _isError = true;
663  try
664  {
665  Poco::JSON::Parser parser;
666  Poco::Dynamic::Var res = parser.parse(json);
667  Poco::JSON::Object::Ptr obj = res.extract<Poco::JSON::Object::Ptr>();
668 
669  Poco::Dynamic::Var tmp = obj->get(sphinx_admin_command_const::indexName);
670  if (tmp.isString())
671  indexName = tmp.convert<std::string>();
672 
673  _isError = false;
674  }
675  catch(Poco::JSON::JSONException& e)
676  {
677  errorMsg = e.displayText();
679  }
680  return !_isError;
681 }
682 //-----------------------------------------------------------------------------
684 {
685  errorMsg.clear();
687  _isError = true;
688  try
689  {
690  std::string path = fObj.getDataDir()+"/"+indexName;
691 
692  if (isExistDir(path))
694 
695  unsigned int allowedPort = sphinx_search_const::defaultPort;
696 
697  if (!getFreeAllowedPort(allowedPort))
698  throw Poco::Exception(errorMsg, ERROR_CREATE_INDEX);
699 
700  if (!makeDir(path))
702 
703  std::string indexDir = path+"/"+sphinx_admin_command_const::indexDir;
704  std::string dataDir = path+"/"+sphinx_admin_command_const::dataDir;
705 
706  if (!makeDir(indexDir))
708 
709  if (!makeDir(dataDir))
711 
712  if (!isExistDir(indexDir))
713  throw Poco::Exception("Don't created index dir: '"+indexDir+"'", ERROR_CREATE_INDEX);
714 
715  if (!isExistDir(dataDir))
716  throw Poco::Exception("Don't created data dir: '"+dataDir+"'", ERROR_CREATE_INDEX);
717 
718  std::string srcFile = fObj.getEtcDir()+"/"+sphinx_search_const::sphinxSchemaFile;
719  std::string dstFile = path+"/"+sphinx_search_const::sphinxSchemaFile;
720 
721  if (copyFile(srcFile, dstFile))
722  {
724  dstFile = path+"/"+sphinx_search_const::sphinxPropertyFile;
725 
726  Poco::AutoPtr<SphinxConfigCreator> pConf = new SphinxConfigCreator(srcFile);
727 
728  std::vector<std::string> keys;
729  pConf->keys(keys);
730 
731  for (size_t i=0;i<keys.size();++i)
732  {
733  if (keys[i].find(sphinx_search_const::sourceNameField)!=std::string::npos)
734  {
735  std::string name = keys[i]+"."+sphinx_search_const::xmlpipeCommandNameField;
736  std::string value = pConf->getString(name);
737  size_t pos = value.find_last_of(' ');
738  if (pos!=std::string::npos)
739  value = value.substr(pos+1);
740 
741  std::stringstream str;
742  str << "cat " << dataDir << '/' << value;
743  pConf->setString(name, str.str());
744  }
745 
746  if (keys[i].find(sphinx_search_const::indexNameField)!=std::string::npos)
747  {
748  std::string name = keys[i]+"."+sphinx_search_const::pathNameField;
749  std::string value = pConf->getString(name);
750 
751  std::stringstream str;
752  str << indexDir << '/' << value;
753  pConf->setString(name, str.str());
754  }
755  }
756  // create structure run dir
757  std::string runDir = fObj.getRunDir();
758  if (!isExistDir(runDir))
759  if (!makeDir(runDir))
761 
762  // create structure log dir
763  std::string logDir = fObj.getLogDir();
764  if (!isExistDir(logDir))
765  if (!makeDir(logDir))
767 
768  logDir = fObj.getLogDir()+"/"+indexName;
769  if (!isExistDir(logDir))
770  if (!makeDir(logDir))
772 
773  // create content of property file
774  std::string value = logDir+"/"+sphinx_search_const::searchdLogFile;
775  pConf->setString(sphinx_search_const::searchdLogName, value);
776 
777  value = logDir+"/"+sphinx_search_const::searchdQueryLogFile;
778  pConf->setString(sphinx_search_const::searchdQueryLogName, value);
779 
780  value = runDir+"/"+sphinx_search_const::searchdPidFileName+"_"+indexName+"."+sphinx_search_const::searchdPidFileExt; // make pid file name
781  pConf->setString(sphinx_search_const::searchdPidName, value);
782 
783  value = fObj.getServerHost()+":"+std::to_string(allowedPort);
784  pConf->setString(sphinx_search_const::searchdListen, value);
785 
786  pConf->save(dstFile);
787  pConf->setPropertyFileConfiguration(dstFile);
788 
789  std::string sphinxConfig = path+"/"+sphinx_search_const::sphinxConfigName;
790  std::ofstream ofs(sphinxConfig.c_str(), std::fstream::trunc);
791  ofs << *pConf;
792  ofs.close();
793 
794  SphinxConfigOptions configOptions;
795  writePropertyOptions(*pConf, configOptions);
796  pConf->save(dstFile);
797  pConf->setPropertyFileConfiguration(dstFile);
798 
799  _isError = false;
800  }
801  }
802  catch(Poco::Exception& e)
803  {
804  errorMsg = e.message();
805  errorCode = e.code();
806  }
807  return !_isError;
808 }
809 //-----------------------------------------------------------------------------
810 //-----------------------------------------------------------------------------
812 :inherited(fObj)
813 {
814 }
815 //-----------------------------------------------------------------------------
817 {
818  errorMsg.clear();
820  _isError = true;
821  try
822  {
823  std::string path = fObj.getDataDir()+"/"+indexName;
824 
825  if (!isExistDir(path))
826  throw Poco::Exception(message(message_const::FOLDER_NOT_EXIST, path), ERROR_CHECK_INDEX);
827 
830 
833 
834  if (!isExistDir(fObj.getLogDir()+"/"+indexName))
836 
837  if (!isExistDir(fObj.getRunDir()))
839 
842 
845 
848 
849  _isError = false;
850  }
851  catch(Poco::Exception& e)
852  {
853  resultData = "0";
854  errorMsg = e.message();
855  errorCode = e.code();
856  }
857  resultData = (!_isError)?"1":"0";
858  return !_isError;
859 }
860 //-----------------------------------------------------------------------------
861 //-----------------------------------------------------------------------------
863 : inherited(fObj), indexName(""), branchName(""), dataContent("")
864 {
865 }
866 //-----------------------------------------------------------------------------
867 bool IndexStoreDataFile::serialize(std::string& json)
868 {
869  errorMsg.clear();
871  _isError = true;
872  try
873  {
874  Poco::JSON::Object::Ptr obj = new Poco::JSON::Object();
878 
879  std::stringstream ostr;
880  Poco::JSON::Stringifier::stringify(obj, ostr);
881  json = ostr.str();
882 
883  _isError = false;
884  }
885  catch(std::exception& e)
886  {
887  errorMsg = e.what();
889  }
890  return !_isError;
891 }
892 //-----------------------------------------------------------------------------
893 bool IndexStoreDataFile::unserialize(const std::string& json)
894 {
895  indexName.clear();
896  branchName.clear();
897  dataContent.clear();
898  errorMsg.clear();
899  _isError = true;
900  try
901  {
902  Poco::JSON::Parser parser;
903  Poco::Dynamic::Var res = parser.parse(json);
904  Poco::JSON::Object::Ptr obj = res.extract<Poco::JSON::Object::Ptr>();
905 
906  Poco::Dynamic::Var tmp = obj->get(sphinx_admin_command_const::indexName);
907  if (tmp.isString())
908  indexName = tmp.convert<std::string>();
909 
911  if (tmp.isString())
912  branchName = tmp.convert<std::string>();
913 
915  if (tmp.isString())
916  dataContent = tmp.convert<std::string>();
917 
918  _isError = false;
919  }
920  catch(Poco::JSON::JSONException& e)
921  {
922  errorMsg = e.displayText();
924  }
925  return !_isError;
926 }
927 //-----------------------------------------------------------------------------
929 {
930  errorMsg.clear();
932  _isError = true;
933  try
934  {
935  std::string path = fObj.getDataDir()+"/"+indexName;
936  if (!isExistDir(path))
937  throw Poco::Exception(message(message_const::FOLDER_NOT_EXIST, path), ERROR_STORE_DATA_FILE);
938 
939  path.append("/").append(sphinx_admin_command_const::dataDir);
940  if (!isExistDir(path))
941  throw Poco::Exception(message(message_const::FOLDER_NOT_EXIST, path), ERROR_STORE_DATA_FILE);
942 
943  std::stringstream str(HCE::decodeBase64(dataContent));
944  if (str.str().empty())
946 
948  {
949  SphinxDataFile dataFile;
950  dataFile.validateData(str);
951  if (dataFile.isError())
952  throw Poco::Exception(dataFile.getErrorMsg(), ERROR_STORE_DATA_FILE);
953  }
954 
956  {
960 
961  std::set<std::string> delList;
962  std::string outString = xmlCleaner.process(str.str(), delList);
963  str.str(outString);
964  }
965 
966  path.append("/").append(branchName).append(".dat");
967 
968  std::ofstream ofs(path.c_str(), std::fstream::trunc);
969  if (!ofs.is_open())
970  throw Poco::Exception(message(message_const::FILE_NOT_OPEN, path), ERROR_STORE_DATA_FILE);
971 
972  ofs << str.str();
973  ofs.close();
974  _isError = false;
975  }
976  catch(Poco::Exception& e)
977  {
978  errorMsg = e.displayText();
979  errorCode = e.code();
980  }
981  catch(std::exception& e)
982  {
983  errorMsg = e.what();
985  }
986  return !_isError;
987 }
988 //-----------------------------------------------------------------------------
989 //-----------------------------------------------------------------------------
990 //-----------------------------------------------------------------------------
992 : inherited(fObj), indexName(""), schemaContent("")
993 {
994 }
995 //-----------------------------------------------------------------------------
996 bool IndexStoreSchemaFile::serialize(std::string& json)
997 {
998  _isError = true;
999  errorMsg.clear();
1000  try
1001  {
1002  Poco::JSON::Object::Ptr obj = new Poco::JSON::Object();
1005 
1006  std::stringstream ostr;
1007  Poco::JSON::Stringifier::stringify(obj, ostr);
1008  json = ostr.str();
1009 
1010  _isError = false;
1011  }
1012  catch(std::exception& e)
1013  {
1014  errorMsg = e.what();
1016  }
1017  return !_isError;
1018 }
1019 //-----------------------------------------------------------------------------
1020 bool IndexStoreSchemaFile::unserialize(const std::string& json)
1021 {
1022  indexName.clear();
1023  schemaContent.clear();
1024  errorMsg.clear();
1025  _isError = true;
1026  try
1027  {
1028  Poco::JSON::Parser parser;
1029  Poco::Dynamic::Var res = parser.parse(json);
1030  Poco::JSON::Object::Ptr obj = res.extract<Poco::JSON::Object::Ptr>();
1031 
1032  Poco::Dynamic::Var tmp = obj->get(sphinx_admin_command_const::indexName);
1033  if (tmp.isString())
1034  indexName = tmp.convert<std::string>();
1035 
1037  if (tmp.isString())
1038  schemaContent = tmp.convert<std::string>();
1039 
1040  _isError = false;
1041  }
1042  catch(Poco::JSON::JSONException& e)
1043  {
1044  errorMsg = e.displayText();
1046  }
1047  return !_isError;
1048 }
1049 //-----------------------------------------------------------------------------
1051 {
1052  errorMsg.clear();
1053  errorCode = NO_ERROR;
1054  _isError = true;
1055  try
1056  {
1057  std::string path = fObj.getDataDir()+"/"+indexName;
1058  if (!isExistDir(path))
1059  throw Poco::Exception(message(message_const::FOLDER_NOT_EXIST, path), ERROR_STORE_SCHEMA_FILE);
1060 
1061  std::stringstream str(HCE::decodeBase64(schemaContent));
1062  if (str.str().empty())
1064 
1066  {
1067  SphinxSchemaFile schemaFile(str);
1068  std::vector<std::pair<std::string, int> > schemaVec;
1069  if (!schemaFile.getFields(schemaVec))
1071  }
1072  path.append("/").append(sphinx_search_const::sphinxSchemaFile);
1073 
1074  std::ofstream ofs(path.c_str(), std::fstream::trunc);
1075  if (!ofs.is_open())
1076  throw Poco::Exception(message(message_const::FILE_NOT_OPEN, path), ERROR_STORE_SCHEMA_FILE);
1077 
1079  ofs.close();
1080  _isError = false;
1081  }
1082  catch(Poco::Exception& e)
1083  {
1084  errorMsg = e.message();
1085  errorCode = e.code();
1086  }
1087  return !_isError;
1088 }
1089 //-----------------------------------------------------------------------------
1090 //-----------------------------------------------------------------------------
1092 : inherited(fObj), indexName(""), branches()
1093 {
1094 }
1095 //-----------------------------------------------------------------------------
1096 bool IndexRebuild::serialize(std::string& json)
1097 {
1098  _isError = true;
1099  errorMsg.clear();
1100  try
1101  {
1102  Poco::JSON::Object::Ptr obj = new Poco::JSON::Object();
1104 
1105  Poco::JSON::Array::Ptr vecBranches = new Poco::JSON::Array();
1106  obj->set(sphinx_admin_command_const::branches, vecBranches);
1107 
1108  for (size_t i=0;i<branches.size();++i)
1109  vecBranches->add(branches[i]);
1110 
1111  std::stringstream ostr;
1112  Poco::JSON::Stringifier::stringify(obj, ostr);
1113  json = ostr.str();
1114 
1115  _isError = false;
1116  }
1117  catch(std::exception& e)
1118  {
1119  errorMsg = e.what();
1121  }
1122  return !_isError;
1123 }
1124 //-----------------------------------------------------------------------------
1125 bool IndexRebuild::unserialize(const std::string& json)
1126 {
1127  indexName.clear();
1128  branches.clear();
1129  errorMsg.clear();
1130  _isError = true;
1131  try
1132  {
1133  Poco::JSON::Parser parser;
1134  Poco::Dynamic::Var res = parser.parse(json);
1135  Poco::JSON::Object::Ptr obj = res.extract<Poco::JSON::Object::Ptr>();
1136 
1137  Poco::Dynamic::Var tmp = obj->get(sphinx_admin_command_const::indexName);
1138  if (tmp.isString())
1139  indexName = tmp.convert<std::string>();
1140 
1141  Poco::JSON::Array::Ptr vecBranches = obj->getArray(sphinx_admin_command_const::branches);
1142  if (!vecBranches.isNull())
1143  {
1144  for (size_t k = 0;k<vecBranches->size();++k)
1145  {
1146  Poco::Dynamic::Var tmp = vecBranches->get(k);
1147  if (tmp.isString())
1148  {
1149  std::string branchName = tmp.convert<std::string>();
1150  if (isAllowedString(branchName))
1151  branches.push_back(branchName);
1152  else
1153  {
1156  if (!resultData.empty())
1157  resultData.append(",");
1158  resultData.append(branchName);
1159  }
1160  }
1161  }
1162  }
1163 
1164  _isError = false;
1165  }
1166  catch(Poco::JSON::JSONException& e)
1167  {
1168  errorMsg = e.displayText();
1170  }
1171  return !_isError;
1172 }
1173 //-----------------------------------------------------------------------------
1174 bool IndexRebuild::makeSource(const std::string& schemaFile, const std::string& branchName, const std::string& sourcePath, const std::string& configPath)
1175 {
1176  bool result = false;
1177  try
1178  {
1179  std::ifstream ifsSchema(schemaFile.c_str());
1180  if (!ifsSchema.is_open())
1181  throw Poco::Exception(message(message_const::FILE_NOT_OPEN, schemaFile), ERROR_MAKE_SOURCE);
1182 
1183  std::string dataFileName = sourcePath+"/"+branchName+"."+sphinx_admin_command_const::dataFileExtension;
1184  std::ifstream ifsDoc(dataFileName.c_str());
1185  if (!ifsDoc.is_open())
1186  {
1187  ifsSchema.close();
1188  throw Poco::Exception(message(message_const::FILE_NOT_OPEN, dataFileName), ERROR_MAKE_SOURCE);
1189  }
1190 
1191  std::string outputFileName = sourcePath+"/"+branchName+"."+sphinx_admin_command_const::sourceFileExtension;
1192 
1193  SphinxDataSource dataSource(ifsSchema, ifsDoc);
1194  std::fstream outputSource(outputFileName.c_str(), std::fstream::out | std::fstream::trunc);
1195  try
1196  {
1197  outputSource << dataSource << std::endl;
1198  result = makeIndex(outputFileName, branchName, configPath, dataSource.getMaxDocId());
1199  }
1200  catch(Poco::Exception& e)
1201  {
1204  }
1205  outputSource.close();
1206  ifsDoc.close();
1207  ifsSchema.close();
1208  }
1209  catch(Poco::Exception& e)
1210  {
1211  errorMsg = e.message();
1212  errorCode = e.code();
1214  }
1215  return result;
1216 }
1217 //-----------------------------------------------------------------------------
1218 bool IndexRebuild::makeIndex(const std::string& sourceFile, const std::string& branchName, const std::string& configPath, unsigned long long maxDocId)
1219 {
1220  const std::string propertyFile = getPropertyFileName(configPath, branchName);
1221  const std::string configFile = getConfigFileName(configPath, branchName);
1222  const std::string propFile = configPath+"/"+sphinx_search_const::sphinxPropertyFile;
1223  bool result = false;
1224  try
1225  {
1226  Poco::AutoPtr<SphinxConfigCreator> pConf = new SphinxConfigCreator(propFile);
1227 
1228  SphinxConfigOptions configOptions;
1229  configOptions.setMaxDocId(maxDocId);
1230  configOptions.addBranch(branchName);
1231  configOptions.setCreatedDate(pConf->getUInt64(sphinx_admin_command_const::optionsCreatedDate, 0));
1232 
1234 
1235  std::vector<std::string> keys;
1236  pConf->keys(keys);
1237 
1238  std::string sectionName;
1239  for (size_t i=0;i<keys.size();++i)
1240  {
1241  if (keys[i].find(sphinx_search_const::sourceNameField)!=std::string::npos)
1242  {
1243  std::string name = keys[i]+"."+sphinx_search_const::xmlpipeCommandNameField;
1244  std::stringstream str;
1245  str << "cat " << sourceFile;
1246  pConf->setString(name, str.str());
1247  }
1248  if (keys[i].find(sphinx_search_const::indexNameField)!=std::string::npos)
1249  {
1250  std::string name = keys[i]+"."+sphinx_search_const::pathNameField;
1251  std::stringstream str;
1252  str << configPath+"/"+sphinx_admin_command_const::indexDir << "/" << branchName;
1253  pConf->setString(name, str.str());
1254  sectionName = keys[i];
1255  }
1256  }
1257 
1258  pConf->save(propertyFile);
1259  pConf->setPropertyFileConfiguration(propertyFile);
1260  pConf->renameSphinxConfigSection(sectionName, "index "+branchName);
1261 
1262  std::ofstream ofs(configFile.c_str(), std::fstream::trunc);
1263  ofs << *pConf;
1264  ofs.close();
1265 
1266  pConf->clear();
1267  pConf->setPropertyFileConfiguration(propertyFile);
1268  pConf->cloneSphinxConfigSection(sectionName, "index "+branchName);
1269  pConf->remove(sectionName);
1270 
1271  writePropertyOptions(*pConf, configOptions);
1272  pConf->save(propertyFile);
1273 
1274  std::stringstream outMsg, errMsg;
1275  const std::string cmd("indexer --config " +configFile+" --all");
1277 
1278  ProcExec procExec(cmd);
1279  if (!procExec.exec(outMsg, errMsg))
1280  throw Poco::Exception(message(message_const::INDEXATION_FAIL, branchName)+message(message_const::ERROR, errMsg.str()));
1281 
1282  if (isExistError(outMsg.str()))
1283  throw Poco::Exception(outMsg.str());
1284 
1285  fObj.log() << outMsg.str() << std::endl;
1286  result = true; // (removeFile(propertyFile) && removeFile(configFile));
1287  }
1288  catch(Poco::Exception& e)
1289  {
1290  errorMsg = e.message();
1293  }
1294  return result;
1295 }
1296 //-----------------------------------------------------------------------------
1298 {
1299  errorMsg.clear();
1300  errorCode = NO_ERROR;
1301  _isError = true;
1302  try
1303  {
1304  if (branches.empty())
1306 
1307  std::string path = fObj.getDataDir()+"/"+indexName;
1308 
1309  if (!isExistDir(path))
1310  throw Poco::Exception(message(message_const::FOLDER_NOT_EXIST, path), ERROR_INDEX_REBUILD);
1311 
1312  std::string indexDir = path+"/"+sphinx_admin_command_const::indexDir;
1313  std::string dataDir = path+"/"+sphinx_admin_command_const::dataDir;
1314 
1315  if (!isExistDir(path+"/"+sphinx_admin_command_const::indexDir))
1316  throw Poco::Exception("Forder: '"+path+"/"+sphinx_admin_command_const::indexDir+"' not exists", ERROR_INDEX_REBUILD);
1317 
1318  if (!isExistDir(path+"/"+sphinx_admin_command_const::dataDir))
1319  throw Poco::Exception("Forder: '"+path+"/"+sphinx_admin_command_const::dataDir+"' not exists", ERROR_INDEX_REBUILD);
1320 
1321  const std::string schemaFileName = path+"/"+sphinx_search_const::sphinxSchemaFile;
1322  std::vector<std::string> vFiles;
1324  {
1325  unsigned int madeFailCount = 0;
1326  if (vFiles.size()==0)
1327  {
1328  throw Poco::Exception("Empty list of files data", ERROR_INDEX_REBUILD);
1329  }
1330  else if (branches.front()=="*")
1331  {
1332  if (!cleanDir(indexDir))
1333  throw Poco::Exception(errorMsg, errorCode);
1334 
1335  for (size_t i=0;i<vFiles.size();++i)
1336  {
1337  if (!makeSource(schemaFileName, vFiles[i], dataDir, path))
1338  {
1339  if (!resultData.empty())
1340  resultData.append(",");
1341  resultData.append(vFiles[i]);
1342  ++madeFailCount;
1343  }
1344  }
1345  }
1346  else
1347  {
1348  for (size_t k=0;k<branches.size();++k)
1349  for (size_t i=0;i<vFiles.size();++i)
1350  if (vFiles[i]==branches[k])
1351  {
1352  if (!makeSource(schemaFileName, vFiles[i], dataDir, path))
1353  {
1354  if (!resultData.empty())
1355  resultData.append(",");
1356  resultData.append(vFiles[i]);
1357  ++madeFailCount;
1358  }
1359  break;
1360  }
1361  }
1362  if (madeFailCount==0)
1363  _isError = false;
1364  }
1365  if (_isError)
1366  throw Poco::Exception(errorMsg, ERROR_INDEX_REBUILD);
1367  }
1368  catch(Poco::Exception& e)
1369  {
1370  errorMsg = e.message();
1371  errorCode = e.code();
1372  }
1373  return !_isError;
1374 }
1375 //-----------------------------------------------------------------------------
1376 //-----------------------------------------------------------------------------
1378 :inherited(fObj)
1379 {
1380 }
1381 //-----------------------------------------------------------------------------
1382 bool IndexSetDataDir::serialize(std::string& json)
1383 {
1384  //TODO
1385  return false;
1386 }
1387 //-----------------------------------------------------------------------------
1388 bool IndexSetDataDir::unserialize(const std::string& json)
1389 {
1390  //TODO
1391  return false;
1392 }
1393 //-----------------------------------------------------------------------------
1395 {
1396  //TODO
1397  return false;
1398 }
1399 //-----------------------------------------------------------------------------
1400 //-----------------------------------------------------------------------------
1402 :inherited(fObj)
1403 {
1404 }
1405 //-----------------------------------------------------------------------------
1407 {
1408  errorMsg.clear();
1409  errorCode = NO_ERROR;
1410  _isError = true;
1411  try
1412  {
1413  if (indexName.empty())
1415 
1416  // check and create if need structure run dir
1417  std::string runDir = fObj.getRunDir();
1418  if (!isExistDir(runDir))
1419  if (!makeDir(runDir))
1420  throw Poco::Exception("Don't created run dir: '"+runDir+"'", ERROR_INDEX_START);
1421 
1422  // check and create if need structure log dir
1423  std::string logDir = fObj.getLogDir();
1424  if (!isExistDir(logDir))
1425  if (!makeDir(logDir))
1426  throw Poco::Exception("Don't created log dir: '"+logDir+"'", ERROR_INDEX_START);
1427 
1428  // check and create if need structure log dir / index name
1429  logDir = fObj.getLogDir()+"/"+indexName;
1430  if (!isExistDir(logDir))
1431  if (!makeDir(logDir))
1432  throw Poco::Exception("Don't created default index log dir: '"+logDir+"'", ERROR_INDEX_START);
1433 
1434  std::string path = fObj.getDataDir()+"/"+indexName;
1435 
1436  if (!isExistDir(path))
1437  throw Poco::Exception("Index '"+path+"' not exist", ERROR_INDEX_START);
1438 
1439  path.append("/").append(sphinx_search_const::sphinxConfigName);
1440  if (!isExistFile(path))
1441  throw Poco::Exception("Config file '"+path+"' not exist", ERROR_INDEX_START);
1442 
1445  {
1446  bool isRunSearchd = fObj.isActiveSearchd();
1447  fObj.log() << "isRunSearchd = " << std::boolalpha << isRunSearchd << std::endl;
1448  fObj.log() << "IndexName: " << fObj.getIndexName() << std::endl;
1449 
1450  if (isRunSearchd)
1451  {
1452  fObj.log() << "STOPED Searchd: " << std::boolalpha << fObj.stopSearchd() << std::endl;
1453  }
1454  if (!fObj.startSearchd())
1455  throw Poco::Exception(fObj.getErrorMsg(), fObj.getErrorCode());
1456 
1457  _isError = false;
1458  }
1459  }
1460  catch(Poco::Exception& e)
1461  {
1462  errorMsg = e.message();
1463  errorCode = e.code();
1464  }
1465  return !_isError;
1466 }
1467 //-----------------------------------------------------------------------------
1468 //-----------------------------------------------------------------------------
1470 :inherited(fObj)
1471 {
1472 }
1473 //-----------------------------------------------------------------------------
1475 {
1476  errorMsg.clear();
1477  errorCode = NO_ERROR;
1478  _isError = true;
1479 
1480  try
1481  {
1482  if (indexName!=fObj.getIndexName())
1483  throw Poco::Exception("Index '"+indexName+"' not started", ERROR_INDEX_STOP);
1484 
1485  std::string path = fObj.getDataDir()+"/"+indexName;
1486  if (!isExistDir(path))
1487  throw Poco::Exception("Index '"+path+"' not exist", ERROR_INDEX_STOP);
1488 
1489  path.append("/").append(sphinx_search_const::sphinxConfigName);
1490  if (!isExistFile(path))
1491  throw Poco::Exception("Config file '"+path+"' not exist", ERROR_INDEX_STOP);
1492 
1493  if (!fObj.stopSearchd())
1494  throw Poco::Exception(fObj.getErrorMsg(), fObj.getErrorCode());
1495 
1496  _isError = false;
1497  }
1498  catch(Poco::Exception& e)
1499  {
1500  errorMsg = e.message();
1501  errorCode = e.code();
1502  }
1503  return !_isError;
1504 }
1505 //-----------------------------------------------------------------------------
1506 //-----------------------------------------------------------------------------
1508 :inherited(fObj)
1509 {
1510 }
1511 //-----------------------------------------------------------------------------
1512 bool IndexMerge::makeMerge(const std::string& branchName, const std::string& configPath, const std::string& trunkName, unsigned long long& maxDocId)
1513 {
1514  bool result = false;
1515  const std::string propertyFile = configPath+"/"+sphinx_search_const::branchPropertyFile;
1516  const std::string configFile = configPath+"/"+sphinx_search_const::branchConfigFile;
1517  const std::string propFile = configPath+"/"+sphinx_search_const::sphinxPropertyFile;
1518  try
1519  {
1520  Poco::AutoPtr<SphinxConfigCreator> pConfBranch = new SphinxConfigCreator(getPropertyFileName(configPath, branchName));
1521  maxDocId = pConfBranch->getUInt64(sphinx_admin_command_const::optionsMaxDocId, 0);
1522 
1523  Poco::AutoPtr<SphinxConfigCreator> pConf = new SphinxConfigCreator(propFile);
1525 
1526  std::vector<std::string> keys;
1527  pConf->keys(keys);
1528 
1529  const std::string sourceFile = configPath+"/"+sphinx_admin_command_const::dataDir+"/"+branchName+"."+sphinx_admin_command_const::sourceFileExtension;
1530 
1531  std::string trunkSectionName, branchSource;
1532  for (size_t i=0;i<keys.size();++i)
1533  {
1534  size_t found = keys[i].find(sphinx_search_const::sourceNameField);
1535  if (found!=std::string::npos)
1536  {
1537  branchSource = keys[i];
1538 
1539  std::string name = keys[i]+"."+sphinx_search_const::xmlpipeCommandNameField;
1540  std::stringstream str;
1541  str << "cat " << sourceFile;
1542  pConf->setString(name, str.str());
1543  }
1544  if (keys[i].find(sphinx_search_const::indexNameField)!=std::string::npos && keys[i].find(trunkName)!=std::string::npos)
1545  {
1546  trunkSectionName = keys[i];
1547  }
1548  }
1549  if (trunkSectionName.empty())
1550  throw Poco::Exception("Section name: '"+trunkSectionName+"' not valid");
1551 
1552  std::string branchSectionName = sphinx_search_const::indexNameField+" "+branchName;
1553  pConf->cloneSphinxConfigSection(trunkSectionName, branchSectionName);
1554 
1555  std::string branchSourceName = branchSource;
1556  std::string trunkSourceName = sphinx_search_const::sourceNameField+" "+trunkName;
1557  pConf->cloneSphinxConfigSection(branchSourceName, trunkSourceName);
1558 
1559  std::string name = trunkSectionName+"."+sphinx_search_const::sourceNameField;
1560  std::string value = trunkSourceName;
1561  pConf->setString(name, value);
1562 
1563  name = trunkSourceName+"."+sphinx_search_const::xmlpipeCommandNameField;
1564  value = "echo \"\"";
1565  pConf->setString(name, value);
1566 
1567  name = branchSectionName+"."+sphinx_search_const::pathNameField;
1568  value = configPath+"/"+sphinx_admin_command_const::indexDir+"/"+branchName;
1569  pConf->setString(name, value);
1570 
1571  name = trunkSectionName+"."+sphinx_search_const::pathNameField;
1572  value = configPath+"/"+sphinx_admin_command_const::indexDir+"/"+trunkName;
1573  pConf->setString(name, value);
1574 
1576  pConf->setString(sphinx_search_const::searchdLogName, value);
1577 
1578  value = fObj.getRunDir()+"/"+/*indexName+"/"+*/
1581  pConf->setString(sphinx_search_const::searchdPidName, value);
1582 
1584  pConf->setString(sphinx_search_const::searchdQueryLogName, value);
1585 
1586  pConf->save(propertyFile);
1587  pConf->setPropertyFileConfiguration(propertyFile);
1588 
1589  std::ofstream ofs(configFile.c_str(), std::fstream::trunc);
1590  ofs << *pConf;
1591  ofs.close();
1592 
1593  std::stringstream outMsg;
1594  const std::string cmd("indexer");
1595  std::vector<std::string> args = {"--merge", trunkName, branchName, "--config", configFile};
1596  ProcExec procExec(cmd, args);
1597  bool ret = procExec.exec(outMsg, outMsg);
1598 
1599  if (!(removeFile(configFile) && removeFile(propertyFile)))
1600  throw Poco::Exception(errorMsg);
1601 
1602  if (!ret)
1603  throw Poco::Exception("Merge '"+branchName+"' to '"+trunkName+"' fail");
1604 
1605  if (isExistError(outMsg.str()))
1606  throw Poco::Exception(outMsg.str());
1607 
1608  result = true;
1609  }
1610  catch(Poco::Exception& e)
1611  {
1612  errorMsg = e.message();
1614  fObj.log() << "ERROR_MAKE_MERGE " << errorMsg << std::endl;
1615  }
1616  catch(std::exception& e)
1617  {
1618  errorMsg = e.what();
1620  fObj.log() << "ERROR_MAKE_MERGE " << errorMsg << std::endl;
1621  }
1622 
1623  return result;
1624 }
1625 //-----------------------------------------------------------------------------
1626 bool IndexMerge::makeTrunk(const std::string& trunkName, const std::string& configPath,
1627  std::vector<std::string>& vIndexes, unsigned long long& maxDocId) throw (Poco::Exception)
1628 {
1629  if (vIndexes.empty())
1630  throw Poco::Exception("Empty list of existing indexes", ERROR_MAKE_TRUNK_INDEX);
1631 
1632  bool result = true;
1633  for (size_t i=0;i<vIndexes.size();++i)
1634  {
1635  if (vIndexes[i]==trunkName)
1636  {
1637  result = false;
1638  break;
1639  }
1640  }
1641 
1642  if (result)
1643  {
1644  const std::string propertyFile = configPath+"/"+sphinx_search_const::branchPropertyFile;
1645  const std::string configFile = configPath+"/"+sphinx_search_const::branchConfigFile;
1646  const std::string propFile = configPath+"/"+sphinx_search_const::sphinxPropertyFile;
1647 
1648  try
1649  {
1650  Poco::AutoPtr<SphinxConfigCreator> pConfBranch = new SphinxConfigCreator(getPropertyFileName(configPath, vIndexes.front()));
1651  maxDocId = pConfBranch->getUInt64(sphinx_admin_command_const::optionsMaxDocId, 0);
1652 
1653  Poco::AutoPtr<SphinxConfigCreator> pConf = new SphinxConfigCreator(propFile);
1655 
1656  std::vector<std::string> keys;
1657  pConf->keys(keys);
1658 
1659  for (size_t i=0;i<keys.size();++i)
1660  {
1661  if (keys[i].find(sphinx_search_const::sourceNameField)!=std::string::npos)
1662  {
1663  std::string name = keys[i]+"."+sphinx_search_const::xmlpipeCommandNameField;
1664  std::stringstream str;
1665  str << "cat " << configPath+"/"+sphinx_admin_command_const::dataDir << "/" << vIndexes.front() << "."
1667  pConf->setString(name, str.str());
1668  }
1669  if (keys[i].find(sphinx_search_const::indexNameField)!=std::string::npos && keys[i].find(trunkName)!=std::string::npos )
1670  {
1671  std::string name = keys[i]+"."+sphinx_search_const::pathNameField;
1672  std::stringstream str;
1673  str << configPath+"/"+sphinx_admin_command_const::indexDir << "/" << trunkName;
1674  pConf->setString(name, str.str());
1675  }
1676  }
1677  std::string value = fObj.getLogDir()+"/"+indexName+"/"+sphinx_search_const::searchdLogFile;
1678  pConf->setString(sphinx_search_const::searchdLogName, value);
1679 
1680  value = fObj.getRunDir()+"/"+/*indexName+"/"+*/
1683  pConf->setString(sphinx_search_const::searchdPidName, value);
1684 
1685  value = fObj.getLogDir()+"/"+indexName+"/"+sphinx_search_const::searchdQueryLogFile;
1686  pConf->setString(sphinx_search_const::searchdQueryLogName, value);
1687 
1688  pConf->save(propertyFile);
1689  pConf->setPropertyFileConfiguration(propertyFile);
1690 
1691  std::ofstream ofs(configFile.c_str(), std::fstream::trunc);
1692  ofs << *pConf;
1693  ofs.close();
1694 
1695  std::stringstream outMsg;
1696  const std::string cmd("indexer");
1697  std::vector<std::string> args = {"--quiet", trunkName, "--config", configFile};
1698  ProcExec procExec(cmd, args);
1699  bool ret = procExec.exec(outMsg, outMsg);
1700 
1701  if (!(removeFile(configFile) && removeFile(propertyFile)))
1702  throw Poco::Exception(errorMsg);
1703 
1704  if (!ret)
1705  throw Poco::Exception("Indexation '"+trunkName+"' fail");
1706 
1707  if (isExistError(outMsg.str()))
1708  throw Poco::Exception(outMsg.str());
1709 
1710  vIndexes.erase(vIndexes.begin());
1711  }
1712  catch(Poco::Exception& e)
1713  {
1714  fObj.log() << "ERROR_MAKE_TRUNK_INDEX " << e.message() << std::endl;
1715  throw Poco::Exception(e.message(), ERROR_MAKE_TRUNK_INDEX);
1716  }
1717  }
1718  return result;
1719 }
1720 //-----------------------------------------------------------------------------
1722 {
1723  errorMsg.clear();
1724  errorCode = NO_ERROR;
1725  _isError = true;
1726  fObj.log() << "IndexMerge::execute enter...." << std::endl;
1727  try
1728  {
1729  if (indexName.empty())
1730  throw Poco::Exception("Received empty index name", ERROR_COMMAND_INITIALIZATION);
1731 
1732  if (branches.empty())
1733  throw Poco::Exception("Received empty list of branches", ERROR_COMMAND_INITIALIZATION);
1734 
1735  std::string path = fObj.getDataDir()+"/"+indexName;
1736  if (!isExistDir(path))
1737  throw Poco::Exception("Index '"+path+"' not exist", ERROR_INDEX_MERGE);
1738 
1739  std::string indexDir = path+"/"+sphinx_admin_command_const::indexDir;
1740  if (!isExistDir(indexDir))
1741  throw Poco::Exception("Forder: '"+indexDir+"' not exists", ERROR_INDEX_MERGE);
1742 
1744  if (!fObject.isLoadedConfig())
1745  throw Poco::Exception(fObject.getErrorMsg(), ERROR_INDEX_MERGE);
1746 
1747  fObject.setLogStream(fObj.log());
1748  fObj.log() << "removeIndexFile fObject.getIndexFileName() = " << fObject.getIndexFileName() << std::endl;
1749 
1750  if (!removeIndexFile(fObject.getIndexFileName(), indexDir))
1751  throw Poco::Exception(errorMsg, errorCode);
1752 
1753  std::vector<std::string> vIndexes;
1754  if (getIndexList(indexDir, vIndexes))
1755  {
1756 // fObj.log() << "getIndexList vIndexes.size() = " << vIndexes.size() << std::endl;
1757 
1758  if (vIndexes.empty())
1759  throw Poco::Exception("Empty indexes list", ERROR_INDEX_MERGE);
1760 
1761  SphinxConfigOptions configOptions;
1762  unsigned long long maxDocId = 0;
1763  unsigned long long branchMaxDocId = 0;
1764 
1765  const std::string trunkFileName = *(vIndexes.begin());
1766  bool isMadeTrunk = makeTrunk(fObject.getIndexFileName(), path, vIndexes, maxDocId);
1767 
1768  // fObj.log() << "Trunk File Name = " << trunkFileName << std::endl;
1769  fObj.log() << "Prepare merge. Make " << fObj.getIndexFileName() << " => " << std::boolalpha << isMadeTrunk << std::endl;
1770  configOptions.addBranch(trunkFileName);
1771 
1772  unsigned int madeFailCount = 0;
1773  if (branches.front()=="*")
1774  {
1775  for (size_t i=0;i<vIndexes.size();++i)
1776  {
1777  if (!makeMerge(vIndexes[i], path, fObject.getIndexFileName(), branchMaxDocId))
1778  {
1779  if (!resultData.empty())
1780  resultData.append(",");
1781  resultData.append(vIndexes[i]);
1782  ++madeFailCount;
1783  }
1784  else
1785  {
1786  configOptions.addBranch(vIndexes[i]);
1787  if (maxDocId < branchMaxDocId)
1788  maxDocId = branchMaxDocId;
1789  }
1790  }
1791  }
1792  else
1793  {
1794  for (size_t k=0;k<branches.size();++k)
1795  for (size_t i=0;i<vIndexes.size();++i)
1796  if (vIndexes[i]==branches[k])
1797  {
1798  if (!makeMerge(vIndexes[i], path, fObject.getIndexFileName(), branchMaxDocId))
1799  {
1800  if (!resultData.empty())
1801  resultData.append(",");
1802  resultData.append(vIndexes[i]);
1803  ++madeFailCount;
1804  }
1805  else
1806  {
1807  configOptions.addBranch(vIndexes[i]);
1808  if (maxDocId < branchMaxDocId)
1809  maxDocId = branchMaxDocId;
1810  }
1811  break;
1812  }
1813  }
1814 
1815  bool isActive = fObject.isActiveSearchd(); // save state of daemon
1816  fObject.stopSearchd();
1817 
1818  fObj.log() << "IndexFileName = " << fObj.getIndexFileName() << std::endl;
1819  fObj.log() << "IS ACTIVE SEARCHD => " << std::boolalpha << isActive << std::endl;
1820 
1821  if (!moveIndexFiles(fObject.getIndexFileName(), indexDir, path))
1822  throw Poco::Exception("move file: "+errorMsg, ERROR_INDEX_MERGE);
1823 
1824  configOptions.setMaxDocId(maxDocId);
1825  configOptions.updateMargedDate();
1826 
1827  if (!makeTrunkConfig(fObject.getIndexFileName(), indexName, trunkFileName, configOptions))
1828  throw Poco::Exception("make config: "+errorMsg, ERROR_INDEX_MERGE);
1829 
1830  fObj.log() << "FO IndexName: " << fObj.getIndexName() << std::endl;
1831  fObj.log() << "Current IndexName: " << indexName << std::endl;
1832 
1833  if (isActive) // restore source state
1834  if (!fObject.startSearchd())
1835  throw Poco::Exception("Index Merge fail. ", ERROR_INDEX_MERGE);
1836 
1837  if (madeFailCount==0)
1838  _isError = false;
1839  }
1840  if (_isError)
1841  throw Poco::Exception(errorMsg, ERROR_INDEX_MERGE);
1842  }
1843  catch(Poco::Exception& e)
1844  {
1845  errorMsg = e.message();
1846  errorCode = e.code();
1847  _isError = true;
1848  }
1849  catch(std::exception& e)
1850  {
1851  errorMsg = e.what();
1853  _isError = true;
1854  }
1855  return !_isError;
1856 }
1857 //-----------------------------------------------------------------------------
1858 //-----------------------------------------------------------------------------
1860 :inherited(fObj)
1861 {
1862 }
1863 //-----------------------------------------------------------------------------
1865 {
1866  errorMsg.clear();
1867  errorCode = NO_ERROR;
1868  _isError = true;
1869  fObj.log() << "\n***********\nIndexMergeTrunk::execute enter...." << std::endl;
1870  try
1871  {
1872  if (indexName.empty())
1873  throw Poco::Exception("Received empty index name", ERROR_COMMAND_INITIALIZATION);
1874 
1875  if (branches.empty())
1876  throw Poco::Exception("Received empty list of branches", ERROR_COMMAND_INITIALIZATION);
1877 
1878  std::string path = fObj.getDataDir()+"/"+indexName;
1879  if (!isExistDir(path))
1880  throw Poco::Exception("Index '"+path+"' not exist", ERROR_INDEX_MERGE_TRUNK);
1881 
1882  std::string indexDir = path+"/"+sphinx_admin_command_const::indexDir;
1883  if (!isExistDir(indexDir))
1884  throw Poco::Exception("Forder: '"+indexDir+"' not exists", ERROR_INDEX_MERGE_TRUNK);
1885 
1887  if (!fObject.isLoadedConfig())
1888  throw Poco::Exception(fObject.getErrorMsg(),ERROR_INDEX_MERGE_TRUNK);
1889 
1890  fObject.setLogStream(fObj.log());
1891  fObj.log() << "fObject.getIndexFileName() = " << fObject.getIndexFileName() << std::endl;
1892 
1893  std::vector<std::string> vIndexes;
1894  if (!getIndexList(indexDir, vIndexes))
1895  throw Poco::Exception("Get index list: "+errorMsg, ERROR_INDEX_MERGE_TRUNK);
1896 
1897  if (vIndexes.empty())
1898  throw Poco::Exception("Empty indexes list", ERROR_INDEX_MERGE);
1899 
1900  const std::string trunkFileName = *(vIndexes.begin());
1901  // copy trunk index files to index dir
1902  if (!copyIndexFiles(fObject.getIndexFileName(), path, indexDir))
1903  throw Poco::Exception("move file: "+errorMsg, ERROR_INDEX_MERGE_TRUNK);
1904 
1905  SphinxConfigOptions configOptions;
1906  unsigned long long maxDocId = 0;
1907  unsigned long long branchMaxDocId = 0;
1908 
1909  unsigned int madeFailCount = 0;
1910  for (size_t k=0;k<branches.size();++k)
1911  for (size_t i=0;i<vIndexes.size();++i)
1912  if (vIndexes[i]==branches[k])
1913  {
1914  if (!makeMerge(vIndexes[i], path, fObject.getIndexFileName(), branchMaxDocId))
1915  {
1916  if (!resultData.empty())
1917  resultData.append(",");
1918  resultData.append(vIndexes[i]);
1919  ++madeFailCount;
1920  }
1921  else
1922  {
1923  configOptions.addBranch(vIndexes[i]);
1924  if (maxDocId < branchMaxDocId)
1925  maxDocId = branchMaxDocId;
1926  }
1927  break;
1928  }
1929 
1930  bool isActive = fObject.isActiveSearchd(); // save state of daemon
1931  fObject.stopSearchd();
1932 
1933  fObj.log() << "IndexFileName = " << fObj.getIndexFileName() << std::endl;
1934  fObj.log() << "IS ACTIVE SEARCHD => " << std::boolalpha << isActive << std::endl;
1935 
1936 
1937  if (!moveIndexFiles(fObject.getIndexFileName(), indexDir, path))
1938  throw Poco::Exception("move file: "+errorMsg, ERROR_INDEX_MERGE_TRUNK);
1939 
1940  if (!makeTrunkConfig(fObject.getIndexFileName(), indexName, trunkFileName, configOptions))
1941  throw Poco::Exception("make config: "+errorMsg, ERROR_INDEX_MERGE_TRUNK);
1942 
1943  fObj.log() << "FO IndexName: " << fObj.getIndexName() << std::endl;
1944  fObj.log() << "Current IndexName: " << indexName << std::endl;
1945 
1946  if (isActive) // restore source state
1947  if (!fObject.startSearchd())
1948  throw Poco::Exception("Index Merge fail. ", ERROR_INDEX_MERGE_TRUNK);
1949 
1950  if (madeFailCount==0)
1951  _isError = false;
1952  }
1953  catch(Poco::Exception& e)
1954  {
1955  errorMsg = e.message();
1956  errorCode = e.code();
1957  _isError = true;
1958  }
1959  catch(std::exception& e)
1960  {
1961  errorMsg = e.what();
1963  _isError = true;
1964  }
1965  return !_isError;
1966 }
1967 //-----------------------------------------------------------------------------
1968 //-----------------------------------------------------------------------------
1970 :inherited(fObj)
1971 {
1972 }
1973 //-----------------------------------------------------------------------------
1974 bool IndexDeleteDataFile::removeFilesList(const std::string& path, std::vector<std::string>& branches, std::vector<std::string>& files, const std::string& ext) throw (Poco::Exception)
1975 {
1976  bool result = false;
1977  unsigned int madeFailCount = 0;
1978  if (branches.front()=="*")
1979  {
1980  for (size_t i=0;i<files.size();++i)
1981  {
1982  std::string fileName = path+"/"+files[i]+"."+ext;
1983  if (!removeFile(fileName))
1984  {
1985  if (!resultData.empty())
1986  resultData.append(",");
1987  resultData.append(fileName);
1988  ++madeFailCount;
1989  }
1990  }
1991  }
1992  else
1993  {
1994  for (size_t k=0;k<branches.size();++k)
1995  for (size_t i=0;i<files.size();++i)
1996  if (files[i]==branches[k])
1997  {
1998  std::string fileName = path+"/"+files[i]+"."+ext;
1999  if (!removeFile(fileName))
2000  {
2001  if (!resultData.empty())
2002  resultData.append(",");
2003  resultData.append(fileName);
2004  ++madeFailCount;
2005  }
2006  }
2007  }
2008  if (madeFailCount==0)
2009  result = true;
2010 
2011  return result;
2012 }
2013 //-----------------------------------------------------------------------------
2014 bool IndexDeleteDataFile::removeIndexFiles(const std::string& path, std::vector<std::string>& branches, std::vector<std::string>& files) throw (Poco::Exception)
2015 {
2016  bool result = false;
2017  unsigned int madeFailCount = 0;
2018 
2019  if (branches.front()=="*")
2020  {
2021  for (size_t i=0;i<files.size();++i)
2022  {
2023  if (!removeIndexFile(files[i], path))
2024  {
2025  if (!resultData.empty())
2026  resultData.append(",");
2027  resultData.append(files[i]);
2028  ++madeFailCount;
2029  }
2030  }
2031  }
2032  else
2033  {
2034  for (size_t k=0;k<branches.size();++k)
2035  for (size_t i=0;i<files.size();++i)
2036  if (files[i]==branches[k])
2037  {
2038  if (!removeIndexFile(files[i], path))
2039  {
2040  if (!resultData.empty())
2041  resultData.append(",");
2042  resultData.append(files[i]);
2043  ++madeFailCount;
2044  }
2045  }
2046  }
2047  if (madeFailCount==0)
2048  result = true;
2049 
2050  return result;
2051 }
2052 //-----------------------------------------------------------------------------
2054 {
2055  errorMsg.clear();
2056  errorCode = NO_ERROR;
2057  _isError = true;
2058  try
2059  {
2060  if (branches.empty())
2061  throw Poco::Exception("Received empty list of branches", ERROR_COMMAND_INITIALIZATION);
2062 
2063  std::string path = fObj.getDataDir()+"/"+indexName;
2064  if (!isExistDir(path))
2065  throw Poco::Exception("Forder: '"+path+"' not exists", ERROR_INDEX_DELETE_DATA_FILE);
2066 
2067  std::string indexDir = path+"/"+sphinx_admin_command_const::indexDir;
2068  std::string dataDir = path+"/"+sphinx_admin_command_const::dataDir;
2069  if (!isExistDir(indexDir))
2070  throw Poco::Exception("Forder: '"+indexDir+"' not exists", ERROR_INDEX_DELETE_DATA_FILE);
2071 
2072  if (!isExistDir(dataDir))
2073  throw Poco::Exception("Forder: '"+dataDir+"' not exists", ERROR_INDEX_DELETE_DATA_FILE);
2074 
2075  std::vector<std::string> dataFiles, sourceFiles, configFiles, propertyFiles, indexes;
2080  getIndexList(indexDir, indexes))
2081  {
2082  if (dataFiles.size()==0 && sourceFiles.size()==0 && indexes.size()==0 && configFiles.size()==0 && propertyFiles.size()==0)
2083  {
2084  throw Poco::Exception("Data files already deleted", ERROR_INDEX_DELETE_DATA_FILE);
2085  }
2086  else
2087  {
2088  _isError = !(removeFilesList(dataDir, branches, dataFiles, sphinx_admin_command_const::dataFileExtension) &&
2089  removeFilesList(dataDir, branches, sourceFiles, sphinx_admin_command_const::sourceFileExtension) &&
2090  removeFilesList(dataDir, branches, configFiles, sphinx_admin_command_const::branchConfigFileExtention) &&
2091  removeFilesList(dataDir, branches, propertyFiles, sphinx_admin_command_const::branchPropertyFileExtention) &&
2092  removeIndexFiles(indexDir, branches, indexes));
2093  }
2094  }
2095  if (_isError)
2096  throw Poco::Exception(errorMsg, ERROR_INDEX_DELETE_DATA_FILE);
2097  }
2098  catch(Poco::Exception& e)
2099  {
2100  errorMsg = e.message();
2101  errorCode = e.code();
2102  }
2103  return !_isError;
2104 }
2105 //-----------------------------------------------------------------------------
2106 //-----------------------------------------------------------------------------
2108 :inherited(fObj)
2109 {
2110 }
2111 //-----------------------------------------------------------------------------
2113 {
2114  errorMsg.clear();
2115  errorCode = NO_ERROR;
2116  _isError = true;
2117  try
2118  {
2119  std::string fileName = fObj.getDataDir()+"/"+indexName+"/"+sphinx_search_const::sphinxSchemaFile;
2120 
2121  if (!removeFile(fileName))
2122  throw Poco::Exception(errorMsg, ERROR_INDEX_DELETE_SCHEMA_FILE);
2123 
2124  if (isExistFile(fileName))
2125  throw Poco::Exception("Remove '"+fileName+"' fail", ERROR_INDEX_DELETE_SCHEMA_FILE);
2126 
2127  _isError = false;
2128  }
2129  catch(Poco::Exception& e)
2130  {
2131  errorMsg = e.message();
2132  errorCode = e.code();
2133  }
2134  return !_isError;
2135 }
2136 //-----------------------------------------------------------------------------
2137 //-----------------------------------------------------------------------------
2139 :inherited(fObj)
2140 {
2141 }
2142 //-----------------------------------------------------------------------------
2144 {
2145  errorMsg.clear();
2146  errorCode = NO_ERROR;
2147  _isError = true;
2148  try
2149  {
2150  std::string path = fObj.getDataDir()+"/"+indexName;
2151  if (!isExistDir(path))
2152  throw Poco::Exception("Forder: '"+path+"' not exists", ERROR_INDEX_APPEND_DATA_FILE);
2153 
2154  std::string dataDir = path+"/"+sphinx_admin_command_const::dataDir;
2155  if (!isExistDir(dataDir))
2156  throw Poco::Exception("Forder: '"+dataDir+"' not exists", ERROR_INDEX_DELETE_DATA_FILE);
2157 
2158  const std::string dataFileName = dataDir+"/"+branchName+"."+sphinx_admin_command_const::dataFileExtension;
2159  std::stringstream oldContent;
2160  SphinxDataFile dataFile;
2161  std::ifstream ifs(dataFileName.c_str(), std::fstream::binary);
2162  if (ifs.is_open())
2163  {
2164  oldContent << ifs.rdbuf();
2165  _isError = !dataFile.append(oldContent);
2166  ifs.close();
2167  if (_isError)
2168  throw Poco::Exception(dataFile.getErrorMsg(), ERROR_INDEX_APPEND_DATA_FILE);
2169  }
2170 
2171  std::stringstream strAppendContent(HCE::decodeBase64(dataContent));
2172  if (!dataFile.append(strAppendContent))
2173  throw Poco::Exception(dataFile.getErrorMsg(), ERROR_INDEX_APPEND_DATA_FILE);
2174 
2175  std::fstream fst(dataFileName.c_str(), std::fstream::out|std::fstream::trunc|std::fstream::binary);
2176  fst << dataFile;
2177  fst.flush();
2178  fst.close();
2179 
2180  _isError = false;
2181  }
2182  catch(Poco::Exception& e)
2183  {
2184  errorMsg = e.message();
2185  errorCode = e.code();
2186  }
2187  return !_isError;
2188 }
2189 //-----------------------------------------------------------------------------
2191 :inherited(fObj), ids()
2192 {
2193 }
2194 //-----------------------------------------------------------------------------
2195 void IndexDeleteDoc::addId(unsigned long long id)
2196 {
2197  ids.push_back(id);
2198 }
2199 //-----------------------------------------------------------------------------
2200 bool IndexDeleteDoc::serialize(std::string& json)
2201 {
2202  _isError = true;
2203  errorMsg.clear();
2204  try
2205  {
2206  Poco::JSON::Object::Ptr obj = new Poco::JSON::Object();
2208 
2209  Poco::JSON::Array::Ptr array = new Poco::JSON::Array();
2210  for (size_t i=0;i<ids.size();++i)
2211  array->add(std::to_string(ids[i]));
2212  obj->set(sphinx_admin_command_const::documents, array);
2213 
2214  std::stringstream ostr;
2215  Poco::JSON::Stringifier::stringify(obj, ostr);
2216  json = ostr.str();
2217 
2218  _isError = false;
2219  }
2220  catch(std::exception& e)
2221  {
2222  errorMsg = e.what();
2224  }
2225  return !_isError;
2226 }
2227 //-----------------------------------------------------------------------------
2228 bool IndexDeleteDoc::unserialize(const std::string& json)
2229 {
2230  indexName.clear();
2231  ids.clear();
2232  errorMsg.clear();
2233  _isError = true;
2234  try
2235  {
2236  Poco::JSON::Parser parser;
2237  Poco::Dynamic::Var res = parser.parse(json);
2238  Poco::JSON::Object::Ptr obj = res.extract<Poco::JSON::Object::Ptr>();
2239 
2240  Poco::Dynamic::Var tmp = obj->get(sphinx_admin_command_const::indexName);
2241  if (tmp.isString())
2242  indexName = tmp.convert<std::string>();
2243 
2244  Poco::JSON::Array::Ptr vecDocs = obj->getArray(sphinx_admin_command_const::documents);
2245  if (!vecDocs.isNull())
2246  {
2247  for (size_t k = 0;k<vecDocs->size();++k)
2248  {
2249  Poco::Dynamic::Var tmp = vecDocs->get(k);
2250  if (tmp.isString())
2251  {
2252  try
2253  {
2254  unsigned long long id = std::stoull(tmp.convert<std::string>());
2255  ids.push_back(id);
2256  }
2257  catch(std::exception& e)
2258  {
2259  fObj.log() << "Get bad doc ID: " << e.what() << std::endl;
2260  }
2261  }
2262  if (tmp.isNumeric())
2263  {
2264  unsigned long long id = tmp.convert<Poco::Int64>();
2265  ids.push_back(id);
2266  }
2267  }
2268  }
2269  _isError = false;
2270  }
2271  catch(Poco::JSON::JSONException& e)
2272  {
2273  errorMsg = e.displayText();
2275  }
2276  return !_isError;
2277 }
2278 //-----------------------------------------------------------------------------
2280 {
2281  errorMsg.clear();
2282  errorCode = NO_ERROR;
2283  _isError = true;
2284  try
2285  {
2286  std::string path = fObj.getDataDir()+"/"+indexName;
2287  if (!isExistDir(path))
2288  throw Poco::Exception("Forder: '"+path+"' not exists", ERROR_INDEX_DELETE_DOC);
2289 
2290  if (ids.size()==0)
2291  throw Poco::Exception("Empty append document list", ERROR_INDEX_DELETE_DOC);
2292 
2293  std::string fileName = path+"/"+sphinx_admin_command_const::deletedFileName;
2294  if (isExistFile(fileName))
2295  {
2296  std::fstream fst(fileName.c_str(), std::fstream::out|std::fstream::app);
2297  if (!fst.is_open())
2298  throw Poco::Exception("file '"+fileName+"' not opened", ERROR_INDEX_DELETE_DOC);
2299 
2300  for (size_t i=0;i<ids.size();++i)
2301  fst << (unsigned long long)(ids[i]) << std::endl;
2302  fst.close();
2303  }
2304  else
2305  {
2306  std::ofstream ofs(fileName.c_str(), std::fstream::trunc);
2307  for (size_t i=0;i<ids.size();++i)
2308  ofs << ids[i] << std::endl;
2309  ofs.close();
2310  }
2311  _isError = false;
2312  }
2313  catch(Poco::Exception& e)
2314  {
2315  errorMsg = e.message();
2316  errorCode = e.code();
2317  }
2318  return !_isError;
2319 }
2320 //-----------------------------------------------------------------------------
2321 //-----------------------------------------------------------------------------
2323 :inherited(fObj)
2324 {
2325 }
2326 //-----------------------------------------------------------------------------
2328 {
2329  errorMsg.clear();
2330  errorCode = NO_ERROR;
2331  _isError = true;
2332  try
2333  {
2334  std::string path = fObj.getDataDir()+"/"+indexName;
2335  if (!isExistDir(path))
2336  throw Poco::Exception("Forder: '"+path+"' not exists", ERROR_INDEX_DELETE_DOC_NUMBER);
2337 
2338  std::string fileName = path+"/"+sphinx_admin_command_const::deletedFileName;
2339  size_t count = 0;
2340  if (isExistFile(fileName))
2341  {
2342  std::ifstream ifs(fileName.c_str());
2343  if (!ifs.is_open())
2344  throw Poco::Exception("file '"+fileName+"' not opened", ERROR_INDEX_DELETE_DOC_NUMBER);
2345 
2346  std::string line;
2347  while(getline(ifs, line))
2348  {
2349  ++count;
2350  }
2351  ifs.close();
2352  }
2353  resultData = std::to_string(count);
2354  _isError = false;
2355  }
2356  catch(Poco::Exception& e)
2357  {
2358  errorMsg = e.message();
2359  errorCode = e.code();
2360  }
2361  catch(std::exception& e)
2362  {
2363  errorMsg = e.what();
2365  }
2366  return !_isError;
2367 }
2368 //-----------------------------------------------------------------------------
2369 //-----------------------------------------------------------------------------
2371 :inherited(fObj)
2372 {
2373 }
2374 //-----------------------------------------------------------------------------
2375 bool IndexPackDocData::packData(const std::string& file, std::set<std::string>& delList)
2376 {
2377  bool result = false;
2381  std::string xmlString;
2382  std::string outString;
2383  try
2384  {
2385  std::ifstream in(file.c_str());
2386  if (!in.is_open())
2387  throw Poco::Exception("File "+file+" not opened");
2388 
2389  in.seekg(0, std::ios::end);
2390  xmlString.resize(in.tellg());
2391  in.seekg(0, std::ios::beg);
2392  in.read(&xmlString[0], xmlString.size());
2393  in.close();
2394 
2395  outString = xmlCleaner.process(xmlString, delList);
2396 
2397  std::ofstream ofs(file.c_str(), std::fstream::trunc);
2398  ofs << outString;
2399  ofs.close();
2400 
2401  result = true;
2402  }
2403  catch(Poco::Exception& e)
2404  {
2405  errorMsg = "packData: "+e.displayText();
2406  }
2407  return result;
2408 }
2409 //-----------------------------------------------------------------------------
2410 bool IndexPackDocData::getDocumentCount(const std::string& file, size_t& documentCount)
2411 {
2412  bool result = false;
2413  try
2414  {
2415  std::ifstream ifs(file.c_str());
2416  if (!ifs.is_open())
2417  throw Poco::Exception("File '"+file+"' not opened");
2418 
2419  SphinxDataFile dataFile;
2420  size_t count = dataFile.documentCount(ifs);
2421  ifs.close();
2422 
2423  if (dataFile.isError())
2424  throw Poco::Exception(dataFile.getErrorMsg());
2425 
2426  result = true;
2427  documentCount += count;
2428  }
2429  catch(Poco::Exception& e)
2430  {
2431  errorMsg = "getDocumentCount: "+e.message();
2432  }
2433  return result;
2434 }
2435 //-----------------------------------------------------------------------------
2437 {
2438  errorMsg.clear();
2439  errorCode = NO_ERROR;
2440  _isError = true;
2441 
2442  try
2443  {
2444  resultData = "0";
2445 
2446  std::string path = fObj.getDataDir()+"/"+indexName;
2447  if (!isExistDir(path))
2448  throw Poco::Exception("Forder: '"+path+"' not exists", ERROR_INDEX_PACK_DOC_DATA);
2449 
2450  std::string dataDir = path+"/"+sphinx_admin_command_const::dataDir;
2451  if (!isExistDir(dataDir))
2452  throw Poco::Exception("Forder: '"+dataDir+"' not exists", ERROR_INDEX_PACK_DOC_DATA);
2453 
2454  if (branches.empty())
2455  throw Poco::Exception("Empty branches list", ERROR_INDEX_PACK_DOC_DATA);
2456 
2457  const std::string backupFile = path+"/"+sphinx_admin_command_const::deletedFileName+".backup";
2458  const std::string fileName = path+"/"+sphinx_admin_command_const::deletedFileName;
2459  std::set<std::string> delList;
2460 
2461  if (isExistFile(fileName))
2462  {
2463  std::ifstream ifs(fileName.c_str());
2464  if (!ifs.is_open())
2465  throw Poco::Exception("file '"+fileName+"' not opened", ERROR_INDEX_PACK_DOC_DATA);
2466 
2467  std::string line;
2468  while(getline(ifs, line))
2469  {
2470  try
2471  {
2472  std::stoull(line);
2473  delList.insert(line);
2474  }
2475  catch(std::exception& e)
2476  {
2477  fObj.log() << "Bad document ID: " << e.what() << std::endl;
2478  }
2479  }
2480  ifs.close();
2481 
2482  if (!moveFile(fileName, backupFile))
2483  throw Poco::Exception(errorMsg, ERROR_INDEX_PACK_DOC_DATA);
2484  }
2485 
2486  std::vector<std::string> vFiles;
2488  throw Poco::Exception(errorMsg, errorCode);
2489 
2490  size_t documentCount = 0;
2491 
2492  if (vFiles.size()==0)
2493  {
2494  throw Poco::Exception("Empty list of files data", ERROR_INDEX_PACK_DOC_DATA);
2495  }
2496  else if (branches.front()=="*")
2497  {
2498  for (size_t i=0;i<vFiles.size();++i)
2499  {
2500  if (!packData(dataDir+"/"+vFiles[i]+"."+sphinx_admin_command_const::dataFileExtension, delList))
2501  throw Poco::Exception(errorMsg, ERROR_INDEX_PACK_DOC_DATA);
2502 
2503  if (!getDocumentCount(dataDir+"/"+vFiles[i]+"."+sphinx_admin_command_const::dataFileExtension, documentCount))
2504  throw Poco::Exception(errorMsg, ERROR_INDEX_PACK_DOC_DATA);
2505  }
2506  }
2507  else
2508  {
2509  for (size_t k=0;k<branches.size();++k)
2510  for (size_t i=0;i<vFiles.size();++i)
2511  if (vFiles[i]==branches[k])
2512  {
2513  if (!packData(dataDir+"/"+vFiles[i]+"."+sphinx_admin_command_const::dataFileExtension, delList))
2514  throw Poco::Exception(errorMsg, ERROR_INDEX_PACK_DOC_DATA);
2515 
2516  if (!getDocumentCount(dataDir+"/"+vFiles[i]+"."+sphinx_admin_command_const::dataFileExtension, documentCount))
2517  throw Poco::Exception(errorMsg, ERROR_INDEX_PACK_DOC_DATA);
2518  }
2519  }
2520  if (isExistFile(backupFile))
2521  if (!removeFile(backupFile))
2522  throw Poco::Exception(errorMsg, ERROR_INDEX_PACK_DOC_DATA);
2523 
2524  resultData = std::to_string(documentCount);
2525  _isError = false;
2526  }
2527  catch(Poco::Exception& e)
2528  {
2529  errorMsg = e.message();
2530  errorCode = e.code();
2531  }
2532  catch(std::exception& e)
2533  {
2534  errorMsg = e.what();
2536  }
2537  return !_isError;
2538 }
2539 //-----------------------------------------------------------------------------
2540 //-----------------------------------------------------------------------------
2542 :inherited(fObj)
2543 {
2544 }
2545 //-----------------------------------------------------------------------------
2547 {
2548  errorMsg.clear();
2549  errorCode = NO_ERROR;
2550  _isError = true;
2551  try
2552  {
2553  std::string path = fObj.getDataDir()+"/"+indexName;
2554 
2555  if (!isExistDir(path))
2556  throw Poco::Exception("Index '"+path+"' not exists", ERROR_INDEX_REMOVE);
2557 
2558  SphinxFunctionalObject fObject("", 0, fObj.getHomeDir(), indexName);
2559  IndexStop indexStop(fObject);
2560  indexStop.setIndexName(indexName);
2561  if (!indexStop.execute())
2562  throw Poco::Exception(indexStop.getErrorMsg(), ERROR_INDEX_REMOVE);
2563 
2564  std::string cmd("rm");
2565  std::vector<std::string> args = {"-R", path};
2566 
2567  std::stringstream outMsg;
2568  ProcExec procExec(cmd, args);
2569  if (!procExec.exec(outMsg, outMsg))
2570  throw Poco::Exception("Remove '"+path+"' fail", ERROR_INDEX_REMOVE);
2571 
2572  if (isExistError(outMsg.str()))
2573  throw Poco::Exception(outMsg.str(), ERROR_INDEX_REMOVE);
2574 
2575  path = fObj.getLogDir()+"/"+indexName;
2576  if (isExistDir(path))
2577  {
2578  args.clear();
2579  args.push_back("-R");
2580  args.push_back(path);
2581  ProcExec procExecLog(cmd, args);
2582  procExecLog.exec();
2583  }
2584  _isError = false;
2585  }
2586  catch(Poco::Exception& e)
2587  {
2588  errorMsg = e.message();
2589  errorCode = e.code();
2590  }
2591  return !_isError;
2592 }
2593 //-----------------------------------------------------------------------------
2594 //-----------------------------------------------------------------------------
2596 :inherited(fObj), indexFromName(""), indexToName("")
2597 {
2598 }
2599 //-----------------------------------------------------------------------------
2600 bool IndexCopy::serialize(std::string& json)
2601 {
2602  _isError = true;
2603  errorMsg.clear();
2604  try
2605  {
2606  Poco::JSON::Object::Ptr obj = new Poco::JSON::Object();
2609 
2610  std::stringstream ostr;
2611  Poco::JSON::Stringifier::stringify(obj, ostr);
2612  json = ostr.str();
2613 
2614  _isError = false;
2615  }
2616  catch(std::exception& e)
2617  {
2618  errorMsg = e.what();
2620  }
2621  return !_isError;
2622 }
2623 //-----------------------------------------------------------------------------
2624 bool IndexCopy::unserialize(const std::string& json)
2625 {
2626  indexFromName.clear();
2627  indexToName.clear();
2628  errorMsg.clear();
2629  _isError = true;
2630  try
2631  {
2632  Poco::JSON::Parser parser;
2633  Poco::Dynamic::Var res = parser.parse(json);
2634  Poco::JSON::Object::Ptr obj = res.extract<Poco::JSON::Object::Ptr>();
2635 
2636  Poco::Dynamic::Var tmp = obj->get(sphinx_admin_command_const::indexFromName);
2637  if (tmp.isString())
2638  indexFromName = tmp.convert<std::string>();
2639 
2641  if (tmp.isString())
2642  indexToName = tmp.convert<std::string>();
2643 
2644  _isError = false;
2645  }
2646  catch(Poco::JSON::JSONException& e)
2647  {
2648  errorMsg = e.displayText();
2650  }
2651  return !_isError;
2652 }
2653 //-----------------------------------------------------------------------------
2655 {
2656  errorMsg.clear();
2657  errorCode = NO_ERROR;
2658  _isError = true;
2659  try
2660  {
2661  const std::string srcIndex = fObj.getDataDir()+"/"+indexFromName;
2662  const std::string dstIndex = fObj.getDataDir()+"/"+indexToName;
2663 
2664  if (isExistDir(dstIndex))
2665  throw Poco::Exception(indexToName+" already exists", ERROR_INDEX_COPY);
2666 
2667  std::string logDir = fObj.getLogDir()+"/"+indexToName;
2668  if (!isExistDir(logDir))
2669  if (!makeDir(logDir))
2670  throw Poco::Exception("Don't created log dir: '"+logDir+"'", ERROR_INDEX_COPY);
2671 
2672  const std::string cmd("cp");
2673  std::vector<std::string> args = {"-R", srcIndex, dstIndex};
2674  ProcExec procExec(cmd, args);
2675  if (!procExec.exec())
2676  throw Poco::Exception("Copy '"+srcIndex+"' to '"+dstIndex+"' fail", ERROR_INDEX_COPY);
2677 
2678  const std::string propFile = dstIndex+"/"+sphinx_search_const::sphinxPropertyFile;
2679  const std::string sphinxConfigFile = dstIndex+"/"+sphinx_search_const::sphinxConfigName;
2680 
2681  Poco::AutoPtr<SphinxConfigCreator> pConf = new SphinxConfigCreator(propFile);
2682  std::vector<std::string> keys;
2683  pConf->keys(keys);
2684 
2685  for (size_t i=0;i<keys.size();++i)
2686  {
2687  if (keys[i].find(sphinx_search_const::sourceNameField)!=std::string::npos)
2688  {
2689  std::string name = keys[i]+"."+sphinx_search_const::xmlpipeCommandNameField;
2690  std::string value = pConf->getString(name);
2691 
2692  size_t pos = value.find(indexFromName);
2693  if (pos!=std::string::npos)
2694  value = value.replace(pos, indexFromName.length(), indexToName);
2695 
2696  pConf->setString(name, value);
2697  }
2698 
2699  if (keys[i].find(sphinx_search_const::indexNameField)!=std::string::npos)
2700  {
2701  std::string name = keys[i]+"."+sphinx_search_const::pathNameField;
2702  std::string value = pConf->getString(name);
2703 
2704  size_t pos = value.find(indexFromName);
2705  if (pos!=std::string::npos)
2706  value = value.replace(pos, indexFromName.length(), indexToName);
2707 
2708  pConf->setString(name, value);
2709  }
2710  }
2711  std::string value = fObj.getLogDir()+"/"+indexToName+"/"+sphinx_search_const::searchdLogFile;
2712  pConf->setString(sphinx_search_const::searchdLogName, value);
2713 
2714  value = fObj.getRunDir()+"/"+/*indexToName+"/"+*/
2717  pConf->setString(sphinx_search_const::searchdPidName, value);
2718 
2720  pConf->setString(sphinx_search_const::searchdQueryLogName, value);
2721 
2722  unsigned int port = 0;
2723  if (!getFreeAllowedPort(port))
2724  throw Poco::Exception(errorMsg, ERROR_INDEX_COPY);
2725 
2726  value = fObj.getServerHost()+":"+std::to_string(port);
2727  pConf->setString(sphinx_search_const::searchdListen, value);
2728 
2729  pConf->save(propFile);
2730  pConf->setPropertyFileConfiguration(propFile);
2731  pConf->deleteSphinxConfigSection(sphinx_admin_command_const::sectionOptions);
2732 
2733  std::ofstream ofs(sphinxConfigFile.c_str(), std::fstream::trunc);
2734  ofs << *pConf;
2735  ofs.close();
2736 
2737  _isError = false;
2738  }
2739  catch(Poco::Exception& e)
2740  {
2741  errorMsg = e.message();
2742  errorCode = e.code();
2743  }
2744  catch(std::exception& e)
2745  {
2746  errorMsg = e.what();
2748  }
2749  return !_isError;
2750 }
2751 //-----------------------------------------------------------------------------
2752 //-----------------------------------------------------------------------------
2754 :inherited(fObj)
2755 {
2756 }
2757 //-----------------------------------------------------------------------------
2759 {
2760  errorMsg.clear();
2761  errorCode = NO_ERROR;
2762  _isError = true;
2763  try
2764  {
2765  if (!inherited::execute())
2766  throw Poco::Exception(inherited::getErrorMsg(), ERROR_INDEX_RENAME);
2767 
2768  bool isActive = (fObj.getIndexName()==indexFromName);
2769 
2770  IndexRemove indexRemove(fObj);
2771  indexRemove.setIndexName(indexFromName);
2772  if (!indexRemove.execute())
2773  throw Poco::Exception(indexRemove.getErrorMsg(), ERROR_INDEX_RENAME);
2774 
2775  if (isActive)
2777 
2778  _isError = false;
2779  }
2780  catch(Poco::Exception& e)
2781  {
2782  errorMsg = e.message();
2783  errorCode = e.code();
2784  }
2785  return !_isError;
2786 }
2787 //-----------------------------------------------------------------------------
2788 //-----------------------------------------------------------------------------
2790 :inherited(fObj), indexName(""), branchName(""), sectionName(""), parameterName(""), parameterValue("")
2791 {
2792 }
2793 //-----------------------------------------------------------------------------
2794 bool IndexSetConfigVar::serialize(std::string& json)
2795 {
2796  _isError = true;
2797  errorMsg.clear();
2798  try
2799  {
2800  Poco::JSON::Object::Ptr obj = new Poco::JSON::Object();
2806 
2807  std::stringstream ostr;
2808  Poco::JSON::Stringifier::stringify(obj, ostr);
2809  json = ostr.str();
2810 
2811  _isError = false;
2812  }
2813  catch(std::exception& e)
2814  {
2815  errorMsg = e.what();
2817  }
2818  return !_isError;
2819 }
2820 //-----------------------------------------------------------------------------
2821 bool IndexSetConfigVar::unserialize(const std::string& json)
2822 {
2823  indexName.clear();
2824  sectionName.clear();
2825  parameterName.clear();
2826  parameterValue.clear();
2827  errorMsg.clear();
2828  _isError = true;
2829  try
2830  {
2831  Poco::JSON::Parser parser;
2832  Poco::Dynamic::Var res = parser.parse(json);
2833  Poco::JSON::Object::Ptr obj = res.extract<Poco::JSON::Object::Ptr>();
2834 
2835  Poco::Dynamic::Var tmp = obj->get(sphinx_admin_command_const::indexName);
2836  if (tmp.isString())
2837  indexName = tmp.convert<std::string>();
2838 
2840  if (tmp.isString())
2841  branchName = tmp.convert<std::string>();
2842 
2844  if (tmp.isString())
2845  sectionName = tmp.convert<std::string>();
2846 
2848  if (tmp.isString())
2849  parameterName = tmp.convert<std::string>();
2850 
2852  if (tmp.isString())
2853  parameterValue = tmp.convert<std::string>();
2854 
2855  _isError = false;
2856  }
2857  catch(Poco::JSON::JSONException& e)
2858  {
2859  errorMsg = e.displayText();
2861  }
2862  return !_isError;
2863 }
2864 //-----------------------------------------------------------------------------
2866 {
2867  errorMsg.clear();
2868  errorCode = NO_ERROR;
2869  _isError = true;
2870  try
2871  {
2872  std::string path = fObj.getDataDir()+"/"+indexName;
2873  if (!isExistDir(path))
2874  throw Poco::Exception("Forder: '"+path+"' not exists");
2875 
2876  const std::string configFile = (branchName.empty())?(path+"/"+sphinx_search_const::sphinxConfigName):(getConfigFileName(path, branchName));
2877  const std::string propFile = (branchName.empty())?(path+"/"+sphinx_search_const::sphinxPropertyFile):(getPropertyFileName(path, branchName));
2878 
2879  Poco::AutoPtr<SphinxConfigCreator> pConf = new SphinxConfigCreator(propFile);
2880 
2881  const std::string name = sectionName+"."+parameterName;
2882  pConf->setString(name, parameterValue);
2883  pConf->save(propFile);
2884  pConf->setPropertyFileConfiguration(propFile);
2885  pConf->deleteSphinxConfigSection(sphinx_admin_command_const::sectionOptions);
2886 
2887  std::ofstream ofs(configFile.c_str(), std::fstream::trunc);
2888  ofs << *pConf;
2889  ofs.close();
2890 
2891  _isError = false;
2892  }
2893  catch(Poco::Exception& e)
2894  {
2895  errorMsg = e.message();
2897  }
2898  return !_isError;
2899 }
2900 //-----------------------------------------------------------------------------
2901 //-----------------------------------------------------------------------------
2903 :inherited(fObj)
2904 {
2905 }
2906 //-----------------------------------------------------------------------------
2907 bool IndexGetConfigVar::serialize(std::string& json)
2908 {
2909  _isError = true;
2910  errorMsg.clear();
2911  try
2912  {
2913  Poco::JSON::Object::Ptr obj = new Poco::JSON::Object();
2917 
2918  std::stringstream ostr;
2919  Poco::JSON::Stringifier::stringify(obj, ostr);
2920  json = ostr.str();
2921 
2922  _isError = false;
2923  }
2924  catch(std::exception& e)
2925  {
2926  errorMsg = e.what();
2928  }
2929  return !_isError;
2930 }
2931 //-----------------------------------------------------------------------------
2932 bool IndexGetConfigVar::unserialize(const std::string& json)
2933 {
2934  indexName.clear();
2935  sectionName.clear();
2936  parameterName.clear();
2937  errorMsg.clear();
2938  _isError = true;
2939  try
2940  {
2941  Poco::JSON::Parser parser;
2942  Poco::Dynamic::Var res = parser.parse(json);
2943  Poco::JSON::Object::Ptr obj = res.extract<Poco::JSON::Object::Ptr>();
2944 
2945  Poco::Dynamic::Var tmp = obj->get(sphinx_admin_command_const::indexName);
2946  if (tmp.isString())
2947  indexName = tmp.convert<std::string>();
2948 
2950  if (tmp.isString())
2951  sectionName = tmp.convert<std::string>();
2952 
2954  if (tmp.isString())
2955  parameterName = tmp.convert<std::string>();
2956 
2957  _isError = false;
2958  }
2959  catch(Poco::JSON::JSONException& e)
2960  {
2961  errorMsg = e.displayText();
2963  }
2964  return !_isError;
2965 }
2966 //-----------------------------------------------------------------------------
2968 {
2969  errorMsg.clear();
2970  errorCode = NO_ERROR;
2971  _isError = true;
2972  try
2973  {
2974  std::string path = fObj.getDataDir()+"/"+indexName;
2975  if (!isExistDir(path))
2976  throw Poco::Exception("Forder: '"+path+"' not exists");
2977 
2978  const std::string propFile = (branchName.empty())?(path+"/"+sphinx_search_const::sphinxPropertyFile):(getPropertyFileName(path, branchName));
2979 
2980  Poco::AutoPtr<SphinxConfigCreator> pConf = new SphinxConfigCreator(propFile);
2981 
2982  const std::string name = sectionName+"."+parameterName;
2983  resultData = pConf->getString(name);
2984 
2985  _isError = false;
2986  }
2987  catch(Poco::Exception& e)
2988  {
2989  errorMsg = e.message();
2991  }
2992  return !_isError;
2993 }
2994 //-----------------------------------------------------------------------------
2995 //-----------------------------------------------------------------------------
2997 :inherited(fObj)
2998 {
2999 }
3000 //-----------------------------------------------------------------------------
3002 {
3003  errorMsg.clear();
3004  errorCode = NO_ERROR;
3005  _isError = true;
3006  try
3007  {
3008  std::string path = fObj.getDataDir()+"/"+indexName;
3009  if (!isExistDir(path))
3010  throw Poco::Exception("Forder: '"+path+"' not exists", ERROR_INDEX_CHECK_SCHEMA);
3011 
3012  path.append("/").append(sphinx_search_const::sphinxSchemaFile);
3013  std::ifstream ifs(path.c_str(), std::fstream::binary);
3014  if (!ifs.is_open())
3015  throw Poco::Exception("File '"+path+"' not found" , ERROR_INDEX_CHECK_SCHEMA);
3016 
3017  SphinxSchemaFile oldSchemaFile(ifs);
3018  std::vector<std::pair<std::string, int> > oldSchemaVec;
3019  bool ret = oldSchemaFile.getFields(oldSchemaVec); // need for read all attributes
3020  ifs.close();
3021  if (!ret)
3022  throw Poco::Exception(oldSchemaFile.getErrorMsg(), ERROR_INDEX_CHECK_SCHEMA);
3023 
3024  std::stringstream str;
3026 
3027  std::vector<std::pair<std::string, int> > checkSchemaVec;
3028  SphinxSchemaFile checkSchemaFile(str);
3029  if (!checkSchemaFile.getFields(checkSchemaVec)) // need for read all attributes
3030  throw Poco::Exception(checkSchemaFile.getErrorMsg(), ERROR_INDEX_CHECK_SCHEMA);
3031 
3032  for (size_t i=0;i<checkSchemaVec.size();++i)
3033  {
3034  bool isFound = false;
3035  for (size_t k=0;k<oldSchemaVec.size();++k)
3036  {
3037  if (checkSchemaVec[i].first==oldSchemaVec[k].first)
3038  {
3039  isFound = true;
3040  break;
3041  }
3042  }
3043  if (!isFound)
3044  throw Poco::Exception("Invalid schema. Field '"+checkSchemaVec[i].first+"' not found", ERROR_INDEX_CHECK_SCHEMA);
3045  }
3046 
3047  _isError = false;
3048  }
3049  catch(Poco::Exception& e)
3050  {
3051  errorMsg = e.displayText();
3052  errorCode = e.code();
3053  }
3054  return !_isError;
3055 }
3056 //-----------------------------------------------------------------------------
3057 //-----------------------------------------------------------------------------
3059 :inherited(fObj)
3060 {
3061 }
3062 //-----------------------------------------------------------------------------
3064 {
3065  errorMsg.clear();
3066  errorCode = NO_ERROR;
3067  _isError = true;
3068 
3069  try
3070  {
3071  std::string path = fObj.getDataDir()+"/"+indexName;
3072  if (!isExistDir(path))
3073  throw Poco::Exception("Index '"+path+"' not exist", ERROR_INDEX_SEARCHD_STATUS);
3074 
3075  const std::string configFile = path+"/"+sphinx_search_const::sphinxConfigName;
3076  if (!isExistFile(configFile))
3077  throw Poco::Exception("Config file '"+configFile+"' not exist", ERROR_INDEX_SEARCHD_STATUS);
3078 
3079  std::stringstream outMsg, errMsg;
3080  const std::string cmd("searchd");
3081  std::vector<std::string> args = {"--status", "--config", configFile};
3082  ProcExec procExec(cmd, args);
3083  if (!procExec.exec(outMsg, errMsg))
3084  throw Poco::Exception("Get status searchd '"+configFile+"' fail\n"+errMsg.str(), ERROR_INDEX_SEARCHD_STATUS);
3085 
3086  if (isExistError(outMsg.str()))
3087  throw Poco::Exception(outMsg.str(), ERROR_INDEX_SEARCHD_STATUS);
3088 
3089  resultData = outMsg.str();
3090 
3091  _isError = false;
3092  }
3093  catch(Poco::Exception& e)
3094  {
3095  errorMsg = e.message();
3096  errorCode = e.code();
3097  }
3098  return !_isError;
3099 }
3100 //-----------------------------------------------------------------------------
3102 {
3103  bool result = false;
3104 
3105  try
3106  {
3107  const std::string propFile = fObj.getDataDir()+"/"+indexName+"/"+sphinx_search_const::sphinxPropertyFile;
3108  Poco::AutoPtr<SphinxConfigCreator> pConf = new SphinxConfigCreator(propFile);
3109  const std::string pidFile = pConf->getString(sphinx_search_const::searchdPidName);
3110  result = isExistFile(pidFile);
3111  }
3112  catch(Poco::Exception& e)
3113  {
3114  errorMsg = e.message();
3116  }
3117  return result;
3118 }
3119 //-----------------------------------------------------------------------------
3120 //-----------------------------------------------------------------------------
3122 :inherited(fObj)
3123 {
3124 }
3125 //-----------------------------------------------------------------------------
3127 {
3128  errorMsg.clear();
3129  errorCode = NO_ERROR;
3130  _isError = true;
3131 
3132  try
3133  {
3134  std::string path = fObj.getDataDir()+"/"+indexName;
3135  if (!isExistDir(path))
3136  throw Poco::Exception("Index '"+path+"' not exist", ERROR_INDEX_STATUS);
3137 
3138  const std::string configFile = path+"/"+sphinx_search_const::sphinxConfigName;
3139  if (!isExistFile(configFile))
3140  throw Poco::Exception("Config file '"+configFile+"' not exist", ERROR_INDEX_STATUS);
3141 
3142  std::stringstream outMsg;
3143  const std::string cmd("indextool");
3144  std::vector<std::string> args = {"--dumpheader", fObj.getIndexFileName(), "--config", configFile};
3145  ProcExec procExec(cmd, args);
3146  outMsg << procExec;
3147  if (procExec.isError())
3148  throw Poco::Exception("Get index status '"+configFile+"' fail", ERROR_INDEX_STATUS);
3149 
3150  if (isExistError(outMsg.str()))
3151  throw Poco::Exception(outMsg.str(), ERROR_INDEX_STATUS);
3152 
3153  resultData = outMsg.str();
3154 
3155  _isError = false;
3156  }
3157  catch(Poco::Exception& e)
3158  {
3159  errorMsg = e.message();
3160  errorCode = e.code();
3161  }
3162  return !_isError;
3163 }
3164 //-----------------------------------------------------------------------------
3165 //-----------------------------------------------------------------------------
3167 :inherited(fObj)
3168 {
3169 }
3170 //-----------------------------------------------------------------------------
3172 {
3173  errorMsg.clear();
3174  errorCode = NO_ERROR;
3175  _isError = true;
3176 
3177  try
3178  {
3179  unsigned long long maxDocId = 0;
3180  resultData = std::to_string(maxDocId);
3181 
3182  std::string path = fObj.getDataDir()+"/"+indexName;
3183  if (!isExistDir(path))
3184  throw Poco::Exception("Index '"+path+"' not exist", ERROR_INDEX_MAX_DOC_ID);
3185 
3186  std::string dataDir = path+"/"+sphinx_admin_command_const::dataDir;
3187 
3188  if (!isExistDir(dataDir))
3189  throw Poco::Exception("Forder: '"+dataDir+"' not exists", ERROR_INDEX_MAX_DOC_ID);
3190 
3191  std::vector<std::string> vFiles;
3193  throw Poco::Exception(errorMsg, ERROR_INDEX_MAX_DOC_ID);
3194 
3195  std::ifstream ifs;
3196  SphinxDataSourceParameters dataSourceParameters;
3197  for (size_t i=0;i<vFiles.size();++i)
3198  {
3199  const std::string fileName = dataDir+"/"+vFiles[i] +"."+sphinx_admin_command_const::sourceFileExtension;
3200  ifs.open(fileName.c_str());
3201  if (ifs.is_open())
3202  {
3203  if (dataSourceParameters.load(ifs))
3204  {
3205  if (maxDocId < dataSourceParameters.getMaxDocId())
3206  maxDocId = dataSourceParameters.getMaxDocId();
3207  }
3208  else
3209  fObj.log() << "Search MaxDocsID in '" << fileName << "' fail." << dataSourceParameters.getErrorMsg() << std::endl;
3210  ifs.close();
3211  }
3212  else
3213  fObj.log() << "File '" << fileName << "' not open" << std::endl;
3214  }
3215 
3216  resultData = std::to_string(maxDocId);
3217  _isError = false;
3218  }
3219  catch(Poco::Exception& e)
3220  {
3221  errorMsg = e.message();
3222  errorCode = e.code();
3223  }
3224  catch(std::exception& e)
3225  {
3226  errorMsg = e.what();
3228  }
3229  return !_isError;
3230 }
3231 //-----------------------------------------------------------------------------
3232 //-----------------------------------------------------------------------------
3234 :inherited(fObj)
3235 {
3236 }
3237 //-----------------------------------------------------------------------------
3239 {
3240  errorMsg.clear();
3241  errorCode = NO_ERROR;
3242  _isError = true;
3243  try
3244  {
3245  if (indexName.empty())
3247 
3248  std::string path = fObj.getDataDir()+"/"+indexName;
3249 
3250  if (!isExistDir(path))
3251  throw Poco::Exception("Forder: '"+path+"' not exists", ERROR_INDEX_DATA_LIST);
3252 
3253  std::string dataDir = path+"/"+sphinx_admin_command_const::dataDir;
3254 
3255  if (!isExistDir(path+"/"+sphinx_admin_command_const::dataDir))
3256  throw Poco::Exception("Forder: '"+path+"/"+sphinx_admin_command_const::dataDir+"' not exists", ERROR_INDEX_DATA_LIST);
3257 
3258  std::vector<std::string> vFiles;
3260  {
3261  for (size_t i=0;i<vFiles.size();++i)
3262  {
3263  if (!resultData.empty())
3264  resultData.append(",");
3265  resultData.append(vFiles[i]);
3266  }
3267  _isError = false;
3268  }
3269  }
3270  catch(Poco::Exception& e)
3271  {
3272  errorMsg = e.message();
3273  errorCode = e.code();
3274  }
3275  return !_isError;
3276 }
3277 //-----------------------------------------------------------------------------
3278 //-----------------------------------------------------------------------------
3280 :inherited(fObj)
3281 {
3282 }
3283 //-----------------------------------------------------------------------------
3285 {
3286  errorMsg.clear();
3287  errorCode = NO_ERROR;
3288  _isError = true;
3289  try
3290  {
3291  if (indexName.empty())
3293 
3294  std::string path = fObj.getDataDir()+"/"+indexName;
3295 
3296  if (!isExistDir(path))
3297  throw Poco::Exception("Forder: '"+path+"' not exists", ERROR_INDEX_BRANCHES_LIST);
3298 
3299  std::string indexDir = path+"/"+sphinx_admin_command_const::indexDir;
3300 
3301  if (!isExistDir(path+"/"+sphinx_admin_command_const::indexDir))
3302  throw Poco::Exception("Forder: '"+path+"/"+sphinx_admin_command_const::indexDir+"' not exists", ERROR_INDEX_BRANCHES_LIST);
3303 
3304  std::vector<std::string> vIndexes;
3305  if (getIndexList(indexDir, vIndexes))
3306  {
3307  for (size_t i=0;i<vIndexes.size();++i)
3308  {
3309  if (!resultData.empty())
3310  resultData.append(",");
3311  resultData.append(vIndexes[i]);
3312  }
3313  _isError = false;
3314  }
3315  }
3316  catch(Poco::Exception& e)
3317  {
3318  errorMsg = e.message();
3319  errorCode = e.code();
3320  }
3321  return !_isError;
3322 }
3323 //-----------------------------------------------------------------------------
3324 //-----------------------------------------------------------------------------
3326 :inherited(fObj)
3327 {
3328 }
3329 //-----------------------------------------------------------------------------
3330 bool IndexBranchesInfo::getBranchInfo(const std::string& branchName, const std::string& branchPath, std::string& branchFieldsList)
3331 {
3332  bool result = false;
3333  branchFieldsList.clear();
3334  const std::string branchFileName = branchPath+"/"+branchName+"."+sphinx_admin_command_const::sourceFileExtension;
3335 
3336  try
3337  {
3338  std::ifstream ifs;
3339  SphinxDataSourceParameters dataSourceParameters;
3340  ifs.open(branchFileName.c_str());
3341  if (!ifs.is_open())
3342  throw Poco::Exception("Open "+branchFileName+" fail");
3343 
3344  bool loaded = dataSourceParameters.load(ifs);
3345  ifs.close();
3346  if (!loaded)
3347  throw Poco::Exception("Load "+branchFileName+" fail. "+dataSourceParameters.getErrorMsg());
3348 
3349  std::string fieldsList;
3350  SphinxDataSourceParameters::PARAM_ATTR__MAP& paramAttr = dataSourceParameters.getParamAttr();
3351  for (SphinxDataSourceParameters::PARAM_ATTR__MAP::iterator iter=paramAttr.begin();iter!=paramAttr.end();++iter)
3352  {
3353  if (!fieldsList.empty())
3354  fieldsList.append(",");
3355  fieldsList.append((*iter).first).append("=").append(std::to_string((*iter).second));
3356  }
3357  Poco::URI::encode(fieldsList, "", branchFieldsList);
3358  result = true;
3359  }
3360  catch(Poco::Exception& e)
3361  {
3362  errorMsg = e.message();
3363  }
3364  return result;
3365 }
3366 //-----------------------------------------------------------------------------
3368 {
3369  errorMsg.clear();
3370  errorCode = NO_ERROR;
3371  _isError = true;
3372  try
3373  {
3374  if (branches.empty())
3375  throw Poco::Exception("Received empty list of branches", ERROR_COMMAND_INITIALIZATION);
3376 
3377  std::string path = fObj.getDataDir()+"/"+indexName;
3378 
3379  if (!isExistDir(path))
3380  throw Poco::Exception("Forder: '"+path+"' not exists", ERROR_INDEX_BRANCHES_INFO);
3381 
3382  const std::string indexDir = path+"/"+sphinx_admin_command_const::indexDir;
3383  const std::string dataDir = path+"/"+sphinx_admin_command_const::dataDir;
3384 
3385  if (!isExistDir(indexDir))
3386  throw Poco::Exception("Forder: '"+indexDir+"' not exists", ERROR_INDEX_BRANCHES_INFO);
3387 
3388  if (!isExistDir(dataDir))
3389  throw Poco::Exception("Forder: '"+dataDir+"' not exists", ERROR_INDEX_BRANCHES_INFO);
3390 
3391  std::vector<std::string> vFiles;
3393  {
3394  unsigned int madeFailCount = 0;
3395  if (branches.front()=="*")
3396  {
3397  for (size_t i=0;i<vFiles.size();++i)
3398  {
3399  std::string branchFieldsList;
3400  if (getBranchInfo(vFiles[i], dataDir, branchFieldsList))
3401  {
3402  if (!resultData.empty())
3403  resultData.append("&");
3404  resultData.append(vFiles[i]).append("=").append(branchFieldsList);
3405  }
3406  else
3407  ++madeFailCount;
3408  }
3409  }
3410  else
3411  {
3412  for (size_t k=0;k<branches.size();++k)
3413  for (size_t i=0;i<vFiles.size();++i)
3414  if (vFiles[i]==branches[k])
3415  {
3416  std::string branchFieldsList;
3417  if (getBranchInfo(vFiles[i], dataDir, branchFieldsList))
3418  {
3419  if (!resultData.empty())
3420  resultData.append("&");
3421  resultData.append(vFiles[i]).append("=").append(branchFieldsList);
3422  }
3423  else
3424  ++madeFailCount;
3425  break;
3426  }
3427  }
3428  if (madeFailCount==0)
3429  _isError = false;
3430  }
3431 
3432  if (_isError)
3433  throw Poco::Exception(errorMsg, ERROR_INDEX_BRANCHES_INFO);
3434  }
3435  catch(Poco::Exception& e)
3436  {
3437  errorMsg = e.message();
3438  errorCode = e.code();
3439  }
3440  return !_isError;
3441 }
3442 //-----------------------------------------------------------------------------
3443 //-----------------------------------------------------------------------------
3445 :inherited(fObj)
3446 {
3447 }
3448 //-----------------------------------------------------------------------------
3449 bool IndexBranchesStatus::makeBranchConfig(const std::string& indexName, const std::string& indexFileName, std::string& configFile)
3450 {
3451  bool result = false;
3452  const std::string path = fObj.getDataDir()+"/"+indexName;
3453  const std::string propFile = path+"/"+sphinx_search_const::sphinxPropertyFile;
3454  configFile = path+"/"+sphinx_search_const::branchConfigFile;
3455  try
3456  {
3457  Poco::AutoPtr<SphinxConfigCreator> pConf = new SphinxConfigCreator(propFile);
3458  std::vector<std::string> keys;
3459  pConf->keys(keys);
3460 
3461  std::string trunkSectionName;
3462  for (size_t i=0;i<keys.size();++i)
3463  {
3464  if (keys[i].find(sphinx_search_const::sourceNameField)!=std::string::npos)
3465  {
3466  std::string name = keys[i]+"."+sphinx_search_const::xmlpipeCommandNameField;
3467  std::string value = "cat "+path+"/"+sphinx_admin_command_const::dataDir+"/"+indexFileName+"."+sphinx_admin_command_const::sourceFileExtension;
3468  pConf->setString(name, value);
3469  }
3470  if (keys[i].find(sphinx_search_const::indexNameField)!=std::string::npos)
3471  trunkSectionName = keys[i];
3472  }
3474  std::string value = path+"/"+fObj.getIndexFileName();
3475  pConf->setString(name, value);
3476 
3477  std::string branchSectionName = sphinx_search_const::indexNameField+" "+indexFileName;
3478  pConf->cloneSphinxConfigSection(trunkSectionName, branchSectionName);
3479 
3480  name = branchSectionName+"."+sphinx_search_const::pathNameField;
3481  value = path+"/"+sphinx_admin_command_const::indexDir+"/"+indexFileName;
3482  pConf->setString(name, value);
3483 
3484  value = fObj.getLogDir()+"/"+indexName+"/"+sphinx_search_const::searchdLogFile;
3485  pConf->setString(sphinx_search_const::searchdLogName, value);
3486 
3487  value = fObj.getRunDir()+"/"+/*indexName+"/"+*/
3488  sphinx_search_const::searchdPidFileName+"_"+indexName+"."+
3490  pConf->setString(sphinx_search_const::searchdPidName, value);
3491 
3492  value = fObj.getLogDir()+"/"+indexName+"/"+sphinx_search_const::searchdQueryLogFile;
3493  pConf->setString(sphinx_search_const::searchdQueryLogName, value);
3494 
3495  pConf->save(propFile);
3496  pConf->setPropertyFileConfiguration(propFile);
3497  pConf->deleteSphinxConfigSection(sphinx_admin_command_const::sectionOptions);
3498 
3499  std::ofstream ofs(configFile.c_str(), std::fstream::trunc);
3500  ofs << *pConf;
3501  ofs.close();
3502  result = true;
3503  }
3504  catch(Poco::Exception& e)
3505  {
3506  errorMsg = e.message();
3507  fObj.log() << "Make branch config error: " << errorMsg << std::endl;
3508  }
3509  return result;
3510 
3511 
3512 }
3513 //-----------------------------------------------------------------------------
3514 bool IndexBranchesStatus::getBranchInfo(const std::string& indexName, const std::string& indexFileName, std::string& information)
3515 {
3516  bool result = false;
3517  information.clear();
3518 
3519  try
3520  {
3521  std::string branchConfigFileName;
3522  if (!makeBranchConfig(indexName, indexFileName, branchConfigFileName))
3523  throw Poco::Exception(errorMsg, ERROR_INDEX_STATUS);
3524 
3525  if (!isExistFile(branchConfigFileName))
3526  throw Poco::Exception("Config file '"+branchConfigFileName+"' not exist", ERROR_INDEX_STATUS);
3527 
3528  std::stringstream outMsg, errMsg;
3529  const std::string cmd("indextool");
3530  std::vector<std::string> args = {"--dumpheader", indexFileName, "--config", branchConfigFileName};
3531  ProcExec procExec(cmd, args);
3532  if (!procExec.exec(outMsg, errMsg))
3533  throw Poco::Exception("Get status '"+indexFileName+"' fail\n"+errMsg.str(), ERROR_INDEX_STATUS);
3534 
3535  if (isExistError(outMsg.str()))
3536  throw Poco::Exception(outMsg.str(), ERROR_INDEX_STATUS);
3537 
3538  Poco::URI::encode(outMsg.str(), "", information);
3539 
3540  result = removeFile(branchConfigFileName);
3541  }
3542  catch(Poco::Exception& e)
3543  {
3544  errorMsg.append(e.message());
3545  errorCode = e.code();
3546  }
3547  return result;
3548 }
3549 //-----------------------------------------------------------------------------
3551 {
3552  errorMsg.clear();
3553  errorCode = NO_ERROR;
3554  _isError = true;
3555  try
3556  {
3557  if (branches.empty())
3558  throw Poco::Exception("Received empty list of branches", ERROR_COMMAND_INITIALIZATION);
3559 
3560  std::string path = fObj.getDataDir()+"/"+indexName;
3561 
3562  if (!isExistDir(path))
3563  throw Poco::Exception("Forder: '"+path+"' not exists", ERROR_INDEX_BRANCHES_STATUS);
3564 
3565  std::string indexDir = path+"/"+sphinx_admin_command_const::indexDir;
3566  std::string dataDir = path+"/"+sphinx_admin_command_const::dataDir;
3567 
3568  if (!isExistDir(indexDir))
3569  throw Poco::Exception("Forder: '"+indexDir+"' not exists", ERROR_INDEX_BRANCHES_STATUS);
3570 
3571  if (!isExistDir(dataDir))
3572  throw Poco::Exception("Forder: '"+dataDir+"' not exists", ERROR_INDEX_BRANCHES_STATUS);
3573 
3574  std::vector<std::string> vIndexes;
3575  if (getIndexList(indexDir, vIndexes))
3576  {
3577  unsigned int madeFailCount = 0;
3578  if (branches.front()=="*")
3579  {
3580  for (size_t i=0;i<vIndexes.size();++i)
3581  {
3582  std::string information;
3583  if (getBranchInfo(indexName, vIndexes[i], information))
3584  {
3585  if (!resultData.empty())
3586  resultData.append("&");
3587  resultData.append(vIndexes[i]).append("=").append(information);
3588  }
3589  else
3590  ++madeFailCount;
3591  }
3592  }
3593  else
3594  {
3595  for (size_t k=0;k<branches.size();++k)
3596  for (size_t i=0;i<vIndexes.size();++i)
3597  if (vIndexes[i]==branches[k])
3598  {
3599  std::string information;
3600  if (getBranchInfo(indexName, vIndexes[i], information))
3601  {
3602  if (!resultData.empty())
3603  resultData.append("&");
3604  resultData.append(vIndexes[i]).append("=").append(information);
3605  }
3606  else
3607  ++madeFailCount;
3608  break;
3609  }
3610  }
3611  if (madeFailCount==0)
3612  _isError = false;
3613  }
3614 
3615  if (_isError)
3616  throw Poco::Exception(errorMsg, ERROR_INDEX_BRANCHES_STATUS);
3617  }
3618  catch(Poco::Exception& e)
3619  {
3620  errorMsg = e.message();
3621  errorCode = e.code();
3622  }
3623  return !_isError;
3624 }
3625 //-----------------------------------------------------------------------------
3627 :inherited(fObj)
3628 {
3629 }
3630 //-----------------------------------------------------------------------------
3632 {
3633  errorMsg.clear();
3634  errorCode = NO_ERROR;
3635  _isError = true;
3636 
3637  try
3638  {
3639  if (indexName.empty() && fObj.getIndexName().empty())
3640  throw Poco::Exception("Current index name is empty", ERROR_INDEX_CONNECT);
3641 
3642  std::string path = (indexName.empty())?(fObj.getDataDir()+"/"+fObj.getIndexName()):(fObj.getDataDir()+"/"+indexName);
3643 
3644  if (!isExistDir(path))
3645  throw Poco::Exception("Index '"+path+"' not exist", ERROR_INDEX_CONNECT);
3646 
3647  path.append("/").append(sphinx_search_const::sphinxConfigName);
3648  if (!isExistFile(path))
3649  throw Poco::Exception("Config file '"+path+"' not exist", ERROR_INDEX_CONNECT);
3650 
3651  if (!indexName.empty())
3653 
3655  throw Poco::Exception(fObj.getErrorMsg(), ERROR_INDEX_CONNECT);
3656 
3657  if (fObj.isConnected())
3658  if (!fObj.close())
3659  throw Poco::Exception(fObj.getErrorMsg(), ERROR_INDEX_CONNECT);
3660 
3661  if (!fObj.easyStart())
3662  throw Poco::Exception(fObj.getErrorMsg(), ERROR_INDEX_CONNECT);
3663 
3664  _isError = false;
3665  }
3666  catch(Poco::Exception& e)
3667  {
3668  errorMsg = e.message();
3669  errorCode = e.code();
3670  }
3671  return !_isError;
3672 }
3673 //-----------------------------------------------------------------------------
3674 //-----------------------------------------------------------------------------
3676 :inherited(fObj)
3677 {
3678 }
3679 //-----------------------------------------------------------------------------
3680 bool IndexDisconnect::serialize(std::string& json)
3681 {
3682  _isError = true;
3683  errorMsg.clear();
3684  try
3685  {
3686  Poco::JSON::Object::Ptr obj = new Poco::JSON::Object();
3687 
3688  std::stringstream ostr;
3689  Poco::JSON::Stringifier::stringify(obj, ostr);
3690  json = ostr.str();
3691 
3692  _isError = false;
3693  }
3694  catch(std::exception& e)
3695  {
3696  errorMsg = e.what();
3698  }
3699  return !_isError;
3700 }
3701 //-----------------------------------------------------------------------------
3702 bool IndexDisconnect::unserialize(const std::string& json)
3703 {
3704  errorMsg.clear();
3705  _isError = true;
3706  try
3707  {
3708  Poco::JSON::Parser parser;
3709  Poco::Dynamic::Var res = parser.parse(json);
3710  Poco::JSON::Object::Ptr obj = res.extract<Poco::JSON::Object::Ptr>();
3711 
3712  _isError = false;
3713  }
3714  catch(Poco::JSON::JSONException& e)
3715  {
3716  errorMsg = e.displayText();
3718  }
3719  return !_isError;
3720 }
3721 //-----------------------------------------------------------------------------
3723 {
3724  errorMsg.clear();
3725  errorCode = NO_ERROR;
3726  _isError = true;
3727 
3728  try
3729  {
3730  if (fObj.isConnected())
3731  if (!fObj.close())
3732  throw Poco::Exception(fObj.getErrorMsg(), ERROR_INDEX_DISCONNECT);
3733 
3734  _isError = false;
3735  }
3736  catch(Poco::Exception& e)
3737  {
3738  errorMsg = e.message();
3739  errorCode = e.code();
3740  }
3741  return !_isError;
3742 }
3743 //-----------------------------------------------------------------------------
3744 //-----------------------------------------------------------------------------
3745 } // end namespace sphinx
3746 } // end namespace HCE