Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Fixed a minor denkfehler in the "bump <1ms runtime to 1ms" logic. Changed g.json.gc to an array (lower memory and better performance for what we use it for). |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | json-multitag-test | json |
| Files: | files | file ages | folders |
| SHA1: |
19276984bde340079137e0ddb8498c44 |
| User & Date: | stephan 2011-10-07 02:58:47.515 |
Context
|
2011-10-07
| ||
| 03:09 | fixed whoami requests in demo apps to notice when the user has been logged out (and logs him in with the new auth token). ... (check-in: ccc90734e0 user: stephan tags: json-multitag-test, json) | |
| 02:58 | Fixed a minor denkfehler in the "bump <1ms runtime to 1ms" logic. Changed g.json.gc to an array (lower memory and better performance for what we use it for). ... (check-in: 19276984bd user: stephan tags: json-multitag-test, json) | |
| 02:16 | merged in trunk [4b0f813b8c]. ... (check-in: 39d9f83781 user: stephan tags: json-multitag-test, json) | |
Changes
Changes to ajax/index.html.
| ︙ | ︙ | |||
235 236 237 238 239 240 241 242 243 244 245 246 247 248 |
<input type='button' value='user/list' onclick='TheApp.cgi.sendCommand("/json/user/list")' />
<input type='button' value='user/get' onclick='TheApp.cgi.sendCommand("/json/user/get?name=anonymous")' />
<input type='button' value='resultCodes' onclick='TheApp.cgi.sendCommand("/json/resultCodes")' />
<input type='button' value='tag/list' onclick='TheApp.cgi.sendCommand("/json/tag/list?includeTickets=false&raw=false")' />
<input type='button' value='tag/list/json' onclick='TheApp.cgi.sendCommand("/json/tag/list/json?raw=false")' />
<input type='button' value='tag/add'
onclick='TheApp.cgi.sendCommand("/json/tag/add",{name:"json-add-tag-test",checkin:"json",value:"tag test",propagate:false,raw:false})' />
<!-- not yet ready...
<input type='button' value='artifact/XYZ' onclick='TheApp.cgi.sendCommand("/json/artifact?uuid=json")' />
-->
<!--
<input type='button' value='get whiki' onclick='TheApp.cgi.getPages("whiki")' />
<input type='button' value='get more' onclick='TheApp.cgi.getPages("HelloWorld/WhikiNews")' />
| > > > > | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
<input type='button' value='user/list' onclick='TheApp.cgi.sendCommand("/json/user/list")' />
<input type='button' value='user/get' onclick='TheApp.cgi.sendCommand("/json/user/get?name=anonymous")' />
<input type='button' value='resultCodes' onclick='TheApp.cgi.sendCommand("/json/resultCodes")' />
<input type='button' value='tag/list' onclick='TheApp.cgi.sendCommand("/json/tag/list?includeTickets=false&raw=false")' />
<input type='button' value='tag/list/json' onclick='TheApp.cgi.sendCommand("/json/tag/list/json?raw=false")' />
<input type='button' value='tag/add'
onclick='TheApp.cgi.sendCommand("/json/tag/add",{name:"json-add-tag-test",checkin:"json",value:"tag test",propagate:false,raw:false})' />
<input type='button' value='tag/cancel'
onclick='TheApp.cgi.sendCommand("/json/tag/cancel",{name:"json-add-tag-test",checkin:"json",raw:false})' />
<input type='button' value='tag/find'
onclick='TheApp.cgi.sendCommand("/json/tag/find",{name:"json",type:"*",raw:false,limit:5})' />
<!-- not yet ready...
<input type='button' value='artifact/XYZ' onclick='TheApp.cgi.sendCommand("/json/artifact?uuid=json")' />
-->
<!--
<input type='button' value='get whiki' onclick='TheApp.cgi.getPages("whiki")' />
<input type='button' value='get more' onclick='TheApp.cgi.getPages("HelloWorld/WhikiNews")' />
|
| ︙ | ︙ |
Changes to src/json.c.
| ︙ | ︙ | |||
338 339 340 341 342 343 344 |
static char buf[BufSize] = {'F','O','S','S','I','L','-',0};
assert((code >= 1000) && (code <= 9999) && "Invalid Fossil/JSON code.");
sprintf(buf+7,"%04d", code);
return buf;
}
/*
| | < < | | | | | | > | | > | 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 |
static char buf[BufSize] = {'F','O','S','S','I','L','-',0};
assert((code >= 1000) && (code <= 9999) && "Invalid Fossil/JSON code.");
sprintf(buf+7,"%04d", code);
return buf;
}
/*
** Adds v to the API-internal cleanup mechanism. key is ingored
** (legacy). If freeOnError is true then v is passed to
** cson_value_free() if the key cannot be inserted, otherweise
** ownership of v is not changed on error. Failure to insert an item
** may be caused by any of the following:
**
** - Allocation error.
** - g.json.gc.a is NULL
** - key is NULL or empty.
**
** Returns 0 on success.
**
** On success, ownership of v is transfered to (or shared with)
** g.json.gc, and v will be valid until that object is cleaned up or
** some internal code incorrectly removes it from the gc (which we
** never do).
*/
int json_gc_add( char const * key, cson_value * v, char freeOnError ){
int const rc = cson_array_append( g.json.gc.a, v );
assert( NULL != g.json.gc.a );
if( (0 != rc) && freeOnError ){
cson_value_free( v );
}
assert( (0==rc) && "Adding item to GC failed." );
return rc;
}
/*
** Returns the value of json_rc_cstr(code) as a new JSON
** string, which is owned by the caller and must eventually
|
| ︙ | ︙ | |||
779 780 781 782 783 784 785 |
cson_value * v;
assert( (NULL == g.json.gc.v) && "cgi_json_bootstrap() was called twice!" );
/* g.json.gc is our "garbage collector" - where we put JSON values
which need a long lifetime but don't have a logical parent to put
them in.
*/
| | | | 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 |
cson_value * v;
assert( (NULL == g.json.gc.v) && "cgi_json_bootstrap() was called twice!" );
/* g.json.gc is our "garbage collector" - where we put JSON values
which need a long lifetime but don't have a logical parent to put
them in.
*/
v = cson_value_new_array();
g.json.gc.v = v;
g.json.gc.a = cson_value_get_array(v);
/*
g.json.param holds the JSONized counterpart of fossil's
cgi_parameter_xxx() family of data. We store them as JSON, as
opposed to using fossil's data directly, because we can retain
full type information for data this way (as opposed to it always
being of type string).
|
| ︙ | ︙ | |||
1410 1411 1412 1413 1414 1415 1416 |
just before they end).
*/
double span;
span = END_TIMER;
/* i'm actually seeing sub-ms runtimes in some tests, but a time of
0 is "just wrong", so we'll bump that up to 1ms.
*/
| | | 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 |
just before they end).
*/
double span;
span = END_TIMER;
/* i'm actually seeing sub-ms runtimes in some tests, but a time of
0 is "just wrong", so we'll bump that up to 1ms.
*/
cson_object_set(o,"procTimeMs", cson_value_new_integer((cson_int_t)((span>1.0)?span:1)));
}
if(g.json.warnings.v){
tmp = g.json.warnings.v;
SET("warnings");
}
/* Only add the payload to SUCCESS responses. Else delete it. */
|
| ︙ | ︙ |
Changes to src/json_tag.c.
| ︙ | ︙ | |||
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
}
if(!zCheckin || !*zCheckin){
json_set_err(FSL_JSON_E_MISSING_ARGS,
"'checkin' parameter is missing.");
return NULL;
}
}
db_begin_transaction();
tag_add_artifact(zPrefix, zName, zCheckin, NULL, 0, 0, 0);
db_end_transaction(0);
return NULL;
}
/*
** Impl of /json/tag/find.
*/
static cson_value * json_tag_find(){
cson_value * payV = NULL;
cson_object * pay = NULL;
cson_value * listV = NULL;
cson_array * list = NULL;
char const * zName = NULL;
char const * zType = NULL;
char fRaw = 0;
Stmt q = empty_Stmt;
int limit = 0;
int tagid = 0;
if( !g.perm.Read ){
json_set_err(FSL_JSON_E_DENIED,
| > > > > | 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
}
if(!zCheckin || !*zCheckin){
json_set_err(FSL_JSON_E_MISSING_ARGS,
"'checkin' parameter is missing.");
return NULL;
}
}
/* FIXME?: verify that the tag is currently active. We have no real
error case unless we do that.
*/
db_begin_transaction();
tag_add_artifact(zPrefix, zName, zCheckin, NULL, 0, 0, 0);
db_end_transaction(0);
return NULL;
}
/*
** Impl of /json/tag/find.
*/
static cson_value * json_tag_find(){
cson_value * payV = NULL;
cson_object * pay = NULL;
cson_value * listV = NULL;
cson_array * list = NULL;
char const * zName = NULL;
char const * zType = NULL;
char const * zType2 = NULL;
char fRaw = 0;
Stmt q = empty_Stmt;
int limit = 0;
int tagid = 0;
if( !g.perm.Read ){
json_set_err(FSL_JSON_E_DENIED,
|
| ︙ | ︙ | |||
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
"'name' parameter is missing.");
return NULL;
}
}
zType = json_find_option_cstr("type",NULL,"t");
if(!zType || !*zType){
zType = "*";
}
limit = json_find_option_int("limit",NULL,"n",0);
fRaw = json_find_option_bool("raw",NULL,NULL,0);
tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='%s' || %Q",
fRaw ? "" : "sym-",
zName);
payV = cson_value_new_object();
pay = cson_value_get_object(payV);
cson_object_set(pay, "name", json_new_string(zName));
cson_object_set(pay, "raw", cson_value_new_bool(fRaw));
| > > > > > > > > | | 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
"'name' parameter is missing.");
return NULL;
}
}
zType = json_find_option_cstr("type",NULL,"t");
if(!zType || !*zType){
zType = "*";
zType2 = zType;
}else{
switch(*zType){
case 'c': zType = "ci"; zType2 = "checkin"; break;
case 'e': zType = "e"; zType2 = "event"; break;
case 'w': zType = "w"; zType2 = "wiki"; break;
case 't': zType = "t"; zType2 = "ticket"; break;
}
}
limit = json_find_option_int("limit",NULL,"n",0);
fRaw = json_find_option_bool("raw",NULL,NULL,0);
tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='%s' || %Q",
fRaw ? "" : "sym-",
zName);
payV = cson_value_new_object();
pay = cson_value_get_object(payV);
cson_object_set(pay, "name", json_new_string(zName));
cson_object_set(pay, "raw", cson_value_new_bool(fRaw));
cson_object_set(pay, "type", json_new_string(zType2));
cson_object_set(pay, "limit", json_new_int(limit));
#if 1
if( tagid<=0 ){
cson_object_set(pay,"artifacts", cson_value_null());
json_warn(FSL_JSON_W_TAG_NOT_FOUND, "Tag not found.");
return payV;
|
| ︙ | ︙ | |||
359 360 361 362 363 364 365 366 367 368 369 370 371 372 |
int const rid = name_to_rid(zCheckin);
if(0==rid){
json_set_err(FSL_JSON_E_UNRESOLVED_UUID,
"Could not find artifact for checkin [%s].",
zCheckin);
goto error;
}
db_prepare(&q,
"SELECT tagname, value FROM tagxref, tag"
" WHERE tagxref.rid=%d AND tagxref.tagid=tag.tagid"
" AND tagtype>%d"
" ORDER BY tagname",
rid,
fRaw ? -1 : 0
| > | 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 |
int const rid = name_to_rid(zCheckin);
if(0==rid){
json_set_err(FSL_JSON_E_UNRESOLVED_UUID,
"Could not find artifact for checkin [%s].",
zCheckin);
goto error;
}
cson_object_set(pay, "checkin", json_new_string(zCheckin));
db_prepare(&q,
"SELECT tagname, value FROM tagxref, tag"
" WHERE tagxref.rid=%d AND tagxref.tagid=tag.tagid"
" AND tagtype>%d"
" ORDER BY tagname",
rid,
fRaw ? -1 : 0
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
188 189 190 191 192 193 194 |
unsigned char dispatchDepth /* Tells JSON command dispatching
which argument we are currently
working on. For this purpose, arg#0
is the "json" path/CLI arg.
*/;
struct { /* "garbage collector" */
cson_value * v;
| | | 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
unsigned char dispatchDepth /* Tells JSON command dispatching
which argument we are currently
working on. For this purpose, arg#0
is the "json" path/CLI arg.
*/;
struct { /* "garbage collector" */
cson_value * v;
cson_array * a;
} gc;
struct { /* JSON POST data. */
cson_value * v;
cson_array * a;
int offset; /* Tells us which PATH_INFO/CLI args
part holds the "json" command, so
that we can account for sub-repos
|
| ︙ | ︙ |