/* * util_str2recno -- * Convert a string to a record number. */ int util_str2recno(WT_SESSION *session, const char *p, uint64_t *recnop) { uint64_t recno; char *endptr; /* * strtouq takes lots of things like hex values, signs and so on and so * forth -- none of them are OK with us. Check the string starts with * digit, that turns off the special processing. */ if (!isdigit(p[0])) goto format; errno = 0; recno = __wt_strtouq(p, &endptr, 0); if (recno == ULLONG_MAX && errno == ERANGE) return ( util_err(session, ERANGE, "%s: invalid record number", p)); if (endptr[0] != '\0') format: return ( util_err(session, EINVAL, "%s: invalid record number", p)); *recnop = recno; return (0); }
/* * json_data -- * Parse the data portion of the JSON input, and insert all * values. */ static int json_data(WT_SESSION *session, JSON_INPUT_STATE *ins, CONFIG_LIST *clp, uint32_t flags) { WT_CURSOR *cursor; WT_DECL_RET; char config[64], *endp, *uri; const char *keyformat; int isrec, nfield, nkeys, toktype, tret; size_t keystrlen; ssize_t gotnolen; uint64_t gotno, recno; cursor = NULL; uri = NULL; /* Reorder and check the list. */ if ((ret = config_reorder(clp->list)) != 0) goto err; /* Update config based on command-line configuration. */ if ((ret = config_update(session, clp->list)) != 0) goto err; /* Create the items collected. */ if ((ret = config_exec(session, clp->list)) != 0) goto err; uri = clp->list[0]; (void)snprintf(config, sizeof(config), "dump=json%s%s", LF_ISSET(LOAD_JSON_APPEND) ? ",append" : "", LF_ISSET(LOAD_JSON_NO_OVERWRITE) ? ",overwrite=false" : ""); if ((ret = session->open_cursor( session, uri, NULL, config, &cursor)) != 0) { ret = util_err(ret, "%s: session.open", uri); goto err; } keyformat = cursor->key_format; isrec = (strcmp(keyformat, "r") == 0); for (nkeys = 0; *keyformat; keyformat++) if (!isdigit(*keyformat)) nkeys++; recno = 0; while (json_peek(session, ins) == '{') { nfield = 0; JSON_EXPECT(session, ins, '{'); if (ins->kvraw == NULL) { if ((ins->kvraw = (char *)malloc(1)) == NULL) { ret = util_err(errno, NULL); goto err; } } ins->kvraw[0] = '\0'; ins->kvrawstart = JSON_INPUT_POS(ins); keystrlen = 0; while (json_peek(session, ins) == 's') { JSON_EXPECT(session, ins, 's'); JSON_EXPECT(session, ins, ':'); toktype = json_peek(session, ins); JSON_EXPECT(session, ins, toktype); if (isrec && nfield == 0) { /* Verify the dump has recnos in order. */ recno++; gotno = __wt_strtouq(ins->tokstart, &endp, 0); gotnolen = (endp - ins->tokstart); if (recno != gotno || ins->toklen != (size_t)gotnolen) { ret = util_err(0, "%s: recno out of order", uri); goto err; } } if (++nfield == nkeys) { size_t curpos = JSON_INPUT_POS(ins); if ((ret = json_kvraw_append(ins, (char *)ins->line.mem + ins->kvrawstart, curpos - ins->kvrawstart)) != 0) goto err; ins->kvrawstart = curpos; keystrlen = strlen(ins->kvraw); } if (json_peek(session, ins) != ',') break; JSON_EXPECT(session, ins, ','); if (json_peek(session, ins) != 's') goto err; } if (json_kvraw_append(ins, ins->line.mem, JSON_INPUT_POS(ins))) goto err; ins->kvraw[keystrlen] = '\0'; if (!LF_ISSET(LOAD_JSON_APPEND)) cursor->set_key(cursor, ins->kvraw); /* skip over inserted space and comma */ cursor->set_value(cursor, &ins->kvraw[keystrlen+2]); if ((ret = cursor->insert(cursor)) != 0) { ret = util_err(ret, "%s: cursor.insert", uri); goto err; } JSON_EXPECT(session, ins, '}'); if (json_peek(session, ins) != ',') break; JSON_EXPECT(session, ins, ','); if (json_peek(session, ins) != '{') goto err; } if (0) { err: if (ret == 0) ret = EINVAL; } /* * Technically, we don't have to close the cursor because the session * handle will do it for us, but I'd like to see the flush to disk and * the close succeed, it's better to fail early when loading files. */ if (cursor != NULL && (tret = cursor->close(cursor)) != 0) { tret = util_err(tret, "%s: cursor.close", uri); if (ret == 0) ret = tret; } if (ret == 0) ret = util_flush(session, uri); return (ret); }