OpenCog Framework  Branch: master, revision 6f0b7fc776b08468cf1b74aa9db028f387b4f0c0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
AtomspaceHTabler.cc
Go to the documentation of this file.
1 /*
2  * opencog/hypertable/AtomspaceHTabler.h
3  *
4  * Copyright (C) 2009-2011 OpenCog Foundation
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Affero General Public License v3 as
8  * published by the Free Software Foundation and including the exceptions
9  * at http://opencog.org/wiki/Licenses
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with this program; if not, write to:
18  * Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21 
22 #include <Common/Compat.h>
23 
24 #include <cstdio>
25 #include <cstring>
26 #include <iostream>
27 #include <vector>
28 #include <sstream>
29 #include <Common/Error.h>
30 
31 #include <Hypertable/Lib/ApacheLogParser.h>
32 #include <Hypertable/Lib/Client.h>
33 #include <Hypertable/Lib/KeySpec.h>
34 
36 
39 #include <opencog/server/CogServer.h>
43 
44 using namespace opencog;
45 using namespace Hypertable;
46 
47 const int BUFF_SIZE = 1028; //TODO: Figure out how big this should actually be
48 const int TIMEOUT = 3000;
49 
50 const String attribute_schema = "\
51 <Schema>\n\
52  <AccessGroup name=\"default\">\n\
53  <ColumnFamily>\n\
54  <Name>name</Name>\n\
55  <deleted>false</deleted>\n\
56  </ColumnFamily>\n\
57  <ColumnFamily>\n\
58  <Name>type</Name>\n\
59  <deleted>false</deleted>\n\
60  </ColumnFamily>\n\
61  <ColumnFamily>\n\
62  <Name>stv</Name>\n\
63  <deleted>false</deleted>\n\
64  </ColumnFamily>\n\
65  <ColumnFamily>\n\
66  <Name>incoming</Name>\n\
67  <deleted>false</deleted>\n\
68  </ColumnFamily>\n\
69  <ColumnFamily>\n\
70  <Name>outgoing</Name>\n\
71  <deleted>false</deleted>\n\
72  </ColumnFamily>\n\
73  <ColumnFamily>\n\
74  <Name>sti</Name>\n\
75  <deleted>false</deleted>\n\
76  </ColumnFamily>\n\
77  <ColumnFamily>\n\
78  <Name>lti</Name>\n\
79  <deleted>false</deleted>\n\
80  </ColumnFamily>\n\
81  <ColumnFamily>\n\
82  <Name>vlti</Name>\n\
83  <deleted>false</deleted>\n\
84  </ColumnFamily>\n\
85  </AccessGroup>\n\
86 </Schema>";
87 
88 const String handle_schema = "\
89 <Schema>\n\
90  <AccessGroup name=\"default\">\n\
91  <ColumnFamily>\n\
92  <Name>handle</Name>\n\
93  <deleted>false</deleted>\n\
94  </ColumnFamily>\n\
95  </AccessGroup>\n\
96 </Schema>";
97 
98 
99 #ifdef HYPERTABLE_INSTALL_DIR
101 {
102  try {
103  c = new Client(HYPERTABLE_INSTALL_DIR, HYPERTABLE_CONFIG_FILE, TIMEOUT);
104  }
105  catch (Hypertable::Exception& e) {
106  if (e.code() == Error::REQUEST_TIMEOUT) {
107  throw NetworkException(TRACE_INFO, "Timeout connecting to hyperspace."
108  " Confirm Hypertable servers are running and try again.");
109  }
110  }
111  initTables();
112 }
113 #else
115 {
116  std::cerr << "To use hypertable functionality, define"
117  << " HYPERTABLE_INSTALL_DIR and HYPERTABLE_CONFIG_FILE"
118  << " in opencog/hypertable/AtomspaceHTabler.h" << std::endl;
119  exit(1);
120 }
121 #endif
122 
124 {
125  std::vector<String> tables;
126  c->get_tables(tables);
127  if (find(tables.begin(), tables.end(), "Atomtable") == tables.end()) {
128  c->create_table("Atomtable", attribute_schema);
129  }
130  if (find(tables.begin(), tables.end(), "Nametable") == tables.end()) {
131  c->create_table("Nametable", handle_schema);
132  }
133  if (find(tables.begin(), tables.end(), "Outsettable") == tables.end()) {
134  c->create_table("Outsettable", handle_schema);
135  }
136  m_handle_table = c->open_table("Atomtable");
137  m_handle_mutator = m_handle_table->create_mutator();
138  m_name_table = c->open_table("Nametable");
139  m_name_mutator = m_name_table->create_mutator();
140  m_outset_table = c->open_table("Outsettable");
141  m_outset_mutator = m_outset_table->create_mutator();
142 }
143 
145 {
146  c->drop_table("Atomtable", true);
147  c->drop_table("Nametable", true);
148  c->drop_table("Outsettable", true);
149  initTables();
150 }
151 
156 Link * AtomspaceHTabler::getLink(Type t, const std::vector<Handle>& handles) const
157 {
158  TableScannerPtr scanner_ptr;
159  ScanSpecBuilder ssb;
160  Cell cell;
161  std::stringstream row;
162 
163  ssb.add_column("handle");
164  row << t;
165  std::vector<Handle>::const_iterator iter;
166  for (iter = handles.begin(); iter != handles.end(); ++iter)
167  {
168  row << ',';
169  UUID uuid = (*iter).value();
170  row << uuid;
171  }
172  ssb.add_row(row.str().c_str());
173  ssb.set_max_versions(1);
174 
175  scanner_ptr = m_outset_table->create_scanner(ssb.get());
176  if (scanner_ptr->next(cell))
177  {
178  std::string handle_str((char *)cell.value, cell.value_len);
179  UUID uuid = strtoul(handle_str.c_str(), NULL, 10);
180  Handle h(uuid);
181  return dynamic_cast<Link *>(getAtom(h));
182  }
183  else {
184  return NULL;
185  }
186 }
187 
192 Node* AtomspaceHTabler::getNode(Type t, const char * name) const
193 {
194  TableScannerPtr scanner_ptr;
195  ScanSpecBuilder ssb;
196  Cell cell;
197 
198  ssb.add_column("handle");
199  std::stringstream row;
200  row << name << ',' << (unsigned long) t;
201  ssb.add_row(row.str().c_str());
202  ssb.set_max_versions(1);
203 
204  scanner_ptr = m_name_table->create_scanner(ssb.get());
205  if (scanner_ptr->next(cell))
206  {
207  std::string handle_str((char *)cell.value, cell.value_len);
208  UUID uuid = strtoul(handle_str.c_str(), NULL, 10);
209  Handle h(uuid);
210  return dynamic_cast<Node *>(getAtom(h));
211  }
212  else
213  {
214  return NULL;
215  }
216 }
217 
224 {
225  std::cout << "storeAtom() called\n";
226  AtomSpace *as = cogserver().getAtomSpace();
227 
228  // If TLB didn't give us an atom, it was a bad handle and there's nothing
229  // else to do.
230  if (!as->isValidHandle(h)) {
231  std::cerr << "storeAtom(): Bad handle\n";
232  return;
233  }
234 
235  KeySpec key;
236  memset(&key, 0, sizeof(key));
237 
238  // Create row index from handle
239  char row[BUFF_SIZE]; //TODO: Figure out how big this should actually be
240 
241  UUID uuid = h.value();
242  key.row_len = snprintf(row, BUFF_SIZE, "%lu", uuid);
243  key.row = row;
244 
245  // If it's a node...
246  if (as->isNode(as->getType(h)))
247  {
248  // Store the name
249  key.column_family = "name";
250  m_handle_mutator->set(key, as->getName(h).c_str(), as->getName(h).length());
251 
252  // Store the handle in Nametable
253  KeySpec name_key;
254  memset(&name_key, 0, sizeof(name_key));
255 
256  char r[BUFF_SIZE];
257  int len = snprintf(r, BUFF_SIZE, "%hu", as->getType(h));
258 
259  std::string name_index = as->getName(h) + ',' + std::string(r,len);
260  name_key.row = name_index.c_str();
261  name_key.row_len = name_index.length();
262  name_key.column_family = "handle";
263 
264  m_name_mutator->set(name_key, key.row, key.row_len);
265  m_name_mutator->flush(); //TODO: Flush to get rid of if possible
266  }
267  // If it's a link...
268  else
269  {
270  // Store the outgoing set
271  int arity = as->getArity(h);
272  const std::vector<Handle> &out = as->getOutgoing(h);
273  std::stringstream ss;
274  for (int i = 0; i < arity; ++i)
275  {
276  ss << out[i];
277  ss << ',';
278 
279  // XXX: Should the outgoing atom itself also be stored?
280  // It makes sense that it would, though that leads to problems
281  // with cycles.
282  }
283  key.column_family = "outgoing";
284  m_handle_mutator->set(key, ss.str().c_str(), ss.str().length());
285 
286  // Store the handle in Outsettable
287  KeySpec outset_key;
288  memset(&outset_key, 0, sizeof(outset_key));
289 
290  char r[BUFF_SIZE];
291  int len = snprintf(r, BUFF_SIZE, "%hu", as->getType(h));
292 
293  std::vector<Handle>::const_iterator iter;
294  for (iter = as->getOutgoing(h).begin();
295  iter != as->getOutgoing(h).end(); ++iter)
296  {
297  UUID uuid = (*iter).value();
298  r[len++] = ',';
299  len += snprintf(r+len, BUFF_SIZE-len, "%lu", uuid);
300  }
301  outset_key.row = r;
302  outset_key.row_len = len;
303 
304  outset_key.column_family = "handle";
305  m_outset_mutator->set(outset_key, key.row, key.row_len);
306  m_outset_mutator->flush(); //TODO: Flush to get rid of if possible
307  }
308 
309  char val[BUFF_SIZE];
310  int val_len;
311 
312  // Store type
313  Type t = as->getType(h);
314  val_len = snprintf(val, BUFF_SIZE, "%d", t);
315  key.column_family = "type";
316  m_handle_mutator->set(key, val, val_len);
317 
318  // Store the importance
319  const AttentionValue& av = as->getAV(h);
320  short sti = av.getSTI();
321  short lti = av.getLTI();
322  unsigned short vlti = av.getVLTI();
323 
324  val_len = snprintf(val, BUFF_SIZE, "%hd", sti);
325  key.column_family = "sti";
326  m_handle_mutator->set(key, val, val_len);
327 
328  val_len = snprintf(val, BUFF_SIZE, "%hd", lti);
329  key.column_family = "lti";
330  m_handle_mutator->set(key, val, val_len);
331 
332  val_len = snprintf(val, BUFF_SIZE, "%hu", vlti);
333  key.column_family = "vlti";
334  m_handle_mutator->set(key, val, val_len);
335 
336  // Store the truth value
337  const TruthValue &tv = as->getTV(h);
338  const SimpleTruthValue *stv = dynamic_cast<const SimpleTruthValue *>(&tv);
339  if (NULL == stv)
340  {
341  std::cerr << "Non-simple truth values are not handled\n";
342  return;
343  }
344  val_len = snprintf(val, BUFF_SIZE, "(%f, %f)",
345  tv.getMean(), tv.getCount());
346  key.column_family = "stv";
347  m_handle_mutator->set(key, val, val_len);
348 
349 
350 #ifdef THERE_IS_NO_NEED_TO_STORE_INCOMING_SET
351  // Store incoming set
352  HandleSeq hs = as->getIncoming(h);
353  std::stringstream ss;
354  for (Handle handle : hs) {
355  ss << ',';
356  ss << handle;
357  }
358  key.column_family = "incoming";
359  m_handle_mutator->set(key, ss.str().c_str(), ss.str().length());
360 #endif /* THERE_IS_NO_NEED_TO_STORE_INCOMING_SET */
361 
362  // TODO: Find a way to get rid of this if possible; it may hurt performance.
363  m_handle_mutator->flush();
364 
365  return;
366 }
367 
372 std::vector<Handle> AtomspaceHTabler::getIncomingSet(Handle h) const
373 {
374  TableScannerPtr scanner_ptr;
375  ScanSpecBuilder ssb;
376  Cell cell;
377  std::vector<Handle> handles;
378 
379  ssb.add_column("incoming");
380  char rowbuff[BUFF_SIZE];
381  snprintf(rowbuff, BUFF_SIZE, "%lu", h.value());
382  ssb.add_row(rowbuff);
383  ssb.set_max_versions(1);
384 
385  scanner_ptr = m_handle_table->create_scanner(ssb.get());
386 
387  while (scanner_ptr->next(cell)) {
388  char *end = (char *)cell.value + cell.value_len;
389  char *comma = (char *)cell.value;
390  while (comma != end) {
391  Handle h = (Handle) strtoul(comma+1, &comma, 10);
392  handles.push_back(h);
393  }
394  }
395 
396  return handles;
397 }
398 
404 {
405  std::cout << "getAtom() called" << std::endl;
406  TableScannerPtr scanner_ptr;
407  ScanSpecBuilder ssb;
408  Cell cell;
409 
410  ssb.add_column("type");
411  ssb.add_column("name");
412  ssb.add_column("stv");
413  ssb.add_column("outgoing");
414  ssb.add_column("sti");
415  ssb.add_column("lti");
416  ssb.add_column("vlti");
417 
418  char rowbuff[BUFF_SIZE];
419  UUID uuid = h.value();
420  snprintf(rowbuff, BUFF_SIZE, "%lu", uuid);
421  ssb.add_row(rowbuff);
422  ssb.set_max_versions(1);
423 
424  Atom *atom_ptr;
425 
426  try {
427  scanner_ptr = m_handle_table->create_scanner(ssb.get());
428  } catch (Exception &e) {
429  std::cerr << e << std::endl;
430  return NULL;
431  }
432 
433  std::string name;
434  const char* stv = 0;
435  std::string stv_str;
436  int type;
437  std::vector<Handle> handles;
438  short sti;
439  short lti;
440  unsigned short vlti;
441 
442  bool found = false;
443 
444  std::cout<< "getAtom(): scanning and processing data..." <<std::endl;
445 
446  //XXX: Can we guarantee the order these will be found? If so, we don't
447  // have to remember as much.
448  // retrieve & process all the information about the atom
449  while (scanner_ptr->next(cell))
450  {
451  found = true;
452  if (!strcmp("type", cell.column_family))
453  {
454  std::cout << "getAtom(): processing type..." <<std::endl;
455  type = atoi(std::string((char *)cell.value, cell.value_len).c_str());
456  }
457  else if (!strcmp("name", cell.column_family))
458  {
459  std::cout << "getAtom(): processing name..." <<std::endl;
460  name = std::string((char *)cell.value, cell.value_len);
461  }
462  else if (!strcmp("stv", cell.column_family))
463  {
464  std::cout << "getAtom(): processing stv..." <<std::endl;
465  std::cout << "getAtom(): stv length: " << cell.value_len << std::endl;
466  stv = std::string((char *)cell.value, cell.value_len).c_str();
467  stv_str = std::string((char *)cell.value, cell.value_len);
468  std::cout << "getAtom(): cell data is at: " << &(cell.value) << ", stv is at: " << &stv << std::endl;
469  }
470  else if (!strcmp("outgoing", cell.column_family))
471  {
472  std::cout << "getAtom(): processing outgoing..." <<std::endl;
473  char *end = (char *)cell.value + cell.value_len;
474  char *comma = (char *)cell.value;
475  while (comma != end) {
476  Handle h = (Handle) strtoul(comma, &comma, 10);
477  handles.push_back(h);
478  comma++;
479  }
480  }
481  else if (!strcmp("sti", cell.column_family))
482  {
483  std::cout << "getAtom(): processing sti..." <<std::endl;
484  sti = (short) atoi(
485  std::string((char *)cell.value, cell.value_len).c_str());
486  }
487  else if (!strcmp("lti", cell.column_family))
488  {
489  std::cout << "getAtom(): processing lti..." <<std::endl;
490  lti = (short) atoi(
491  std::string((char *)cell.value, cell.value_len).c_str());
492  }
493  else if (!strcmp("vlti", cell.column_family))
494  {
495  std::cout << "getAtom(): processing vlti..." <<std::endl;
496  vlti = (short) atoi(
497  std::string((char *)cell.value, cell.value_len).c_str());
498  }
499  std::cout << "getAtom(): item processed" <<std::endl;
500  if (stv) std::cout << "getAtom(): stv char*: " << stv << std::endl;
501  std::cout << "getAtom(): stv string: " << stv_str << std::endl;
502  }
503  std::cout<< "getAtom(): Processing complete. Creating atom." <<std::endl;
504  std::stringstream mystrstr;
505  mystrstr << stv;
506  if (mystrstr.str().empty())
507  {
508  std::cout << "no further than this" << std::endl;
509  // breakpoint here
510  std::cout << "em effing stop" << std::endl;
511  }
512  std::cout << "getAtom(): stv char*: " << stv <<std::endl;
513  std::cout << "getAtom(): stv string: " << stv_str << std::endl;
514 
515  if (!found) return NULL;
516 
517  if (classserver().isNode(type))
518  {
519  atom_ptr = new Node(type, name);
520  std::cout << "getAtom(): Node created" <<std::endl;
521  std::cout << "getAtom(): stv char*: " << stv <<std::endl;
522  std::cout << "getAtom(): stv string: " << stv_str << std::endl;
523  }
524  else
525  {
526  atom_ptr = new Link(type, handles);
527  std::cout << "getAtom(): Link created" <<std::endl;
528  std::cout << "getAtom(): stv char*: " << stv <<std::endl;
529  std::cout << "getAtom(): stv string: " << stv_str << std::endl;
530  }
531 
532  // Restore importance
533  const AttentionValue av(sti,lti,vlti);
534  atom_ptr->setAttentionValue(av);
535  std::cout<< "getAtom(): importance restored" <<std::endl;
536 
537  // Restore truth value
538  std::cout << "getAtom(): stv char*: " << stv <<std::endl;
539  std::cout << "getAtom(): stv string: " << stv_str << std::endl;
540  double mean = atof(stv + 1);
541  std::cout << "getAtom(): stv mean value: " << mean <<std::endl;
542  char *comma = strchr(stv + 2, ',');
543  std::cout << "getAtom(): stv comma:" << comma <<std::endl;
544  double count = atof(comma + 1);
545  std::cout << "getAtom(): stv count OK" <<std::endl;
546  SimpleTruthValue nstv(mean, count);
547  atom_ptr->setTruthValue(nstv);
548  std::cout << "getAtom(): truth value restored" <<std::endl;
549 
550  // XXX we should explicitly add the atom to the TLB
551 
552  return atom_ptr;
553 }
554 
virtual count_t getCount() const =0
a TruthValue that stores a mean and the number of observations (strength and confidence) ...
std::vector< Handle > HandleSeq
a list of handles
Definition: Handle.h:246
bool isNode(Type t)
Definition: ClassServer.h:182
lti_t getLTI() const
return LTI property value
void setTruthValue(TruthValuePtr)
Sets the TruthValue object of the atom.
Definition: Atom.cc:81
ClassServer & classserver(ClassServerFactory *=ClassServer::createInstance)
Definition: ClassServer.cc:159
void setAttentionValue(AttentionValuePtr)
Sets the AttentionValue object of the atom.
Definition: Atom.cc:163
virtual void storeAtom(Handle)
unsigned long UUID
UUID == Universally Unique Identifier.
Definition: Handle.h:46
const String handle_schema
virtual Node * getNode(Type, const char *) const
const String attribute_schema
virtual Atom * getAtom(Handle) const
UUID value(void) const
Definition: Handle.h:85
vlti_t getVLTI() const
return VLTI property value
unsigned short Type
type of Atoms, represented as short integer (16 bits)
Definition: types.h:40
virtual Link * getLink(Type, const std::vector< Handle > &) const
virtual strength_t getMean() const =0
sti_t getSTI() const
return STI property value
virtual std::vector< Handle > getIncomingSet(Handle) const
const int TIMEOUT
const int BUFF_SIZE