if (find_arg(ua, "cache") > 0) {
return cloud_volumes_cmd(ua, cmd, "truncate cache");
}
-
- bmemset(&pr, 0, sizeof(pr));
/*
* Look for all Purged volumes that can be recycled, are enabled and
OutputWriter wt(ua->api_opts);
wt.start_group("header");
wt.get_output(
+ OT_START_OBJ,
OT_STRING, "name", my_name,
OT_STRING, "version", VERSION " (" BDATE ")",
OT_STRING, "uname", HOST_OS " " DISTNAME " " DISTVER,
OT_INT64, "debug", debug_level,
OT_INT, "trace", get_trace(),
OT_ALIST_STR, "tags", debug_get_tags_list(&tlist, debug_level_tags),
+ OT_END_OBJ,
OT_END);
ua->send_msg("%s", wt.end_group());
}
}
endeach_jcr(jcr);
+
+ } else if (ua->api > 1) { // We always return something in APIv2
+ ow.start_group("running");
+ ow.get_output(OT_START_ARRAY, OT_END);
}
njobs = 0; /* count the number of job really displayed */
if (!ua->api) {
ua->send_msg(_(" JobId Type Level Files Bytes Name Status\n"));
ua->send_msg(_("======================================================================\n"));
-
- } else if (ua->api > 1) {
- ua->send_msg(ow.start_group("running", false));
}
}
status = jcr->JobStatus;
STORE *w = wstore;
STORE *r = rstore;
JOB *j = jcr->job;
- ua->send_msg("%s", ow.get_output(OT_CLEAR,
- OT_START_OBJ,
- OT_INT32, "jobid", jcr->JobId,
- OT_JOBLEVEL,"level", jcr->getJobLevel(),
- OT_JOBTYPE, "type", jcr->getJobType(),
- OT_JOBSTATUS,"status", status,
- OT_STRING, "status_desc",msg,
- OT_STRING, "comment", jcr->comment,
- OT_SIZE, "jobbytes", jcr->JobBytes,
- OT_INT32, "jobfiles", jcr->JobFiles,
- OT_STRING, "job", jcr->Job,
- OT_STRING, "name", j?j->name():"",
- OT_STRING, "clientname",c?c->name():"",
- OT_STRING, "fileset", f?f->name():"",
- OT_STRING, "storage", w?w->name():"",
- OT_STRING, "rstorage", r?r->name():"",
- OT_UTIME, "schedtime", jcr->sched_time,
- OT_UTIME, "starttime", jcr->start_time,
- OT_INT32, "priority", jcr->JobPriority,
- OT_INT32, "errors", jcr->JobErrors,
- OT_END_OBJ,
- OT_END));
+ ow.get_output(OT_START_OBJ,
+ OT_INT32, "jobid", jcr->JobId,
+ OT_JOBLEVEL,"level", jcr->getJobLevel(),
+ OT_JOBTYPE, "type", jcr->getJobType(),
+ OT_JOBSTATUS,"status", status,
+ OT_STRING, "status_desc",msg,
+ OT_STRING, "comment", jcr->comment,
+ OT_SIZE, "jobbytes", jcr->JobBytes,
+ OT_INT32, "jobfiles", jcr->JobFiles,
+ OT_STRING, "job", jcr->Job,
+ OT_STRING, "name", j?j->name():"",
+ OT_STRING, "clientname",c?c->name():"",
+ OT_STRING, "fileset", f?f->name():"",
+ OT_STRING, "storage", w?w->name():"",
+ OT_STRING, "rstorage", r?r->name():"",
+ OT_UTIME, "schedtime", jcr->sched_time,
+ OT_UTIME, "starttime", jcr->start_time,
+ OT_INT32, "priority", jcr->JobPriority,
+ OT_INT32, "errors", jcr->JobErrors,
+ OT_END_OBJ,
+ OT_END);
} else {
char b1[50], b2[50], b3[50];
}
endeach_jcr(jcr);
+ if (ua->api > 1) {
+ ow.end_list();
+ char *p = ow.end_group();
+ ua->send_msg("%s", p);
+ }
+
if (njobs == 0) {
/* Note the following message is used in regress -- don't change */
ua->send_msg(_("No Jobs running.\n====\n"));
/* display a closing header */
if (!ua->api) {
ua->send_msg("====\n");
- } else if (ua->api > 1) {
- ua->send_msg(ow.end_group(false));
}
}
Dmsg0(200, "leave list_run_jobs()\n");
static void list_terminated_jobs(UAContext *ua)
{
- char dt[MAX_TIME_LENGTH], b1[30], b2[30];
+ char dt[MAX_TIME_LENGTH], b1[30], b2[30], *p;
char level[10];
+ bool add_sep=false;
OutputWriter ow(ua->api_opts);
+ if (ua->api > 1) {
+ ow.start_group("terminated");
+ p = ow.get_output(OT_START_ARRAY, OT_END);
+ ua->send_msg("%s", p);
+ }
+
if (last_jobs->empty()) {
- if (!ua->api) ua->send_msg(_("No Terminated Jobs.\n"));
+ if (!ua->api) {
+ ua->send_msg(_("No Terminated Jobs.\n"));
+ } else if (ua->api > 1) {
+ ow.get_output(OT_CLEAR, OT_END_ARRAY, OT_END);
+ p = ow.end_group();
+ ua->send_msg("%s", p);
+ }
return;
}
lock_last_jobs_list();
ua->send_msg(_("\nTerminated Jobs:\n"));
ua->send_msg(_(" JobId Level Files Bytes Status Finished Name \n"));
ua->send_msg(_("====================================================================\n"));
- } else if (ua->api > 1) {
- ua->send_msg(ow.start_group("terminated"));
}
foreach_dlist(je, last_jobs) {
char JobName[MAX_NAME_LENGTH];
} else if (ua->api > 1) {
ua->send_msg("%s",
ow.get_output(OT_CLEAR,
+ add_sep ? OT_SEP : OT_NOP,
OT_START_OBJ,
OT_INT32, "jobid", je->JobId,
OT_JOBLEVEL,"level", je->JobLevel,
OT_END_OBJ,
OT_END));
+ add_sep=true;
} else {
ua->send_msg(_("%6d %-7s %8s %10s %-7s %-8s %s\n"),
je->JobId,
if (!ua->api) {
ua->send_msg(_("\n"));
} else if (ua->api > 1) {
- ua->send_msg(ow.end_group(false));
+ ow.get_output(OT_CLEAR, OT_END_ARRAY, OT_END);
+ p = ow.end_group();
+ ua->send_msg("%s", p);
}
unlock_last_jobs_list();
}
}
Dmsg1(500, "processing: %s\n", res->res_collector.hdr.name);
render_collector_status(res->res_collector, buf);
- ua->send_msg(buf.c_str());
+ ua->send_msg("%s", buf.c_str());
};
UnlockRes();
if (!collname){
render_updcollector_status(buf);
- ua->send_msg(buf.c_str());
+ ua->send_msg("%s", buf.c_str());
}
Dmsg0(200, "leave list_collectors_status()\n");
}
POOLMEM *buf;
Dmsg1(200, "enter api_collectors_status() %s\n", NPRTB(collname));
- ow.start_group("collector_backends");
+ ow.start_group("collector");
+ ow.get_output(OT_START_OBJ, OT_END);
+ ow.start_list("collector_backends");
LockRes();
foreach_res(res, R_COLLECTOR) {
if (collname && !bstrcmp(collname, res->res_collector.hdr.name)){
api_render_collector_status(res->res_collector, ow);
};
UnlockRes();
- buf = ow.end_group();
+ ow.end_list();
if (!collname){
- ow.start_group("collector_update");
+ ow.get_output(OT_SEP, OT_LABEL, "collector_update", OT_END);
api_render_updcollector_status(ow);
- buf = ow.end_group();
}
- ua->send_msg(buf);
+ ow.get_output(OT_END_OBJ, OT_END);
+ buf = ow.end_group();
+ ua->send_msg("%s", buf);
Dmsg0(200, "leave api_collectors_status()\n");
};
}
}
}
-
wt.start_group("header");
wt.get_output(
+ OT_START_OBJ,
OT_STRING, "name", my_name,
OT_STRING, "version", VERSION " (" BDATE ")",
OT_STRING, "uname", HOST_OS " " DISTNAME " " DISTVER,
OT_PLUGINS, "plugins", b_plugin_list,
OT_INT, "pkiencryption", (int)me->pki_encrypt,
OT_INT, "pkisignature", (int)me->pki_sign,
- OT_STRING, "pkicipher", NPRTB(cipher),
- OT_STRING, "pkidigest", NPRTB(digest),
+ OT_STRING, "pkicipher", NPRTB(cipher),
+ OT_STRING, "pkidigest", NPRTB(digest),
OT_INT32, "fips", crypto_get_fips(),
OT_STRING, "crypto", crypto_get_version(),
OT_BOOL, "gpfs", GPFSLIB::enabled(),
+ OT_END_OBJ,
OT_END);
p = wt.end_group();
sendit(p, strlen(p), sp);
{
OutputWriter ow(sp->api_opts);
int sec, bps, brps, val;
+ bool add_sep=false;
char *p;
JCR *njcr;
/* API v1, edit with comma, space before the name, sometime ' ' as separator */
+ ow.start_group("running");
+ p = ow.get_output(OT_START_ARRAY, OT_END);
+ sendit(p, strlen(p), sp);
foreach_jcr(njcr) {
int vss = 0;
vss = 1;
}
#endif
- p = ow.get_output(OT_CLEAR, OT_START_OBJ, OT_END);
+ if (add_sep) {
+ p = ow.get_output(OT_CLEAR, OT_SEP, OT_START_OBJ, OT_END);
+
+ } else {
+ p = ow.get_output(OT_CLEAR, OT_START_OBJ, OT_END);
+ add_sep = true;
+ }
if (njcr->JobId == 0) {
val = (njcr->dir_bsock && njcr->dir_bsock->tls)?1:0;
ow.get_output(OT_UTIME, "DirectorConnected", (utime_t)njcr->start_time,
OT_INT, "DirTLS", val,
+ OT_END_OBJ,
OT_END);
} else {
ow.get_output(OT_INT32, "JobId", njcr->JobId,
OT_END);
}
+
sendit(p, strlen(p), sp);
if (njcr->JobId == 0) {
continue;
}
+
sec = time(NULL) - njcr->start_time;
if (sec <= 0) {
sec = 1;
bps = (int)(njcr->JobBytes / sec);
brps = (int)(njcr->ReadBytes / sec);
ow.get_output(OT_CLEAR,
+ OT_SEP, // We have started to display info
OT_INT32, "JobFiles", njcr->JobFiles,
OT_SIZE, "JobBytes", njcr->JobBytes,
OT_INT, "Bytes/sec", bps,
}
sendit(p, strlen(p), sp);
- ow.get_output(OT_CLEAR, OT_END);
+ ow.get_output(OT_CLEAR, OT_SEP, OT_END);
if (njcr->JobFiles > 0) {
njcr->lock();
sendit(p, strlen(p), sp);
}
endeach_jcr(njcr);
+
+ ow.get_output(OT_CLEAR, OT_END_ARRAY, OT_END);
+ p = ow.end_group();
+ sendit(p, strlen(p), sp);
}
static void list_running_jobs(STATUS_PKT *sp)
POOLMEM *buf;
Dmsg1(200, "enter api_collectors_status() %s\n", NPRTB(collname));
- ow.start_group("collector_backends");
+ ow.start_group("collector");
+ ow.get_output(OT_START_OBJ, OT_END);
+ ow.start_list("collector_backends");
LockRes();
foreach_res(res, R_COLLECTOR) {
if (collname && !bstrcmp(collname, res->res_collector.hdr.name)){
api_render_collector_status(res->res_collector, ow);
};
UnlockRes();
- buf = ow.end_group();
+ ow.end_list();
if (!collname){
- ow.start_group("collector_update");
+ ow.get_output(OT_SEP, OT_LABEL, "collector_update", OT_END);
api_render_updcollector_status(ow);
- buf = ow.end_group();
}
+ ow.get_output(OT_END_OBJ, OT_END);
+ buf = ow.end_group();
sendit(buf, strlen(buf), sp);
Dmsg0(200, "leave api_collectors_status()\n");
};
#include "guid_to_name.h"
#include "htable.h"
#include "sellist.h"
-#include "output.h"
#include "protos.h"
+#include "output.h"
#include "bget_msg.h"
#if BEEF
#include "bee_lib_dedup.h"
/* use new output (lowercase, no special char) */
#define OF_USE_NEW_OUTPUT 1
+#define OF_USE_QUOTES 2
+#define OF_USE_JSON 4
void OutputWriter::parse_options(const char *options)
{
nb=0;
switch(*p) {
+ case 'q':
+ flags |= OF_USE_QUOTES;
+ break;
+
+ case 'j':
+ flags |= OF_USE_QUOTES; // q
+ flags |= OF_USE_JSON; // j
+ flags |= OF_USE_NEW_OUTPUT; /* o lowercase and only isalpha */
+ set_separator(','); // S44
+ set_equal(':'); // e123
+ set_label(":"); // l
+ set_hash("{", "}");
+ set_table("[", "]");
+ set_object_separator('{', '}');
+ break;
+
case 'C':
flags = 0;
set_time_format(OW_DEFAULT_TIMEFORMAT);
set_separator(OW_DEFAULT_SEPARATOR);
+ set_equal(OW_DEFAULT_EQUAL);
+ set_hash(OW_DEFAULT_OPEN_HASH, OW_DEFAULT_CLOSE_HASH);
+ set_table(OW_DEFAULT_OPEN_TABLE, OW_DEFAULT_CLOSE_TABLE);
+ set_label(OW_DEFAULT_LABEL);
+ set_object_separator(0, 0);
break;
case 'S': /* object separator */
nb = nb*10 + (*(++p) - '0');
}
if (isascii(nb)) {
- set_object_separator((char) nb);
+ set_object_separator((char) nb, (char)nb);
}
break;
set_separator((char) nb);
}
break;
+ case 'e':
+ while(isdigit(*(p+1))) {
+ nb = nb*10 + (*(++p) - '0');
+ }
+ if (isascii(nb)) {
+ set_equal((char) nb);
+ }
+ break;
+ case 'l':
+ while(isdigit(*(p+1))) {
+ nb = nb*10 + (*(++p) - '0');
+ }
+ if (isascii(nb)) {
+ char ed1[2];
+ ed1[0] = (char) nb;
+ ed1[1] = 0;
+ set_label(ed1);
+ }
+ break;
default:
break;
}
}
}
-char *OutputWriter::get_options(char *dest)
+const char *OutputWriter::ow_quote_string(const char *str, POOLMEM *&b)
+{
+ if (flags & OF_USE_QUOTES) {
+ b = quote_string(b, str);
+ return b;
+ } else {
+ return str;
+ }
+}
+
+const char *OutputWriter::ow_quote_string(const char *str)
+{
+ return ow_quote_string(str, quote_buf);
+}
+
+const char *OutputWriter::ow_quote_string2(const char *str)
+{
+ return ow_quote_string(str, quote_buf2);
+}
+
+char *OutputWriter::get_options(char *dest, int len)
{
char ed1[50];
*dest = *ed1 = 0;
if (separator != OW_DEFAULT_SEPARATOR) {
snprintf(dest, 50, "s%d", (int)separator);
}
- if (object_separator) {
- snprintf(ed1, sizeof(ed1), "S%d", (int) object_separator);
- bstrncat(dest, ed1, sizeof(ed1));
+ if (object_separator[0]) {
+ snprintf(ed1, sizeof(ed1), "S%d", (int) object_separator[0]);
+ bstrncat(dest, ed1, len);
}
if (timeformat != OW_DEFAULT_TIMEFORMAT) {
snprintf(ed1, sizeof(ed1), "t%d", (int) timeformat);
- bstrncat(dest, ed1, sizeof(ed1));
+ bstrncat(dest, ed1, len);
+ }
+ if (equal != OW_DEFAULT_EQUAL) {
+ snprintf(ed1, sizeof(ed1), "e%d", (int) equal);
+ bstrncat(dest, ed1, len);
+ }
+ if (strcmp(label, OW_DEFAULT_LABEL) != 0) {
+ snprintf(ed1, sizeof(ed1), "l%d", (int)label[0]);
+ bstrncat(dest, ed1, len);
}
if (flags & OF_USE_NEW_OUTPUT) {
- bstrncat(dest, "o", 1);
+ bstrncat(dest, "o", len);
+ }
+ if (flags & OF_USE_QUOTES) {
+ bstrncat(dest, "q", len);
+ }
+ if (flags & OF_USE_JSON) {
+ bstrncat(dest, "j", len);
}
return dest;
}
void OutputWriter::get_buf(bool append)
{
if (!buf) {
+ quote_buf = get_pool_memory(PM_MESSAGE);
+ quote_buf2 = get_pool_memory(PM_MESSAGE);
buf = get_pool_memory(PM_MESSAGE);
- *buf = 0;
+ *quote_buf2 = *quote_buf = *buf = 0;
} else if (!append) {
*buf = 0;
char *OutputWriter::start_group(const char *name, bool append)
{
get_buf(append);
- pm_strcat(buf, name);
- pm_strcat(buf, ":\n");
- return buf;
+ return get_output(OT_START_OBJ, OT_LABEL, name, OT_END);
}
char *OutputWriter::end_group(bool append)
{
get_buf(append);
- pm_strcat(buf, "\n");
+ return get_output(OT_SEP,
+ OT_INT32, "error", error,
+ OT_STRING, "errmsg", NPRTB(errmsg),
+ OT_END_OBJ,
+ OT_NL,
+ OT_END);
+}
- return buf;
+char *OutputWriter::start_object(const char *name, bool append)
+{
+ get_buf(append);
+ return get_output(OT_LABEL, name, OT_START_OBJ, OT_END);
+}
+
+char *OutputWriter::end_object(bool append)
+{
+ get_buf(append);
+ return get_output(OT_END_OBJ, OT_END);
}
char *OutputWriter::start_list(const char *name, bool append)
{
get_buf(append);
- pm_strcat(buf, name);
- pm_strcat(buf, ": [\n");
+ if (use_json()) {
+ if (*buf) {
+ int l = strlen(buf);
+ if (buf[l - 1] != ',' && buf[l - 1] != ':' && buf[l - 1] != '{') {
+ pm_strcat(buf, ",");
+ }
+ }
+ pm_strcat(buf, ow_quote_string(name));
+ pm_strcat(buf, ":[");
+ need_separator = false;
+ will_need_separator = false;
+
+ } else {
+ pm_strcat(buf, name);
+ pm_strcat(buf, ": [\n");
+ }
return buf;
}
char *OutputWriter::end_list(bool append)
{
get_buf(append);
- pm_strcat(buf, "]\n");
+ if (use_json()) {
+ pm_strcat(buf, "]");
+
+ } else {
+ pm_strcat(buf, "]\n");
+ }
return buf;
}
return ret;
}
+bool OutputWriter::use_json()
+{
+ return flags & OF_USE_JSON;
+}
+
char *OutputWriter::get_output(va_list ap, POOLMEM **out, OutputType first)
{
char ed1[MAX_TIME_LENGTH];
char *s = NULL, *k = NULL;
alist *lst;
Plugin *plug;
+ POOLMEM *tmp3 = get_pool_memory(PM_FNAME);
POOLMEM *tmp2 = get_pool_memory(PM_FNAME);
POOLMEM *tmp = get_pool_memory(PM_FNAME);
OutputType val = first;
- *tmp2 = *tmp = 0;
+ *tmp3 = *tmp2 = *tmp = 0;
while (val != OT_END) {
/* Some arguments are not using a keyword */
switch (val) {
- case OT_END:
+ case OT_SEP:
+ need_separator = true;
+ will_need_separator = false;
+ break;
+ case OT_NOP:
+ need_separator = false;
+ will_need_separator = false;
+ break;
+ case OT_CLEAR:
+ need_separator = false;
+ will_need_separator = false;
+ break;
case OT_START_OBJ:
+ case OT_START_ARRAY:
+ case OT_START_HASH:
+ will_need_separator = false;
+ break;
+ case OT_NL:
+ case OT_END:
case OT_END_OBJ:
- case OT_CLEAR:
+ case OT_END_ARRAY:
+ case OT_END_HASH:
+ need_separator = false;
+ will_need_separator = true;
break;
-
default:
+ will_need_separator = true;
k = va_arg(ap, char *); /* Get the variable name */
/* If requested, we can put the keyword in lowercase */
case OT_ALIST_STR:
lst = va_arg(ap, alist *);
i = 0;
- Mmsg(tmp, "%s=", k);
+ Mmsg(tmp, "%s%c%s",
+ ow_quote_string(k), equal,
+ open_table);
if (lst) {
foreach_alist(s, lst) {
if (i++ > 0) {
pm_strcat(tmp, ",");
}
- pm_strcat(tmp, s);
+ pm_strcat(tmp, ow_quote_string(s));
}
}
- pm_strcat(tmp, separator_str);
+ pm_strcat(tmp, close_table);
break;
case OT_PLUGINS:
lst = va_arg(ap, alist *);
i = 0;
- pm_strcpy(tmp, "plugins=");
+ Mmsg(tmp, "%s%c%s",
+ ow_quote_string("plugin"),
+ equal,
+ open_table);
if (lst) {
foreach_alist(plug, lst) {
if (i++ > 0) {
pm_strcat(tmp, ",");
}
- pm_strcat(tmp, plug->name);
+ pm_strcat(tmp, ow_quote_string(plug->file));
}
}
- pm_strcat(tmp, separator_str);
+ pm_strcat(tmp, close_table);
break;
case OT_RATIO:
d = va_arg(ap, double);
- Mmsg(tmp, "%s=%.2f%c", k, d, separator);
+ Mmsg(tmp, "%s%c%.2f", ow_quote_string(k), equal, d);
break;
case OT_BOOL:
i = va_arg(ap, int);
- Mmsg(tmp, "%s=%s%c", k, i?"true":"false", separator);
+ Mmsg(tmp, "%s%c%s", ow_quote_string(k), equal, i?"true":"false");
break;
case OT_STRING:
s = va_arg(ap, char *);
- Mmsg(tmp, "%s=%s%c", k, NPRTB(s), separator) ;
+ Mmsg(tmp, "%s%c%s", ow_quote_string(k), equal, ow_quote_string2(NPRTB(s))) ;
break;
-
case OT_INT32:
i32 = va_arg(ap, int32_t);
- Mmsg(tmp, "%s=%d%c", k, i32, separator);
+ Mmsg(tmp, "%s%c%d", ow_quote_string(k), equal, i32);
break;
case OT_UTIME:
default:
bstrutime(ed1, sizeof(ed1), bt);
}
- Mmsg(tmp, "%s_epoch=%lld%c%s=%s%c", k, bt, separator, k, ed1, separator);
+ if (flags & OF_USE_QUOTES) {
+ ow_quote_string(ed1, tmp3);
+ bstrncpy(ed1, tmp3, sizeof(ed1));
+ }
+ Mmsg(tmp3, "%s_epoch", k);
+ Mmsg(tmp,
+ "%s%c%lld"
+ "%c"
+ "%s%c%s",
+ ow_quote_string(tmp3), equal, bt,
+ separator,
+ ow_quote_string2(k), equal, ed1);
break;
case OT_DURATION:
bt = va_arg(ap, utime_t);
- bstrutime(ed1, sizeof(ed1), bt);
- Mmsg(tmp, "%s=%lld%c%s_str=%s%c", k, bt, separator, k, edit_utime(bt, ed1, sizeof(ed1)), separator);
+ bstrutime(ed1, sizeof(ed1), bt);
+ if (flags & OF_USE_QUOTES) {
+ ow_quote_string(edit_utime(bt, ed1, sizeof(ed1)), tmp3);
+ bstrncpy(ed1, tmp3, sizeof(ed1));
+ }
+
+ Mmsg(tmp3, "%s_str", k);
+ Mmsg(tmp, "%s%c%lld"
+ "%c"
+ "%s%c%s",
+ ow_quote_string(k), equal, bt,
+ separator,
+ ow_quote_string2(tmp3), equal, ed1);
break;
case OT_SIZE:
case OT_INT64:
i64 = va_arg(ap, int64_t);
- Mmsg(tmp, "%s=%lld%c", k, i64, separator);
+ Mmsg(tmp, "%s%c%lld", ow_quote_string(k), equal, i64);
break;
case OT_PINT64:
u64 = va_arg(ap, uint64_t);
- Mmsg(tmp, "%s=%llu%c", k, u64, separator);
+ Mmsg(tmp, "%s%c%llu", ow_quote_string(k), equal, u64);
break;
case OT_INT:
i64 = va_arg(ap, int);
- Mmsg(tmp, "%s=%lld%c", k, i64, separator);
+ Mmsg(tmp, "%s%c%lld", ow_quote_string(k), equal, i64);
break;
case OT_JOBLEVEL:
case OT_JOBTYPE:
case OT_JOBSTATUS:
i32 = va_arg(ap, int32_t);
- if (i32 == 0) {
- Mmsg(tmp, "%s=%c", k, separator);
+ if (i32 == 0) { // TODO: Check if it's possible
+ Mmsg(tmp, "%s%c%s", ow_quote_string(k), equal, ow_quote_string2(""));
} else {
- Mmsg(tmp, "%s=%c%c", k, (char)i32, separator);
+ ed1[0] = (char)i32;
+ ed1[1] = 0;
+ Mmsg(tmp, "%s%c%s", ow_quote_string(k), equal, ow_quote_string2(ed1));
}
break;
break;
case OT_END_OBJ:
- pm_strcpy(tmp, "\n");
+ i=0;
+ if (object_separator[1]) {
+ tmp[i++] = object_separator[1];
+ } else {
+ tmp[i++] = '\n';
+ }
+ tmp[i] = 0;
+ break;
+
+ case OT_LABEL:
+ Mmsg(tmp, "%s%s", ow_quote_string(k), label);
+ will_need_separator = false;
break;
case OT_START_OBJ:
i=0;
- if (object_separator) {
- for(; i < 32 ; i++) {
- tmp[i] = object_separator;
- }
+ if (object_separator[0]) {
+ tmp[i++] = object_separator[0];
+
+ } else {
+ tmp[i++] = '\n';
}
- tmp[i++] = '\n';
tmp[i] = 0;
break;
+ case OT_START_HASH:
+ pm_strcpy(tmp, open_hash);
+ break;
+
+ case OT_END_HASH:
+ pm_strcpy(tmp, close_hash);
+ break;
+
+ case OT_START_ARRAY:
+ pm_strcpy(tmp, open_table);
+ break;
+
+ case OT_END_ARRAY:
+ pm_strcpy(tmp, close_table);
+ break;
+
+ case OT_NL:
+ pm_strcat(tmp, "\n");
+ break;
+
+ case OT_NOP:
+ break;
+
+ case OT_SEP:
+ break; // Will add a separator at the next round
+
case OT_END:
/* wanted fallback */
default:
}
if (val != OT_END) {
+ if (need_separator) {
+ pm_strcat(out, separator_str);
+
+ }
+ need_separator = will_need_separator;
pm_strcat(out, tmp);
val = (OutputType) va_arg(ap, int); /* OutputType is promoted to int when using ... */
}
free_pool_memory(tmp);
free_pool_memory(tmp2);
+ free_pool_memory(tmp3);
//Dmsg1(000, "%s", *out);
return *out;
}
int64_t nb64 = -1;
btime_t t = time(NULL);
- ok(strcmp(wt.get_options(ed1), "") == 0, "Default options");
-
+ ok(strcmp(wt.get_options(ed1, sizeof(ed1)), "") == 0, "Default options");
Pmsg1(000, "%s", wt.start_group("test"));
wt.get_output(&tmp, OT_CLEAR,
OT_END));
wt.set_time_format(OTT_TIME_UNIX);
- ok(strcmp("t1", wt.get_options(ed1)) == 0, "Check unix time format");
+ ok(strcmp("t1", wt.get_options(ed1, sizeof(ed1))) == 0, "Check unix time format");
Pmsg1(000, "%s",
wt.get_output(OT_CLEAR,
OT_END));
wt.set_time_format(OTT_TIME_NC);
- ok(strcmp("t2", wt.get_options(ed1)) == 0, "Check NC time format");
+ ok(strcmp("t2", wt.get_options(ed1, sizeof(ed1))) == 0, "Check NC time format");
Pmsg1(000, "%s",
wt.get_output(OT_CLEAR,
Pmsg1(000, "%s", wt.end_group(false));
wt.parse_options("s43t1O");
- ok(strcmp(wt.get_options(ed1), "s43t1") == 0, "Check options after parsing");
+ ok(strcmp(wt.get_options(ed1, sizeof(ed1)), "s43t1") == 0, "Check options after parsing");
- ok(strstr(
- wt.get_output(OT_CLEAR,
- OT_BTIME, "now", t,
- OT_STRING, "brazil", "test",
- OT_END),
- "+brazil=test+") != NULL,
+ char *p = wt.get_output(OT_CLEAR,
+ OT_BTIME, "now", t,
+ OT_STRING, "brazil", "test",
+ OT_END);
+ ok(strstr(p, "+brazil=test") != NULL,
"Check separator");
+ Pmsg1(000, "===> [%s]\n", p);
wt.parse_options("CS35");
- ok(strcmp(wt.get_options(ed1), "S35") == 0, "Check options after parsing");
+ ok(strcmp(wt.get_options(ed1, sizeof(ed1)), "S35") == 0, "Check options after parsing");
Pmsg1(000, "%s",
wt.get_output(OT_CLEAR,
OT_END_OBJ,
OT_END));
- free(str);
+ wt.parse_options("Cs44e58q");
+ ok(strcmp(wt.get_options(ed1, sizeof(ed1)), "s44e58q") == 0, "Check options after parsing");
+
+ wt.parse_options("Cj");
+ Dmsg1(0, "%s\n", wt.get_options(ed1, sizeof(ed1)));
+ ok(strcmp(wt.get_options(ed1, sizeof(ed1)), "s44S123e58l58oqj") == 0, "Check options after parsing");
+
+ Pmsg1(000, "%s",
+ wt.get_output(OT_CLEAR,
+ OT_START_ARRAY,
+ OT_LABEL, "backup",
+ OT_START_HASH,
+ OT_STRING, "test", "my value",
+ OT_STRING, "test2", ptr,
+ OT_END_HASH,
+ OT_LABEL, "restore",
+ OT_START_HASH,
+ OT_STRING, "test", "my value",
+ OT_STRING, "test2", ptr,
+ OT_END_HASH,
+ OT_LABEL, "info",
+ OT_START_HASH,
+ OT_BTIME, "now", t,
+ OT_STRING, "test2", ptr,
+ OT_END_HASH,
+ OT_END_ARRAY,
+ OT_END));
+
+ free(str);
return report();
}
#endif /* TEST_PROGRAM */
OT_ALIST_STR,
OT_BOOL, /* boolean */
+ OT_NL, /* Add new line */
+ OT_SEP, /* Add a separator */
+ OT_NOP, /* do nothing */
OT_END, /* Last operator (no extra arg) */
OT_START_OBJ, /* Skip a line to start a new object (no extra arg) */
OT_END_OBJ, /* Skip a line to end current object (no extra arg) */
+ OT_LABEL, /* label sep ("test":) */
+ OT_START_ARRAY, /* Start array [ */
+ OT_END_ARRAY, /* End array ] */
+ OT_START_HASH, /* Start hash { */
+ OT_END_HASH, /* End hash */
OT_CLEAR, /* truncate current buffer (no extra arg) */
OT_DURATION /* time duration in second */
};
#define OW_DEFAULT_SEPARATOR '\n'
#define OW_DEFAULT_TIMEFORMAT OTT_TIME_ISO
+#define OW_DEFAULT_EQUAL '='
+
+#define OW_DEFAULT_OPEN_HASH ""
+#define OW_DEFAULT_CLOSE_HASH ""
+
+#define OW_DEFAULT_OPEN_TABLE ""
+#define OW_DEFAULT_CLOSE_TABLE ""
+
+#define OW_DEFAULT_LABEL ":\n"
/* If included from output.c, mark the class as export (else, symboles are
* exported from all files...
private:
void init() {
buf = NULL;
+ quote_buf = NULL;
+ quote_buf2 = NULL;
separator = OW_DEFAULT_SEPARATOR;
separator_str[0] = OW_DEFAULT_SEPARATOR;
separator_str[1] = 0;
timeformat = OW_DEFAULT_TIMEFORMAT;
- object_separator = 0;
+ object_separator[0] = 0;
+ object_separator[1] = 0;
+ equal = OW_DEFAULT_EQUAL;
+ equal_str[0] = OW_DEFAULT_EQUAL;
+ equal_str[1] = 0;
+
+ open_hash = OW_DEFAULT_OPEN_HASH;
+ close_hash = OW_DEFAULT_CLOSE_HASH;
+ open_table = OW_DEFAULT_OPEN_TABLE;
+ close_table = OW_DEFAULT_CLOSE_TABLE;
+ label = OW_DEFAULT_LABEL;
flags = 0;
+
+ need_separator=false;
+ will_need_separator=true;
+
+ error = 0;
+ errmsg = NULL;
};
protected:
virtual char *get_output(va_list ap, POOLMEM **out, OutputType first);
void get_buf(bool append); /* Allocate buf if needed */
+ bool quote_str;
int flags;
+ char equal;
+ char equal_str[2];
char separator;
char separator_str[2];
- char object_separator;
+ char object_separator[2];
OutputTimeType timeformat;
POOLMEM *buf;
+ POOLMEM *quote_buf; /* Buffer used to quote parameters */
+ POOLMEM *quote_buf2;
+ const char *open_table;
+ const char *close_table;
+ const char *open_hash;
+ const char *close_hash;
+ const char *label;
+
+ int error;
+ char *errmsg;
+
+ bool need_separator;
+ bool will_need_separator;
public:
OutputWriter(const char *opts) {
virtual ~OutputWriter() {
free_and_null_pool_memory(buf);
+ free_and_null_pool_memory(quote_buf);
+ free_and_null_pool_memory(quote_buf2);
+ bfree_and_null(errmsg);
};
/* s[ascii code]t[0-3]
* "s43t1" => + as separator and time as unix timestamp
*/
virtual void parse_options(const char *opts);
- virtual char *get_options(char *dest_l128); /* MAX_NAME_LENGTH mini */
+ virtual char *get_options(char *dest_l128, int len); /* MAX_NAME_LENGTH mini */
/* Make a clear separation in the output*/
virtual char *start_group(const char *name, bool append=true);
virtual char *start_list(const char *name, bool append=true);
virtual char *end_list(bool append=true);
+ void set_label(const char *l) {
+ label = l;
+ };
+
+ void set_error(int errcode, const char *errstr) {
+ error = errcode;
+ errmsg = bstrdup(errstr);
+ };
+
+ void set_hash(const char *o, const char *c)
+ {
+ open_hash = o;
+ close_hash = c;
+ };
+
+ void set_table(const char *o, const char *c)
+ {
+ open_table = o;
+ close_table = c;
+ };
+
/* \n by default, can be \t for example */
void set_separator(char sep) {
separator = sep;
separator_str[0] = sep;
};
- void set_object_separator(char sep) {
- object_separator = sep;
+ void set_equal(char eq) {
+ equal = eq;
+ equal_str[0] = eq;
+ };
+ void set_object_separator(char sep, char esep) {
+ object_separator[0] = sep;
+ object_separator[1] = esep;
};
-
void set_time_format(OutputTimeType fmt) {
timeformat = fmt;
};
+ bool use_json();
+
+ char *start_object(const char *name, bool append=true);
+ char *end_object(bool append=true);
/* Usage:
* get_output(&out,
* "name=value\nage=10\nbirt-date=2012-01-12 10:20:00\nweight=100\n"
*
*/
-
+
/* Use a user supplied buffer */
char *get_output(POOLMEM **out, OutputType first, ...);
/* Use the internal buffer */
char *get_output(OutputType first, ...);
+
+ /* Quote or not the string, memory allocated in quote_buffer */
+ const char *ow_quote_string(const char *str);
+
+ /* Quote or not the string, memory allocated in quote_buffer2 */
+ const char *ow_quote_string2(const char *str);
+
+ /* Quote or not the string, memory allocated in quote_buffer2 */
+ const char *ow_quote_string(const char *str, POOLMEM *&buffer);
};
#endif
OutputWriter ow(sp->api_opts);
char dt[MAX_TIME_LENGTH], b1[30], b2[30];
char level[10];
+ bool add_sep=false;
struct s_last_job *je;
const char *msg;
char *p;
- msg = _("\nTerminated Jobs:\n");
- if (!sp->api) sendit(msg, strlen(msg), sp);
+ if (sp->api > 1) {
+ ow.start_group("terminated");
+ p = ow.get_output(OT_START_ARRAY, OT_END);
+ sendit(p, strlen(p), sp);
+
+ } else if (!sp->api) {
+ msg = _("\nTerminated Jobs:\n");
+ sendit(msg, strlen(msg), sp);
+ }
if (last_jobs->size() == 0) {
- if (!sp->api) sendit("====\n", 5, sp);
+ if (!sp->api) {
+ sendit("====\n", 5, sp);
+
+ } else if (sp->api > 1) {
+ ow.get_output(OT_CLEAR, OT_END_ARRAY, OT_END);
+ p = ow.end_group();
+ sendit(p, strlen(p), sp);
+ }
return;
}
+
lock_last_jobs_list();
msg = _(" JobId Level Files Bytes Status Finished Name \n");
if (!sp->api) sendit(msg, strlen(msg), sp);
msg = _("===================================================================\n");
if (!sp->api) sendit(msg, strlen(msg), sp);
- if (sp->api > 1) {
- p = ow.start_group("terminated");
- sendit(p, strlen(p), sp);
- }
foreach_dlist(je, last_jobs) {
char JobName[MAX_NAME_LENGTH];
const char *termstat;
*p = 0;
}
}
+ p = buf;
if (sp->api == 1) {
bsnprintf(buf, sizeof(buf), _("%6d\t%-6s\t%8s\t%10s\t%-7s\t%-8s\t%s\n"),
- je->JobId,
- level,
- edit_uint64_with_commas(je->JobFiles, b1),
- edit_uint64_with_suffix(je->JobBytes, b2),
- termstat,
- dt, JobName);
+ je->JobId,
+ level,
+ edit_uint64_with_commas(je->JobFiles, b1),
+ edit_uint64_with_suffix(je->JobBytes, b2),
+ termstat,
+ dt, JobName);
} else if (sp->api > 1) {
p = ow.get_output(OT_CLEAR,
+ add_sep? OT_SEP : OT_NOP,
OT_START_OBJ,
OT_INT, "jobid", je->JobId,
OT_JOBLEVEL,"level", je->JobLevel,
OT_INT, "errors", je->Errors,
OT_END_OBJ,
OT_END);
- sendit(p, strlen(p), sp);
+ add_sep = true;
+
} else {
bsnprintf(buf, sizeof(buf), _("%6d %-6s %8s %10s %-7s %-8s %s\n"),
- je->JobId,
- level,
- edit_uint64_with_commas(je->JobFiles, b1),
- edit_uint64_with_suffix(je->JobBytes, b2),
- termstat,
- dt, JobName);
- sendit(buf, strlen(buf), sp);
+ je->JobId,
+ level,
+ edit_uint64_with_commas(je->JobFiles, b1),
+ edit_uint64_with_suffix(je->JobBytes, b2),
+ termstat,
+ dt, JobName);
}
+ sendit(p, strlen(p), sp);
}
unlock_last_jobs_list();
if (!sp->api) {
sendit("====\n", 5, sp);
} else if (sp->api > 1) {
- p = ow.end_group(false);
+ ow.get_output(OT_CLEAR, OT_END_ARRAY, OT_END);
+ p = ow.end_group();
sendit(p, strlen(p), sp);
}
}
void cloud_dev::get_api_cloud_upload_transfer_status(OutputWriter &ow, bool verbose)
{
- ow.start_group("uploads");
+ ow.get_output(OT_LABEL, "uploads", OT_END);
upload_mgr.append_api_status(ow, verbose);
- ow.end_group();
}
/* format a status message of the cloud transfers. Verbose gives details on each transfer */
void cloud_dev::get_api_cloud_download_transfer_status(OutputWriter &ow, bool verbose)
{
- ow.start_group("downloads");
+ ow.get_output(OT_LABEL, "downloads", OT_END);
download_mgr.append_api_status(ow, verbose);
- ow.end_group();
}
/* for a given volume VolumeName, return parts that is a list of the
OT_DURATION, "duration", m_stat_duration/ONE_SEC,
OT_STRING,"message", NPRTB(m_message),
OT_INT32, "retry", m_retry,
+ OT_END_OBJ,
OT_END);
} else {
ow.get_output(OT_START_OBJ,
OT_DURATION, "eta", m_stat_eta/ONE_SEC,
OT_STRING,"message", NPRTB(m_message),
OT_INT32, "retry", m_retry,
+ OT_END_OBJ,
OT_END);
}
}
}
ow.end_list();
}
+ ow.get_output(OT_END_OBJ, OT_END);
}
/* Forward referenced functions */
static void sendit(POOL_MEM &msg, int len, STATUS_PKT *sp);
static void sendit(const char *msg, int len, void *arg);
-static void dbg_sendit(const char *msg, int len, void *arg);
static void send_blocked_status(DEVICE *dev, STATUS_PKT *sp);
static void send_device_status(DEVICE *dev, STATUS_PKT *sp);
static void list_running_jobs(STATUS_PKT *sp);
bool list_shstore(DEVICE *dev, POOLMEM **msg, int *len) { return false;}
#endif
-static void api_list_one_device(char *name, DEVICE *dev, STATUS_PKT *sp)
+static void api_list_one_device(char *name, DEVICE *dev, STATUS_PKT *sp, OutputWriter *ow)
{
- OutputWriter ow(sp->api_opts);
int zero=0;
int blocked=0;
uint64_t f, t;
dev->get_freespace(&f, &t);
- ow.get_output(OT_START_OBJ,
- OT_STRING, "name", dev->device->hdr.name,
- OT_STRING, "archive_device", dev->archive_name(),
- OT_STRING, "type", dev->print_type(),
- OT_STRING, "driver", dev->print_driver_type(),
- OT_STRING, "media_type", dev->device->media_type,
- OT_INT, "open", (int)dev->is_open(),
- OT_INT, "writers", dev->num_writers,
- OT_INT32, "maximum_concurrent_jobs", dev->max_concurrent_jobs,
- OT_INT64, "maximum_volume_size", dev->max_volume_size,
- OT_INT, "read_only", dev->device->read_only,
- OT_INT, "autoselect", dev->device->autoselect,
- OT_INT, "enabled", dev->enabled,
- OT_INT64, "free_space", f,
- OT_INT64, "total_space", t,
- OT_INT64, "devno", dev->devno,
- OT_END);
+ ow->get_output(OT_START_OBJ,
+ OT_STRING, "name", dev->device->hdr.name,
+ OT_STRING, "archive_device", dev->archive_name(),
+ OT_STRING, "type", dev->print_type(),
+ OT_STRING, "driver", dev->print_driver_type(),
+ OT_STRING, "media_type", dev->device->media_type,
+ OT_INT, "open", (int)dev->is_open(),
+ OT_INT, "writers", dev->num_writers,
+ OT_INT32, "maximum_concurrent_jobs", dev->max_concurrent_jobs,
+ OT_INT64, "maximum_volume_size", dev->max_volume_size,
+ OT_INT, "read_only", dev->device->read_only,
+ OT_INT, "autoselect", dev->device->autoselect,
+ OT_INT, "enabled", dev->enabled,
+ OT_INT64, "free_space", f,
+ OT_INT64, "total_space", t,
+ OT_INT64, "devno", dev->devno,
+ OT_END);
if (dev->is_open()) {
if (dev->is_labeled()) {
- ow.get_output(OT_STRING, "mounted", dev->blocked()?"0":"1",
- OT_STRING, "waiting", dev->blocked()?"1":"0",
- OT_STRING, "volume", dev->VolHdr.VolumeName,
- OT_STRING, "pool", NPRTB(dev->pool_name),
- OT_END);
+ ow->get_output(OT_STRING, "mounted", dev->blocked()?"0":"1",
+ OT_STRING, "waiting", dev->blocked()?"1":"0",
+ OT_STRING, "volume", dev->VolHdr.VolumeName,
+ OT_STRING, "pool", NPRTB(dev->pool_name),
+ OT_END);
} else {
- ow.get_output(OT_INT, "mounted", zero,
- OT_INT, "waiting", zero,
- OT_STRING, "volume", "",
- OT_STRING, "pool", "",
- OT_END);
+ ow->get_output(OT_INT, "mounted", zero,
+ OT_INT, "waiting", zero,
+ OT_STRING, "volume", "",
+ OT_STRING, "pool", "",
+ OT_END);
}
blocked = 1;
/* TODO: give more information about blocked status
* and the volume needed if WAITING for SYSOP
*/
- ow.get_output(OT_STRING, "blocked_desc", NPRTB(p),
- OT_INT, "blocked", blocked,
- OT_END);
+ ow->get_output(OT_STRING, "blocked_desc", NPRTB(p),
+ OT_INT, "blocked", blocked,
+ OT_END);
- ow.get_output(OT_INT, "append", (int)dev->can_append(),
- OT_END);
+ ow->get_output(OT_INT, "append", (int)dev->can_append(),
+ OT_END);
if (dev->can_append()) {
- ow.get_output(OT_INT64, "bytes", dev->VolCatInfo.VolCatBytes,
- OT_INT32, "blocks", dev->VolCatInfo.VolCatBlocks,
- OT_END);
+ ow->get_output(OT_INT64, "bytes", dev->VolCatInfo.VolCatBytes,
+ OT_INT32, "blocks", dev->VolCatInfo.VolCatBlocks,
+ OT_END);
} else { /* reading */
- ow.get_output(OT_INT64, "bytes", dev->VolCatInfo.VolCatRBytes,
- OT_INT32, "blocks", dev->VolCatInfo.VolCatReads, /* might not be blocks */
- OT_END);
+ ow->get_output(OT_INT64, "bytes", dev->VolCatInfo.VolCatRBytes,
+ OT_INT32, "blocks", dev->VolCatInfo.VolCatReads, /* might not be blocks */
+ OT_END);
}
- ow.get_output(OT_INT, "file", dev->file,
- OT_INT, "block", dev->block_num,
- OT_END);
+ ow->get_output(OT_INT, "file", dev->file,
+ OT_INT, "block", dev->block_num,
+ OT_END);
} else {
- ow.get_output(OT_INT, "mounted", zero,
+ ow->get_output(OT_INT, "mounted", zero,
OT_INT, "waiting", zero,
OT_STRING, "volume", "",
OT_STRING, "pool", "",
OT_END);
}
- list_shstore(dev, &ow);
+ list_shstore(dev, ow);
- p = ow.get_output(OT_END_OBJ, OT_END);
+ p = ow->get_output(OT_END_OBJ, OT_END);
sendit(p, strlen(p), sp);
}
-static void list_one_device(char *name, DEVICE *dev, STATUS_PKT *sp)
+static void list_one_device(char *name, DEVICE *dev, STATUS_PKT *sp, OutputWriter *ow)
{
char b1[35], b2[35], b3[35];
POOL_MEM msg(PM_MESSAGE);
int bpb;
if (sp->api > 1) {
- api_list_one_device(name, dev, sp);
+ api_list_one_device(name, dev, sp, ow);
return;
}
if (!sp->api) sendit("==\n", 4, sp);
}
-void _dbg_list_one_device(char *name, DEVICE *dev, const char *file, int line)
-{
- STATUS_PKT sp;
- sp.bs = NULL;
- sp.callback = dbg_sendit;
- sp.context = NULL;
- d_msg(file, line, 0, "Called dbg_list_one_device():");
- list_one_device(name, dev, &sp);
- send_device_status(dev, &sp);
-}
-
-static void list_one_autochanger(char *name, AUTOCHANGER *changer, STATUS_PKT *sp)
+static void list_one_autochanger(char *name, AUTOCHANGER *changer, STATUS_PKT *sp, OutputWriter *ow)
{
int len;
char *p;
DEVRES *device;
POOL_MEM msg(PM_MESSAGE);
- OutputWriter ow(sp->api_opts);
if (sp->api > 1) {
- ow.get_output(OT_START_OBJ,
- OT_STRING, "autochanger", changer->hdr.name,
- OT_END);
+ ow->get_output(OT_START_OBJ,
+ OT_STRING, "autochanger", changer->hdr.name,
+ OT_END);
- ow.start_group("devices");
+ ow->start_list("devices");
foreach_alist(device, changer->device) {
- ow.get_output(OT_START_OBJ,
- OT_STRING, "name", device->hdr.name,
- OT_STRING, "device",device->device_name,
- OT_END_OBJ,
- OT_END);
+ // We build a list here with a CLEAR
+ ow->get_output(OT_START_OBJ,
+ OT_STRING, "name", device->hdr.name,
+ OT_STRING, "device",device->device_name,
+ OT_END_OBJ,
+ OT_END);
}
- ow.end_group();
+ ow->end_list();
- p = ow.get_output(OT_END_OBJ, OT_END);
+ p = ow->get_output(OT_END_OBJ, OT_END);
sendit(p, strlen(p), sp);
+ ow->get_output(OT_CLEAR, OT_END);
} else {
int len;
DEVRES *device;
AUTOCHANGER *changer;
- POOL_MEM msg(PM_MESSAGE);
+ OutputWriter ow(sp->api_opts);
+ char *buf=NULL;
+ bool first;
if (!sp->api) {
+ POOL_MEM msg(PM_MESSAGE);
len = Mmsg(msg, _("\nDevice status:\n"));
sendit(msg, len, sp);
+
+ } else if (sp->api > 1) {
+ ow.start_group("devices");
+ ow.get_output(OT_START_OBJ, OT_END);
+ buf = ow.start_list("autochanger");
+ sendit(buf, strlen(buf), sp);
}
+ first = true;
foreach_res(changer, R_AUTOCHANGER) {
if (!name || strcmp(changer->hdr.name, name) == 0) {
- list_one_autochanger(changer->hdr.name, changer, sp);
+ ow.get_output(OT_CLEAR, first? OT_NOP : OT_SEP, OT_END);
+ list_one_autochanger(changer->hdr.name, changer, sp, &ow);
+ first = false;
}
}
+ if (sp->api > 1) {
+ ow.get_output(OT_CLEAR, OT_END);
+ ow.end_list();
+ buf = ow.start_list("device");
+ sendit(buf, strlen(buf), sp);
+ }
+
+ first = true;
foreach_res(device, R_DEVICE) {
if (!name || strcmp(device->hdr.name, name) == 0) {
- list_one_device(device->hdr.name, device->dev, sp);
+ ow.get_output(OT_CLEAR, first? OT_NOP : OT_SEP, OT_END);
+ list_one_device(device->hdr.name, device->dev, sp, &ow);
+ first = false;
}
}
+ if (sp->api > 1) {
+ ow.end_list();
+ ow.get_output(OT_END_OBJ, OT_END);
+ buf = ow.end_group();
+ sendit(buf, strlen(buf), sp);
+ }
if (!sp->api) sendit("====\n\n", 6, sp);
}
{
if (sp->api) {
DEVRES *device;
+
foreach_res(device, R_DEVICE) {
if (device->dev && device->dev->is_cloud()) {
- cloud_dev *cdev = (cloud_dev*)device->dev;
+ char *p;
OutputWriter ow(sp->api_opts);
- ow.start_group(device->hdr.name);
+ cloud_dev *cdev = (cloud_dev*)device->dev;
+
+ ow.start_group("cloud");
+ ow.get_output(OT_START_OBJ, OT_END);
cdev->get_api_cloud_upload_transfer_status(ow, verbose);
cdev->get_api_cloud_download_transfer_status(ow, verbose);
- ow.end_group();
- char *p = ow.get_output(OT_END_OBJ, OT_END);
+ ow.get_output(OT_END_OBJ, OT_END);
+ p = ow.end_group();
sendit(p, strlen(p), sp);
+ break; // One transfer manager?
}
}
+
+
} else {
bool first=true;
int len;
sd_list_loaded_drivers(&drivers);
wt.start_group("header");
wt.get_output(
+ OT_START_OBJ,
OT_STRING, "name", my_name,
OT_STRING, "version", VERSION " (" BDATE ")",
OT_STRING, "uname", HOST_OS " " DISTNAME " " DISTVER,
OT_INT64, "debug", debug_level,
OT_INT, "trace", get_trace(),
OT_ALIST_STR, "tags", debug_get_tags_list(&tlist, debug_level_tags),
+ OT_END_OBJ,
OT_END);
p = wt.end_group();
sendit(p, strlen(p), sp);
JCR *jcr;
DCR *dcr, *rdcr;
time_t now = time(NULL);
+ bool add_sep=false;
+ char *p;
+
+ ow.start_group("running");
+ p = ow.get_output(OT_START_ARRAY, OT_END);
+ sendit(p, strlen(p), sp);
foreach_jcr(jcr) {
+ p = ow.get_output(OT_CLEAR, add_sep ? OT_SEP : OT_NOP, OT_START_OBJ, OT_END);
+ add_sep = true;
+
if (jcr->JobId == 0 && jcr->dir_bsock) {
int val = (jcr->dir_bsock && jcr->dir_bsock->tls)?1:0;
- p1 = ow.get_output(OT_CLEAR,
- OT_UTIME, "DirectorConnected", (utime_t)jcr->start_time,
+ p1 = ow.get_output(OT_UTIME, "DirectorConnected", (utime_t)jcr->start_time,
OT_INT, "DirTLS", val,
+ OT_END_OBJ,
OT_END);
sendit(p1, strlen(p1), sp);
continue;
}
if (jcr->getJobType() == JT_SYSTEM) {
+ add_sep = false; // Skip this one, it has been printed already
continue;
}
- ow.get_output(OT_CLEAR,
- OT_START_OBJ,
- OT_INT32, "jobid", jcr->JobId,
+ ow.get_output(OT_INT32, "jobid", jcr->JobId,
OT_STRING, "job", jcr->Job,
OT_JOBLEVEL,"level", jcr->getJobLevel(),
OT_JOBTYPE, "type", jcr->getJobType(),
}
endeach_jcr(jcr);
+ // Finish the JSON output if needed
+ ow.get_output(OT_CLEAR, OT_END_ARRAY, OT_END);
+ p = ow.end_group();
+ sendit(p, strlen(p), sp);
}
static void list_running_jobs(STATUS_PKT *sp)
}
}
-static void dbg_sendit(const char *msg, int len, void *sp)
-{
- if (len > 0) {
- Dmsg0(-1, msg);
- }
-}
-
/*
* Status command from Director
*/
POOLMEM *buf;
Dmsg1(200, "enter api_collectors_status() %s\n", NPRTB(collname));
- ow.start_group("collector_backends");
+ ow.start_group("collector");
+ ow.get_output(OT_START_OBJ, OT_END);
+ ow.start_list("collector_backends");
LockRes();
foreach_res(res, R_COLLECTOR) {
if (collname && !bstrcmp(collname, res->res_collector.hdr.name)){
api_render_collector_status(res->res_collector, ow);
};
UnlockRes();
- buf = ow.end_group();
- if (!collname){
- ow.start_group("collector_update");
+ ow.end_list();
+ if (!collname) {
+ ow.get_output(OT_SEP, OT_LABEL, "collector_update", OT_END);
api_render_updcollector_status(ow);
- buf = ow.end_group();
+
}
+ ow.get_output(OT_END_OBJ, OT_END);
+ buf = ow.end_group();
sendit(buf, strlen(buf), sp);
Dmsg0(200, "leave api_collectors_status()\n");
};