add ota algorithm for device

1. effective "Differential Upgrade" patch algorithm with high compression rate
2. effective recovery algorithm support recovery firmware in blocks which has low memory consumption and wear-leveling strategies, especially suitable for embeded devices with low RAM.
3. add sample ota bootloader project, see:
board\TencentOS_tiny_EVB_MX_Plus\KEIL\ota\ota_bootloader_recovery
4. add sample application project for download firmware through http, see:
board\TencentOS_tiny_EVB_MX_Plus\KEIL\ota\ota_application_download_through_http
5. add sample application project for download firmware through qcloud explorer console, see:
board\TencentOS_tiny_EVB_MX_Plus\KEIL\ota\ota_application_download_through_qcloud_iot_explorer
6. an OTA markdown document is pending
This commit is contained in:
daishengdong
2020-06-02 15:03:42 +08:00
parent 84faf16765
commit 5b51d50ade
177 changed files with 42367 additions and 1233 deletions

View File

@@ -0,0 +1,561 @@
/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#include "assert.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "graph.h"
int graph_create(graph_t *graph, int vertexs_n)
{
int i = 0;
vertex_t *vertexs;
if (!graph || vertexs_n <= 0) {
return -1;
}
memset(graph, 0, sizeof(graph_t));
if ((vertexs = malloc(vertexs_n * sizeof(vertex_t))) == NULL) {
return -1;
}
memset(vertexs, 0, vertexs_n * sizeof(vertex_t));
for (i = 0; i < vertexs_n; ++i) {
list_init(&vertexs[i].first_in);
list_init(&vertexs[i].first_out);
}
graph->edges_n = 0;
graph->vertexs_n = vertexs_n;
graph->vertexs = vertexs;
return 0;
}
int graph_destroy(graph_t *graph)
{
int i = 0;
vertex_t *vertex;
edge_t *edge, *tmp;
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
for (i = 0; i < graph->vertexs_n; ++i) {
vertex = &graph->vertexs[i];
LIST_FOR_EACH_ENTRY_SAFE(edge, tmp, edge_t, tail_list, &vertex->first_out) {
list_del(&edge->tail_list);
free(edge);
}
}
free(graph->vertexs);
graph->edges_n = 0;
graph->vertexs_n = 0;
graph->vertexs = NULL;
return 0;
}
int graph_edge_add(graph_t *graph, int tail_vertex, int head_vertex)
{
edge_t *edge;
vertex_t *tail_v, *head_v;
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (tail_vertex >= graph->vertexs_n ||
head_vertex >= graph->vertexs_n ||
tail_vertex < 0 ||
head_vertex < 0) {
return -1;
}
if ((edge = malloc(sizeof(edge_t))) == NULL) {
return -1;
}
edge->head_vertex = head_vertex;
edge->tail_vertex = tail_vertex;
list_init(&edge->head_list);
list_init(&edge->tail_list);
tail_v = &graph->vertexs[tail_vertex];
head_v = &graph->vertexs[head_vertex];
list_add(&edge->tail_list, &tail_v->first_out);
++tail_v->out_degree;
list_add(&edge->head_list, &head_v->first_in);
++head_v->in_degree;
++graph->edges_n;
return 0;
}
int graph_edge_rmv(graph_t *graph, int tail_vertex, int head_vertex)
{
edge_t *edge, *tmp;
vertex_t *tail_v, *head_v;
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (tail_vertex >= graph->vertexs_n ||
head_vertex >= graph->vertexs_n ||
tail_vertex < 0 ||
head_vertex < 0) {
return -1;
}
tail_v = &graph->vertexs[tail_vertex];
head_v = &graph->vertexs[head_vertex];
LIST_FOR_EACH_ENTRY_SAFE(edge, tmp, edge_t, tail_list, &tail_v->first_out) {
if (edge->tail_vertex == tail_vertex &&
edge->head_vertex == head_vertex) {
list_del(&edge->tail_list);
--tail_v->out_degree;
list_del(&edge->head_list);
--head_v->in_degree;
free(edge);
--graph->edges_n;
return 0;
}
}
return -1;
}
int graph_edge_rmv_by_tail(graph_t *graph, int tail_vertex, graph_edge_delete_cb del_cb, void *cb_arg)
{
edge_t *edge, *tmp;
vertex_t *tail_v, *head_v;
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (tail_vertex >= graph->vertexs_n || tail_vertex < 0) {
return -1;
}
tail_v = &graph->vertexs[tail_vertex];
LIST_FOR_EACH_ENTRY_SAFE(edge, tmp, edge_t, tail_list, &tail_v->first_out) {
if (edge->tail_vertex == tail_vertex) {
list_del(&edge->tail_list);
--tail_v->out_degree;
list_del(&edge->head_list);
head_v = &graph->vertexs[edge->head_vertex];
--head_v->in_degree;
if (del_cb) {
del_cb(edge->tail_vertex, edge->head_vertex, cb_arg);
}
free(edge);
--graph->edges_n;
}
}
return 0;
}
int graph_edge_rmv_one_by_tail(graph_t *graph, int tail_vertex)
{
edge_t *edge, *tmp;
vertex_t *tail_v, *head_v;
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (tail_vertex >= graph->vertexs_n || tail_vertex < 0) {
return -1;
}
tail_v = &graph->vertexs[tail_vertex];
LIST_FOR_EACH_ENTRY_SAFE(edge, tmp, edge_t, tail_list, &tail_v->first_out) {
if (edge->tail_vertex == tail_vertex) {
list_del(&edge->tail_list);
--tail_v->out_degree;
list_del(&edge->head_list);
head_v = &graph->vertexs[edge->head_vertex];
--head_v->in_degree;
free(edge);
--graph->edges_n;
return 0;
}
}
return -1;
}
int graph_edge_rmv_by_head(graph_t *graph, int head_vertex, graph_edge_delete_cb del_cb, void *cb_arg)
{
edge_t *edge, *tmp;
vertex_t *tail_v, *head_v;
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (head_vertex >= graph->vertexs_n || head_vertex < 0) {
return -1;
}
head_v = &graph->vertexs[head_vertex];
LIST_FOR_EACH_ENTRY_SAFE(edge, tmp, edge_t, head_list, &head_v->first_in) {
if (edge->head_vertex == head_vertex) {
list_del(&edge->tail_list);
tail_v = &graph->vertexs[edge->tail_vertex];
--tail_v->out_degree;
list_del(&edge->head_list);
--head_v->in_degree;
if (del_cb) {
del_cb(edge->tail_vertex, edge->head_vertex, cb_arg);
}
free(edge);
--graph->edges_n;
}
}
return 0;
}
int graph_edge_rmv_one_by_head(graph_t *graph, int head_vertex)
{
edge_t *edge, *tmp;
vertex_t *tail_v, *head_v;
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (head_vertex >= graph->vertexs_n || head_vertex < 0) {
return -1;
}
head_v = &graph->vertexs[head_vertex];
LIST_FOR_EACH_ENTRY_SAFE(edge, tmp, edge_t, head_list, &head_v->first_in) {
if (edge->head_vertex == head_vertex) {
list_del(&edge->tail_list);
tail_v = &graph->vertexs[edge->tail_vertex];
--tail_v->out_degree;
list_del(&edge->head_list);
--head_v->in_degree;
free(edge);
--graph->edges_n;
return 0;
}
}
return -1;
}
int graph_edgesn_get(graph_t *graph)
{
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
return graph->edges_n;
}
int graph_vertex_max(graph_t *graph)
{
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
return graph->vertexs_n;
}
int graph_indegree_get(graph_t *graph, int vertex)
{
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (vertex >= graph->vertexs_n || vertex < 0) {
return -1;
}
return graph->vertexs[vertex].in_degree;
}
int graph_outdegree_get(graph_t *graph, int vertex)
{
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (vertex >= graph->vertexs_n || vertex < 0) {
return -1;
}
return graph->vertexs[vertex].out_degree;
}
int graph_tag_set(graph_t *graph, int vertex, v_tag_t tag)
{
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (vertex >= graph->vertexs_n || vertex < 0) {
return -1;
}
graph->vertexs[vertex].tag = tag;
return 0;
}
int graph_tag_reset(graph_t *graph, int vertex)
{
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
if (vertex >= graph->vertexs_n || vertex < 0) {
return -1;
}
graph->vertexs[vertex].tag = 0;
return 0;
}
v_tag_t graph_tag_get(graph_t *graph, int vertex)
{
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return (v_tag_t)-1;
}
if (vertex >= graph->vertexs_n || vertex < 0) {
return (v_tag_t)-1;
}
return graph->vertexs[vertex].tag;
}
int graph_dfs_create(dfs_t *dfs, graph_t *graph)
{
if (!dfs || !graph) {
return -1;
}
if (graph_vertex_max(graph) == 0) {
return -1;
}
memset(dfs, 0, sizeof(dfs_t));
if (stack_create(&dfs->stack, graph_vertex_max(graph)) != 0) {
return 0;
}
if (stack_push(&dfs->stack, 0) != 0) {
// push the first vertex of the graph into the stack
return -1;
}
graph_vertex_set_visited(graph, 0);
dfs->graph = graph;
return 0;
}
int graph_dfs_destroy(dfs_t *dfs)
{
int i = 0;
if (!dfs || !dfs->graph) {
return -1;
}
for (i = 0; i < graph_vertex_max(dfs->graph); ++i) {
graph_tag_reset(dfs->graph, i);
}
stack_destroy(&dfs->stack);
dfs->graph = NULL;
return 0;
}
int graph_dfs_has_next(dfs_t *dfs)
{
if (!dfs || !dfs->graph) {
return 0;
}
return !stack_is_empty(&dfs->stack);
}
int graph_dfs_ring_detect(dfs_t *dfs, int *ring_size)
{
int i = 0;
edge_t *edge;
graph_t *graph;
vertex_t *vertex;
int vertex_idx, the_ring_size = 0, is_found = 0;
assert(sizeof(int) == sizeof(element_type_t));
if (!dfs || !dfs->graph || !ring_size) {
return -1;
}
graph = dfs->graph;
while (!stack_is_empty(&dfs->stack)) {
vertex_idx = stack_top(&dfs->stack);
vertex = &graph->vertexs[vertex_idx];
is_found = 0;
LIST_FOR_EACH_ENTRY(edge, edge_t, tail_list, &vertex->first_out) {
if (!graph_vertex_is_visited(graph, edge->head_vertex)) {
// still fresh neighbors here
stack_push(&dfs->stack, edge->head_vertex);
graph_vertex_set_visited(graph, edge->head_vertex);
is_found = 1;
break;
}
if (graph_vertex_is_tnode(graph, edge->head_vertex) ||
graph_vertex_is_rnode(graph, edge->head_vertex)) {
// already detected as a ring or a terminal node
continue;
}
// set DFS_RING_NODE tag
graph_vertex_set_rnode(graph, edge->head_vertex);
// if reach here, a ring is detected
stack_peek_init(&dfs->stack);
while ((vertex_idx = stack_peek(&dfs->stack)) != -1) {
++the_ring_size;
if (vertex_idx == edge->head_vertex) {
*ring_size = the_ring_size;
return 0;
}
}
}
// no fresh neighbors anymore
if (!is_found) {
stack_pop(&dfs->stack);
graph_vertex_set_tnode(graph, vertex_idx);
}
}
/* if here, graph may still has isolated nodes there: multi-connected-component in the graph */
for (i = 0; i < graph_vertex_max(graph); ++i) {
if (!graph_vertex_is_visited(graph, i)) {
stack_push(&dfs->stack, i);
graph_vertex_set_visited(graph, i);
break;
}
}
return -1;
}
int graph_out_print(graph_t *graph)
{
int i = 0;
edge_t *edge;
vertex_t *vertex;
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
for (i = 0; i < graph->vertexs_n; ++i) {
vertex = &graph->vertexs[i];
if (vertex->out_degree == 0) {
continue;
}
printf("\nvertex: %d\n", i);
LIST_FOR_EACH_ENTRY(edge, edge_t, tail_list, &vertex->first_out) {
printf(" - %d -> %d\n", edge->tail_vertex, edge->head_vertex);
}
}
return 0;
}
int graph_in_print(graph_t *graph)
{
int i = 0;
edge_t *edge;
vertex_t *vertex;
if (!graph || !graph->vertexs || !graph->vertexs_n) {
return -1;
}
for (i = 0; i < graph->vertexs_n; ++i) {
vertex = &graph->vertexs[i];
if (vertex->in_degree == 0) {
continue;
}
printf("\nvertex: %d\n", i);
LIST_FOR_EACH_ENTRY(edge, edge_t, head_list, &vertex->first_in) {
printf(" - %d -> %d\n", edge->tail_vertex, edge->head_vertex);
}
}
return 0;
}