rest: add POST oglive/default

Remove 'is_default' column from 'lives' database table and add
column 'priority' of type INT. This new value can store a priority
value but the actual design only stores 1 or 0.

Update GET oglive/list to use the new 'priority' database value.

Add POST oglive/default.
Set the database column 'priority' to 1 if the new default
exists in the database. Set the others to priority 0.
Modify legacy ogliveinfo.json if the new default coresponds to a
live not found in the database. Edit the field 'default' of the
file's json.
master
Alejandro Sirgo Rica 2024-12-05 13:33:58 +01:00
parent e3188191d9
commit 6a63218f85
3 changed files with 286 additions and 16 deletions

View File

@ -4769,11 +4769,13 @@ static int og_cmd_oglive_list(struct og_rest_ctx *ctx)
.data = ctx->buf_reply
};
const char *msglog, *live_name, *live_datetime;
json_t *root, *live_entry, *oglive_array;
json_t *root, *live_entry, *oglive_array, *default_entry;
const char *msglog, *live_name;
uint64_t live_timestamp;
json_error_t json_err;
struct og_dbi *dbi;
dbi_result result;
int priority;
root = json_load_file(OG_LIVE_JSON_FILE_PATH, 0, &json_err);
if (!root) {
@ -4784,7 +4786,12 @@ static int og_cmd_oglive_list(struct og_rest_ctx *ctx)
oglive_array = json_object_get(root, "oglive");
if (!oglive_array || !json_is_array(oglive_array)) {
syslog(LOG_ERR, "Expected 'oglive' to be a JSON array\n");
json_decref(root);
return -1;
}
default_entry = json_object_get(root, "default");
if (!default_entry || json_typeof(default_entry) != JSON_INTEGER) {
json_decref(root);
return -1;
}
@ -4799,8 +4806,8 @@ static int og_cmd_oglive_list(struct og_rest_ctx *ctx)
}
result = dbi_conn_queryf(dbi->conn,
"SELECT name, "
"DATE_FORMAT(creation_date, '%%a %%b %%d %%H:%%i:%%s %%Y') AS formatted_date "
"SELECT name, priority, "
"UNIX_TIMESTAMP(creation_date) AS creation_timestamp "
"FROM oglive");
if (!result) {
@ -4815,7 +4822,19 @@ static int og_cmd_oglive_list(struct og_rest_ctx *ctx)
while (dbi_result_next_row(result) > 0) {
live_name = dbi_result_get_string(result, "name");
live_datetime = dbi_result_get_string(result, "formatted_date");
live_timestamp = dbi_result_get_longlong(result, "creation_timestamp");
priority = dbi_result_get_int(result, "priority");
if (priority > 0) {
if (json_integer_set(default_entry, json_array_size(oglive_array)) < 0) {
syslog(LOG_ERR, "Failed to modify 'default' entry value\n");
dbi_result_free(result);
og_dbi_close(dbi);
json_decref(root);
ctx->http_error = OG_HTTP_500_INTERNAL_SERVER_ERROR;
return -1;
}
}
live_entry = json_object();
if (!live_entry) {
@ -4829,7 +4848,7 @@ static int og_cmd_oglive_list(struct og_rest_ctx *ctx)
}
json_object_set_new(live_entry, "directory", json_string(live_name));
json_object_set_new(live_entry, "date", json_string(live_datetime));
json_object_set_new(live_entry, "date", json_integer(live_timestamp));
json_array_append_new(oglive_array, live_entry);
}
@ -5855,7 +5874,6 @@ static int og_cmd_oglive_add(struct og_rest_ctx *ctx)
{
const char *oglive_str;
bool is_update = false;
int is_default_value;
const char *msglog;
struct og_dbi *dbi;
uint64_t flags = 0;
@ -5906,20 +5924,16 @@ static int og_cmd_oglive_add(struct og_rest_ctx *ctx)
dbi_result_free(result);
is_default_value = 0;
if (is_update)
result = dbi_conn_queryf(dbi->conn,
"UPDATE oglive SET creation_date = NOW(), is_default = %d "
"UPDATE oglive SET creation_date = NOW() "
"WHERE name = '%s'",
is_default_value,
oglive_str);
else
result = dbi_conn_queryf(dbi->conn,
"INSERT INTO oglive (name, creation_date, is_default) "
"VALUES ('%s', NOW(), %d)",
oglive_str,
is_default_value);
"INSERT INTO oglive (name, creation_date) "
"VALUES ('%s', NOW())",
oglive_str);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
@ -6012,6 +6026,210 @@ static int og_cmd_oglive_delete(struct og_rest_ctx *ctx)
return 0;
}
static int update_ogliveinfo_default(const char *oglive_str)
{
char buf_data[OG_MSG_RESPONSE_MAXLEN];
struct og_buffer og_buffer = {
.data = buf_data
};
json_t *root, *oglive_array, *default_entry, *live_entry, *dir_entry;
char tmp_filename[] = "/tmp/ogliveinfo_XXXXXX";
int default_idx, i, fd, ret;
const char *live_name;
json_error_t json_err;
root = json_load_file(OG_LIVE_JSON_FILE_PATH, 0, &json_err);
if (!root) {
syslog(LOG_ERR, "malformed json line %d: %s\n",
json_err.line, json_err.text);
return -1;
}
oglive_array = json_object_get(root, "oglive");
if (!oglive_array || !json_is_array(oglive_array)) {
json_decref(root);
return -1;
}
default_entry = json_object_get(root, "default");
if (!default_entry || json_typeof(default_entry) != JSON_INTEGER) {
json_decref(root);
return -1;
}
default_idx = -1;
for (i = 0; i < json_array_size(oglive_array); i++) {
live_entry = json_array_get(oglive_array, i);
if (json_typeof(live_entry) != JSON_OBJECT) {
json_decref(root);
return -1;
}
dir_entry = json_object_get(live_entry, "directory");
if (!dir_entry || json_typeof(dir_entry) != JSON_STRING) {
json_decref(root);
return -1;
}
live_name = json_string_value(dir_entry);
if (!strncmp(oglive_str, live_name, strlen(live_name))) {
default_idx = i;
break;
}
}
if (default_idx < 0) {
json_decref(root);
return -1;
}
if (json_integer_set(default_entry, default_idx) < 0) {
syslog(LOG_ERR, "Failed to modify 'default' entry value\n");
json_decref(root);
return -1;
}
if (json_dump_callback(root, og_json_dump_clients, &og_buffer,
JSON_INDENT(2) | JSON_PRESERVE_ORDER)) {
json_decref(root);
return -1;
}
json_decref(root);
fd = mkstemp(tmp_filename);
if (fd < 0) {
syslog(LOG_ERR, "cannot generate temp file %s: %s (%s:%d)\n",
tmp_filename, strerror(errno), __func__, __LINE__);
return -1;
}
ret = write(fd, og_buffer.data, og_buffer.len);
if (ret < 0) {
syslog(LOG_ERR, "cannot write to temporary file %s: %s (%s:%d)\n",
tmp_filename, strerror(errno), __func__, __LINE__);
return -1;
}
ret = write(fd, "\n", 1);
if (ret < 0) {
syslog(LOG_ERR, "cannot write to temporary file %s: %s (%s:%d)\n",
tmp_filename, strerror(errno), __func__, __LINE__);
return -1;
}
close(fd);
if (ret < 0) {
syslog(LOG_ERR, "cannot write file %s: %s (%s:%d)\n",
tmp_filename, strerror(errno), __func__, __LINE__);
unlink(tmp_filename);
return -1;
}
if (rename(tmp_filename, OG_LIVE_JSON_FILE_PATH) < 0) {
syslog(LOG_ERR, "cannot rename file %s to %s: %s (%s:%d)\n",
tmp_filename, OG_LIVE_JSON_FILE_PATH, strerror(errno), __func__, __LINE__);
unlink(tmp_filename);
return -1;
}
return 0;
}
static int og_cmd_oglive_set_default(struct og_rest_ctx *ctx)
{
const char *oglive_str;
uint64_t flags = 0;
const char *msglog;
struct og_dbi *dbi;
dbi_result result;
bool db_has_live;
const char *key;
json_t *value;
int priority;
int err = 0;
json_object_foreach(ctx->json, key, value) {
if (!strcmp(key, "name")) {
err = og_json_parse_string(value, &oglive_str);
flags |= OG_REST_PARAM_NAME;
} else {
err = -1;
}
if (err < 0)
return err;
}
if (!og_flags_validate(flags, OG_REST_PARAM_NAME))
return -1;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
__func__, __LINE__);
ctx->http_error = OG_HTTP_501_SERVICE_UNAVAILABLE;
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"SELECT name FROM oglive WHERE name = '%s'",
oglive_str);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "Failed to query database (%s:%d) %s\n", __func__, __LINE__, msglog);
ctx->http_error = OG_HTTP_500_INTERNAL_SERVER_ERROR;
og_dbi_close(dbi);
return -1;
}
db_has_live = dbi_result_next_row(result) > 0;
dbi_result_free(result);
priority = 1;
if (db_has_live) {
result = dbi_conn_queryf(dbi->conn,
"UPDATE oglive SET priority = %d "
"WHERE name = '%s'",
priority, oglive_str);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
ctx->http_error = OG_HTTP_500_INTERNAL_SERVER_ERROR;
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
} else if (update_ogliveinfo_default(oglive_str) < 0) {
syslog(LOG_ERR, "No live entries found with name %s", oglive_str);
ctx->http_error = OG_HTTP_404_NOT_FOUND;
og_dbi_close(dbi);
return -1;
}
result = dbi_conn_queryf(dbi->conn,
"UPDATE oglive SET priority = 0 "
"WHERE priority != 0 AND name != '%s'",
oglive_str);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
ctx->http_error = OG_HTTP_500_INTERNAL_SERVER_ERROR;
og_dbi_close(dbi);
return -1;
}
dbi_result_free(result);
og_dbi_close(dbi);
return 0;
}
static int og_cmd_get_server_stats(struct og_rest_ctx *ctx)
{
json_t *root, *time_obj, *memory, *swap;
@ -6242,6 +6460,7 @@ struct {
[OG_URI_OGLIVE_ADD] = { "oglive/add", },
[OG_URI_OGLIVE_DELETE] = { "oglive/delete", },
[OG_URI_OGLIVE_SET] = { "oglive/set", },
[OG_URI_OGLIVE_DEFAULT] = { "oglive/default", },
[OG_URI_CENTER_ADD] = { "center/add", },
[OG_URI_CENTER_UPDATE] = { "center/update", },
[OG_URI_CENTER_DELETE] = { "center/delete", },
@ -6953,6 +7172,19 @@ int og_client_state_process_payload_rest(struct og_client *cli)
goto err_process_rest_payload;
}
err = og_cmd_oglive_set(&ctx);
} else if (!strncmp(cmd, "oglive/default", strlen("oglive/default"))) {
if (method != OG_METHOD_POST) {
ctx.http_error = OG_HTTP_405_METHOD_NOT_ALLOWED;
goto err_process_rest_payload;
}
if (!root) {
syslog(LOG_ERR,
"command oglive default with no payload\n");
ctx.http_error = OG_HTTP_400_BAD_REQUEST;
goto err_process_rest_payload;
}
err = og_cmd_oglive_set_default(&ctx);
} else if (!strncmp(cmd, "center/add",
strlen("center/add"))) {
if (method != OG_METHOD_POST) {

View File

@ -145,6 +145,7 @@ enum og_rest_uri {
OG_URI_OGLIVE_ADD,
OG_URI_OGLIVE_DELETE,
OG_URI_OGLIVE_SET,
OG_URI_OGLIVE_DEFAULT,
OG_URI_CENTER_ADD,
OG_URI_CENTER_UPDATE,
OG_URI_CENTER_DELETE,

View File

@ -497,6 +497,42 @@ static int og_dbi_schema_v12(struct og_dbi *dbi)
return 0;
}
static int og_dbi_schema_v13(struct og_dbi *dbi)
{
const char *msglog;
dbi_result result;
syslog(LOG_DEBUG, "Updating table oglive\n");
result = dbi_conn_query(dbi->conn, "ALTER TABLE `oglive` DROP COLUMN `is_default`");
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_INFO, "Error deleting column is_default in oglive table (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
dbi_result_free(result);
result = dbi_conn_query(dbi->conn, "ALTER TABLE `oglive` ADD COLUMN `priority` INT NOT NULL DEFAULT 0");
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_INFO, "Error adding column priority to oglive table (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
dbi_result_free(result);
result = dbi_conn_query(dbi->conn, "UPDATE version SET version = 13");
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_INFO, "Could not update version row (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
dbi_result_free(result);
return 0;
}
static struct og_schema_version {
int version;
int (*update)(struct og_dbi *dbi);
@ -513,6 +549,7 @@ static struct og_schema_version {
{ .version = 10, .update = og_dbi_schema_v10,},
{ .version = 11, .update = og_dbi_schema_v11,},
{ .version = 12, .update = og_dbi_schema_v12,},
{ .version = 13, .update = og_dbi_schema_v13,},
{ 0, NULL },
};