1 #include "BlackBoxRuntime.hpp"
2 #include <mysql++/mysql++.h>
4 BlackBoxCache
* gBlackBoxCache
= NULL
;
7 BBArun_wchar_to_UTF8(const wchar_t *str
)
10 const wchar_t* p
= str
;
17 #ifndef WCHAR_T_IS_32BIT
21 #ifndef WCHAR_T_IS_32BIT
28 char* newData
= (char*)malloc(len
+ 1);
38 *np
++ = (char)(0xC0 | ((c
>> 6) & 0x1F));
39 *np
++ = (char)(0x80 | (c
& 0x3F));
41 #ifndef WCHAR_T_CONSTANT_WIDTH
42 else if ((c
& 0xFC00) == 0xD800)
44 uint16_t u
= ((c
>> 6) & 0xF) + 1;
45 *np
++ = 0xF0 | ((u
>> 2) & 0x7);
46 *np
++ = 0x80 | ((u
<< 4) & 0x30) | ((c
>> 2) & 0xF);
48 *np
++ = 0x80 | ((c
<< 4) & 0x30) | ((c2
>> 6) & 0xF);
49 *np
++ = 0x80 | (c2
& 0x3F);
53 #if defined(WCHAR_T_CONSTANT_WIDTH) && !defined(WCHAR_T_IS_32BIT)
57 *np
++ = (char)(0xD0 | ((c
>> 12) & 0xF));
58 *np
++ = (char)(0x80 | ((c
>> 6) & 0x3F));
59 *np
++ = (char)(0x80 | (c
& 0x3F));
61 #if defined(WCHAR_T_CONSTANT_WIDTH) && !defined(WCHAR_T_IS_32BIT)
64 *np
++ = (char)(0xF0 | ((c
>> 18) & 0x7));
65 *np
++ = (char)(0x80 | ((c
>> 12) & 0x3F));
66 *np
++ = (char)(0x80 | ((c
>> 6) & 0x3F));
67 *np
++ = (char)(0x80 | (c
& 0x3F));
76 class SQLModelPersister
77 : public BlackBoxPersistBase
81 : mConn(mysqlpp::use_exceptions
), mReady(false)
83 const char* db
= getenv("BLABOC_DB");
86 printf("Missing BLABOC_DB. Not creating persister.\n");
89 const char* host
= getenv("BLABOC_HOST");
92 printf("Missing BLABOC_HOST. Not creating persister.\n");
95 const char* user
= getenv("BLABOC_USER");
98 printf("Missing BLABOC_USER. Not creating persister.\n");
101 const char* pass
= getenv("BLABOC_PASSWORD");
104 printf("Missing BLABOC_PASSWORD. Not creating persister.\n");
110 mConn
.connect(db
, host
, user
, pass
);
113 catch (std::exception
& e
)
115 printf("Error connecting to database: %s. Not creating persister.\n",
125 saveState(const char* aURL
, const std::string
& aData
)
130 // Figure out if we need to update or insert...
131 mysqlpp::Query
query(mConn
.query());
133 query
<< "SELECT COUNT(*) FROM black_box_state WHERE url=\""
134 << mysqlpp::escape
<< aURL
<< "\"";
138 mysqlpp::Result res
= query
.store();
139 unsigned int count
= res
.at(0)[(unsigned int)0];
143 query
<< "INSERT INTO black_box_state (url,data) VALUES (\""
144 << mysqlpp::escape
<< aURL
<< "\", \""
145 << mysqlpp::escape
<< aData
<< "\")";
150 query
<< "UPDATE black_box_state SET data=\""
151 << mysqlpp::escape
<< aData
<< "\" WHERE url=\""
152 << mysqlpp::escape
<< aURL
<< "\"";
156 catch (std::exception
& e
)
158 printf("Exception saving state: %s\n", e
.what());
163 restoreState(const char* aURL
, std::string
& aData
)
171 mysqlpp::Query
query(mConn
.query());
172 query
<< "SELECT data FROM black_box_state WHERE url=\""
173 << mysqlpp::escape
<< aURL
<< "\"";
177 mysqlpp::Result res
= query
.store();
183 mysqlpp::ColData col
= res
.at(0)["data"];
184 aData
.assign(col
.data(), col
.size());
186 catch (std::exception
& e
)
188 printf("Exception restoring state: %s\n", e
.what());
194 mysqlpp::Connection mConn
;
198 MixedModelBase::MixedModelBase()
199 : mPersister(new SQLModelPersister()),
200 VARIABLES(NULL
), INPUTS(NULL
), OUTPUTS(NULL
),
201 CONSTANTS(NULL
), TMPINPUTS(NULL
), TMPOUTPUTS(NULL
),
202 blackBoxes(NULL
), blackBoxNames(NULL
),
203 BACKVARIABLES(NULL
), BACKOUTPUTS(NULL
)
207 MixedModelBase::~MixedModelBase()
211 if (BACKVARIABLES
!= NULL
)
212 delete [] BACKVARIABLES
;
214 if (BACKOUTPUTS
!= NULL
)
215 delete [] BACKOUTPUTS
;
217 if (blackBoxes
!= NULL
)
221 if (gBlackBoxCache
== NULL
)
223 for (i
= 0; i
< nBlackBoxes
; i
++)
224 if (blackBoxes
[i
] != NULL
)
226 blackBoxes
[i
]->Serialise(state
);
227 if (state
.size() != 0)
228 mPersister
->saveState(blackBoxNames
[i
].c_str(), state
);
229 delete blackBoxes
[i
];
232 delete [] blackBoxes
;
237 if (blackBoxNames
!= NULL
)
238 delete [] blackBoxNames
;
242 MixedModelBase::runConverged()
244 if (mConvergeSteps
++ > 10)
246 printf("Warning: It took more than 10 steps for the black-boxes to "
247 "converge within tolerance. Quitting early.\n");
251 uint32_t i
, l
= countOtherVariables();
255 printf("Computing RSS with...\n");
256 for (i
= 0; i
< countOtherVariables(); i
++)
257 printf(" * OTHERVARIABLES[%u] = %g\n", i
, VARIABLES
[i
]);
258 for (i
= 0; i
< countOutputVariables(); i
++)
259 printf(" * OUTPUTS[%u] = %g\n", i
, OUTPUTS
[i
]);
260 printf("Listing complete.\n");
263 for (i
= 0; i
< l
; i
++)
265 t
= VARIABLES
[i
] - BACKVARIABLES
[i
];
268 l
= countOutputVariables();
269 for (i
= 0; i
< l
; i
++)
271 t
= OUTPUTS
[i
] - BACKOUTPUTS
[i
];
276 printf("Step %u: RSS = %g\n", mConvergeSteps
, RSS
);
286 MixedModelBase::createBlackBox
296 BlackBoxModelBase
* cachedModel
= gBlackBoxCache
->FindModelInCache(URI
);
297 if (cachedModel
!= NULL
)
299 blackBoxes
[aIdx
] = cachedModel
;
301 char* utf8uri
= BBArun_wchar_to_UTF8(URI
);
302 blackBoxNames
[aIdx
] = utf8uri
;
309 const wchar_t* offs
= wcschr(URI
, '#');
310 std::wstring name
, id
;
314 name
= std::wstring(URI
, offs
- URI
);
319 std::map
<std::wstring
, BlackBoxModelFactory
*>::iterator i
320 = blackBoxFactories().find(name
);
322 if (i
== blackBoxFactories().end())
324 printf("Warning: Cannot create a black box with URI base %S because "
325 "no factory could be found.\n",
327 throw std::exception();
330 blackBoxes
[aIdx
] = (*i
).second
->createBlackBoxModel(id
, inputs
, outputs
);
331 char* utf8uri
= BBArun_wchar_to_UTF8(URI
);
332 blackBoxNames
[aIdx
] = utf8uri
;
336 mPersister
->restoreState(blackBoxNames
[aIdx
].c_str(), data
);
338 blackBoxes
[aIdx
]->Deserialise(data
);
340 if (gBlackBoxCache
!= NULL
)
341 gBlackBoxCache
->CacheModel(URI
, blackBoxes
[aIdx
]);
344 std::map
<std::wstring
,BlackBoxModelFactory
*>* MixedModelBase::sBlackBoxFactories
= NULL
;
346 class StandardBlackBoxCache
347 : public BlackBoxCache
350 StandardBlackBoxCache()
354 ~StandardBlackBoxCache()
360 FindModelInCache(const std::wstring
& aURI
)
362 std::map
<std::wstring
, BlackBoxModelBase
*>::iterator i
= mModels
.find(aURI
);
364 if (i
== mModels
.end())
371 CacheModel(const std::wstring
& aURI
, BlackBoxModelBase
* aModel
)
373 mModels
.insert(std::pair
<std::wstring
, BlackBoxModelBase
*>(aURI
, aModel
));
377 SaveAllCachedModels()
379 std::map
<std::wstring
, BlackBoxModelBase
*>::iterator i
;
382 SQLModelPersister smp
;
384 for (i
= mModels
.begin(); i
!= mModels
.end(); i
++)
386 (*i
).second
->Serialise(state
);
387 if (state
.size() != 0)
389 char* utf8uri
= BBArun_wchar_to_UTF8((*i
).first
.c_str());
390 smp
.saveState(utf8uri
, state
);
399 std::map
<std::wstring
, BlackBoxModelBase
*>::iterator i
;
400 for (i
= mModels
.begin(); i
!= mModels
.end(); i
++)
405 std::map
<std::wstring
, BlackBoxModelBase
*> mModels
;
408 void setupStandardBlackBoxCache()
410 gBlackBoxCache
= new StandardBlackBoxCache();