00001 #define TRACE_NAME "XSBAgent"
00002 #include "XSBAgent.h"
00003
00004 #include "XSBQuery.h"
00005 #include "FlowManager.h"
00006 #include "XSBPool.h"
00007
00008 #include <stdlib.h>
00009 #include <fstream>
00010 #include <sstream>
00011 #include <cstdio>
00012
00013
00015
00016
00017
00019
00020 static void ensure_file(const char* filename,
00021 const char* text)
00022 {
00023 std::ifstream in(filename);
00024
00025 if (in.good()) {
00026 const char *p = text;
00027 while (true) {
00028 char c;
00029 in.get(c);
00030 if (in.eof()) { c = '\0'; }
00031 if (*p != c) {
00032 TRACE "File " << filename << " has the wrong char ("
00033 << *p << " != " << c << ") at position "
00034 << (p-text) << "; correcting." << endl;
00035 break;
00036 }
00037 if (*p == '\0') return;
00038 ++p;
00039 }
00040 }
00041
00042 std::ofstream out(filename);
00043 out << text;
00044 }
00045
00046 static void write_c_support()
00047 {
00048 ensure_file("/tmp/blindfold_xsb_support.c",
00049 "#include <stdio.h>\n"
00050 "#define TRUE 1\n"
00051 "\n"
00052 "extern int blindfold_xsb_status;\n"
00053 "int blindfold_xsb_status = -1;\n"
00054 "\n"
00055 "void set_status_c(int status)\n"
00056 "{\n"
00057 " // We DONT need to do a high-water thing, because XSB will\n"
00058 " // not call this again during backtracking.\n"
00059 " // if (status > blindfold_xsb_status) \n"
00060 " blindfold_xsb_status = status;\n"
00061 " // printf(\"status reported as: %d\\n\", status);\n"
00062 "}\n"
00063 "\n"
00064 "void get_status_c(int* ii)\n"
00065 "{\n"
00066 " *ii = blindfold_xsb_status;\n"
00067 " // blindfold_xsb_status = -1;\n"
00068 "}\n");
00069
00070 ensure_file("/tmp/blindfold_xsb_support.H",
00071 "%\n"
00072 " \n"
00073 ":- foreign_pred set_status(+a) from\n"
00074 " set_status_c(a:int):void.\n"
00075 "\n"
00076 ":- foreign_pred get_status(-a) from\n"
00077 " get_status_c(a:intptr):void.\n");
00078 }
00079
00080 XSBAgent::XSBAgent()
00081 : predicateCounter(0),
00082 currentQuery(0)
00083 {
00084 out = FlowManager::main.streamThrough("x-shell:", *this, true);
00085 write_c_support();
00086 if (TRACING) {
00087 *out << "cd /tmp; xsb -e \"['/tmp/blindfold_xsb_support']. put(5).\";echo '~'\n";
00088 } else {
00089 *out << "cd /tmp; xsb --nobanner --quietload --noprompt -e \"['/tmp/blindfold_xsb_support']. put(5).\";echo '~'\n";
00090 }
00091 waitingForAck = true;
00092 while (waitingForAck) FlowManager::main.run();
00093 }
00094
00095 #if 0
00096
00097 XSBAgent::XSBAgent(const XSBAgent& other)
00098 {
00099 NOT_IMPLEMENTED
00100 }
00101
00102 const XSBAgent& XSBAgent::operator=(const XSBAgent& other)
00103 {
00104 NOT_IMPLEMENTED
00105 }
00106
00107 bool XSBAgent::operator==(const XSBAgent& other) const
00108 {
00109 NOT_IMPLEMENTED
00110 }
00111
00112 bool XSBAgent::operator<(const XSBAgent& other) const
00113 {
00114 NOT_IMPLEMENTED
00115 }
00116
00117 size_t XSBAgent::hash() const
00118 {
00119 NOT_IMPLEMENTED
00120 }
00121
00122 ostream& XSBAgent::print_to(ostream& stream) const
00123 {
00124 NOT_IMPLEMENTED
00125 }
00126
00127 #endif
00128
00129 XSBAgent::~XSBAgent()
00130 {
00131
00132 }
00133
00135
00136
00137
00139
00140
00142
00143
00144
00146
00147 QueryablePool* XSBAgent::newQueryablePool(VariableScope* scope = 0)
00148 {
00149 return new XSBPool(*this, scope);
00150 }
00151
00152
00153 #if 0
00154 Query* XSBAgent::getQuery(TripleSource* pattern, TripleSource* dataset)
00155 {
00156 XSBQuery* m = new XSBQuery(this, pattern, dataset);
00157 currentQueryer = m;
00158 FlowManager::main.run();
00159 return m;
00160 }
00161 #endif
00162
00163 std::ostream* XSBAgent::getFile(char** fileNameBuffer)
00164 {
00165 *fileNameBuffer = strdup("/tmp/blindfold_XXXXXX");
00166 int fd = mkstemp(*fileNameBuffer);
00167 assert(fd >= 0);
00168 return new std::fstream(fd);
00169 }
00170
00171 std::string XSBAgent::getNewPredicate()
00172 {
00173 #if 0
00174 std::string result;
00175 {
00176 std::ostringstream ss(result);
00177 ss << "auto" << predicateCounter++;
00178 }
00179 std::cout << "Generated name " << result << "\n";
00180 return result;
00181 #endif
00182 char buf[80];
00183 sprintf(buf, "auto%02d", predicateCounter++);
00184 return std::string(buf);
00185 }
00186
00187
00188
00189 void XSBAgent::write(const void* byteBuffer, size_t numBytes)
00190 {
00191 char* end;
00192 if (waitingForAck) {
00193 TRACE "XSB waiting for ACK or NACK" << endl;
00194
00195
00196 end = static_cast<char*>(memchr(byteBuffer, 5, numBytes));
00197 if (end) {
00198 waitingForAck = false;
00199 TRACE "XSB is working." << endl;
00200 FlowManager::main.returnFromRun();
00201 return;
00202 }
00203
00204 end = static_cast<char*>(memchr(byteBuffer, 126, numBytes));
00205 if (end) {
00206 std::cerr << "Unable to run 'xsb'. It must be in your path." << endl;
00207 exit(2);
00208 }
00209
00210 TRACE "...not yet. Hmmm." << endl;
00211 return;
00212 }
00213
00214 TRACE "XSB Output " << numBytes << " chars\n";
00215 buffer.write(byteBuffer, numBytes);
00216
00217
00218 end = static_cast<char*>(memchr(buffer.peek(), 4, buffer.size()));
00219 if (!end) return;
00220 *end = '\0';
00221
00222 char* start = static_cast<char*>(memchr(buffer.peek(), 1, buffer.size()));
00223 TRACE "Parsing buffer: *****" << start << "*****\n";
00224 assert(start);
00225 start++;
00226
00227 char* delim;
00228 while (*start) {
00229 TRACE "trying to convert \"" << start << "\"\n";
00230 long int value = strtol(start, &delim, 10);
00231 if (delim != start) {
00232 TRACE "got a value! (" << value << ")\n";
00233 currentQuery->handleValue(value);
00234 }
00235 start = delim+1;
00236 }
00237
00238 currentQuery->handleValue(-1);
00239 buffer.skip(end-static_cast<char*>(buffer.peek()));
00240
00241
00242 FlowManager::main.returnFromRun();
00243 }
00244
00245 void XSBAgent::shutdown() {
00246 *out << "halt.\n";
00247 FlowManager::main.runPending();
00248
00249
00250 }
00251
00253
00254
00255
00257
00258 void XSBAgent::sync() {
00259 std::list<XSBPool*>::iterator i;
00260 for (i=pools.begin(); i != pools.end(); ++i) {
00261 (*i)->sync();
00262 }
00263 }
00264 #undef TRACE_NAME