1d4afb5ceSopenharmony_ci/*
2d4afb5ceSopenharmony_ci * lws-api-test-fts - lws full-text search api test
3d4afb5ceSopenharmony_ci *
4d4afb5ceSopenharmony_ci * Written in 2010-2019 by Andy Green <andy@warmcat.com>
5d4afb5ceSopenharmony_ci *
6d4afb5ceSopenharmony_ci * This file is made available under the Creative Commons CC0 1.0
7d4afb5ceSopenharmony_ci * Universal Public Domain Dedication.
8d4afb5ceSopenharmony_ci */
9d4afb5ceSopenharmony_ci
10d4afb5ceSopenharmony_ci#include <libwebsockets.h>
11d4afb5ceSopenharmony_ci#if defined(LWS_HAS_GETOPT_LONG) || defined(WIN32)
12d4afb5ceSopenharmony_ci#include <getopt.h>
13d4afb5ceSopenharmony_ci#endif
14d4afb5ceSopenharmony_ci#include <fcntl.h>
15d4afb5ceSopenharmony_ci
16d4afb5ceSopenharmony_ci#if defined(LWS_HAS_GETOPT_LONG) || defined(WIN32)
17d4afb5ceSopenharmony_cistatic struct option options[] = {
18d4afb5ceSopenharmony_ci	{ "help",	no_argument,		NULL, 'h' },
19d4afb5ceSopenharmony_ci	{ "createindex", no_argument,		NULL, 'c' },
20d4afb5ceSopenharmony_ci	{ "index",	required_argument,	NULL, 'i' },
21d4afb5ceSopenharmony_ci	{ "debug",	required_argument,	NULL, 'd' },
22d4afb5ceSopenharmony_ci	{ "file",	required_argument,	NULL, 'f' },
23d4afb5ceSopenharmony_ci	{ "lines",	required_argument,	NULL, 'l' },
24d4afb5ceSopenharmony_ci	{ NULL, 0, 0, 0 }
25d4afb5ceSopenharmony_ci};
26d4afb5ceSopenharmony_ci#endif
27d4afb5ceSopenharmony_ci
28d4afb5ceSopenharmony_cistatic const char *index_filepath = "/tmp/lws-fts-test-index";
29d4afb5ceSopenharmony_cistatic char filepath[256];
30d4afb5ceSopenharmony_ci
31d4afb5ceSopenharmony_ciint main(int argc, char **argv)
32d4afb5ceSopenharmony_ci{
33d4afb5ceSopenharmony_ci	int n, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;
34d4afb5ceSopenharmony_ci	int fd, fi, ft, createindex = 0, flags = LWSFTS_F_QUERY_AUTOCOMPLETE;
35d4afb5ceSopenharmony_ci	struct lws_fts_search_params params;
36d4afb5ceSopenharmony_ci	struct lws_fts_result *result;
37d4afb5ceSopenharmony_ci	struct lws_fts_file *jtf;
38d4afb5ceSopenharmony_ci	struct lws_fts *t;
39d4afb5ceSopenharmony_ci	char buf[16384];
40d4afb5ceSopenharmony_ci
41d4afb5ceSopenharmony_ci	do {
42d4afb5ceSopenharmony_ci#if defined(LWS_HAS_GETOPT_LONG) || defined(WIN32)
43d4afb5ceSopenharmony_ci		n = getopt_long(argc, argv, "hd:i:cfl", options, NULL);
44d4afb5ceSopenharmony_ci#else
45d4afb5ceSopenharmony_ci       n = getopt(argc, argv, "hd:i:cfl");
46d4afb5ceSopenharmony_ci#endif
47d4afb5ceSopenharmony_ci		if (n < 0)
48d4afb5ceSopenharmony_ci			continue;
49d4afb5ceSopenharmony_ci		switch (n) {
50d4afb5ceSopenharmony_ci		case 'i':
51d4afb5ceSopenharmony_ci			strncpy(filepath, optarg, sizeof(filepath) - 1);
52d4afb5ceSopenharmony_ci			filepath[sizeof(filepath) - 1] = '\0';
53d4afb5ceSopenharmony_ci			index_filepath = filepath;
54d4afb5ceSopenharmony_ci			break;
55d4afb5ceSopenharmony_ci		case 'd':
56d4afb5ceSopenharmony_ci			logs = atoi(optarg);
57d4afb5ceSopenharmony_ci			break;
58d4afb5ceSopenharmony_ci		case 'c':
59d4afb5ceSopenharmony_ci			createindex = 1;
60d4afb5ceSopenharmony_ci			break;
61d4afb5ceSopenharmony_ci		case 'f':
62d4afb5ceSopenharmony_ci			flags &= ~LWSFTS_F_QUERY_AUTOCOMPLETE;
63d4afb5ceSopenharmony_ci			flags |= LWSFTS_F_QUERY_FILES;
64d4afb5ceSopenharmony_ci			break;
65d4afb5ceSopenharmony_ci		case 'l':
66d4afb5ceSopenharmony_ci			flags |= LWSFTS_F_QUERY_FILES |
67d4afb5ceSopenharmony_ci				 LWSFTS_F_QUERY_FILE_LINES;
68d4afb5ceSopenharmony_ci			break;
69d4afb5ceSopenharmony_ci		case 'h':
70d4afb5ceSopenharmony_ci			fprintf(stderr,
71d4afb5ceSopenharmony_ci				"Usage: %s [--createindex]"
72d4afb5ceSopenharmony_ci					"[--index=<index filepath>] "
73d4afb5ceSopenharmony_ci					"[-d <log bitfield>] file1 file2 \n",
74d4afb5ceSopenharmony_ci					argv[0]);
75d4afb5ceSopenharmony_ci			exit(1);
76d4afb5ceSopenharmony_ci		}
77d4afb5ceSopenharmony_ci	} while (n >= 0);
78d4afb5ceSopenharmony_ci
79d4afb5ceSopenharmony_ci	lws_set_log_level(logs, NULL);
80d4afb5ceSopenharmony_ci	lwsl_user("LWS API selftest: full-text search\n");
81d4afb5ceSopenharmony_ci
82d4afb5ceSopenharmony_ci	if (createindex) {
83d4afb5ceSopenharmony_ci
84d4afb5ceSopenharmony_ci		lwsl_notice("Creating index\n");
85d4afb5ceSopenharmony_ci
86d4afb5ceSopenharmony_ci		/*
87d4afb5ceSopenharmony_ci		 * create an index by shifting through argv and indexing each
88d4afb5ceSopenharmony_ci		 * file given there into a single combined index
89d4afb5ceSopenharmony_ci		 */
90d4afb5ceSopenharmony_ci
91d4afb5ceSopenharmony_ci		ft = open(index_filepath, O_CREAT | O_WRONLY | O_TRUNC, 0600);
92d4afb5ceSopenharmony_ci		if (ft < 0) {
93d4afb5ceSopenharmony_ci			lwsl_err("%s: can't open index %s\n", __func__,
94d4afb5ceSopenharmony_ci				 index_filepath);
95d4afb5ceSopenharmony_ci
96d4afb5ceSopenharmony_ci			goto bail;
97d4afb5ceSopenharmony_ci		}
98d4afb5ceSopenharmony_ci
99d4afb5ceSopenharmony_ci		t = lws_fts_create(ft);
100d4afb5ceSopenharmony_ci		if (!t) {
101d4afb5ceSopenharmony_ci			lwsl_err("%s: Unable to allocate trie\n", __func__);
102d4afb5ceSopenharmony_ci
103d4afb5ceSopenharmony_ci			goto bail1;
104d4afb5ceSopenharmony_ci		}
105d4afb5ceSopenharmony_ci
106d4afb5ceSopenharmony_ci		while (optind < argc) {
107d4afb5ceSopenharmony_ci
108d4afb5ceSopenharmony_ci			fi = lws_fts_file_index(t, argv[optind],
109d4afb5ceSopenharmony_ci						(int)strlen(argv[optind]), 1);
110d4afb5ceSopenharmony_ci			if (fi < 0) {
111d4afb5ceSopenharmony_ci				lwsl_err("%s: Failed to get file idx for %s\n",
112d4afb5ceSopenharmony_ci					 __func__, argv[optind]);
113d4afb5ceSopenharmony_ci
114d4afb5ceSopenharmony_ci				goto bail1;
115d4afb5ceSopenharmony_ci			}
116d4afb5ceSopenharmony_ci
117d4afb5ceSopenharmony_ci			fd = open(argv[optind], O_RDONLY);
118d4afb5ceSopenharmony_ci			if (fd < 0) {
119d4afb5ceSopenharmony_ci				lwsl_err("unable to open %s for read\n",
120d4afb5ceSopenharmony_ci						argv[optind]);
121d4afb5ceSopenharmony_ci				goto bail;
122d4afb5ceSopenharmony_ci			}
123d4afb5ceSopenharmony_ci
124d4afb5ceSopenharmony_ci			do {
125d4afb5ceSopenharmony_ci				int n = (int)read(fd, buf, sizeof(buf));
126d4afb5ceSopenharmony_ci
127d4afb5ceSopenharmony_ci				if (n <= 0)
128d4afb5ceSopenharmony_ci					break;
129d4afb5ceSopenharmony_ci
130d4afb5ceSopenharmony_ci				if (lws_fts_fill(t, (uint32_t)fi, buf, (size_t)n)) {
131d4afb5ceSopenharmony_ci					lwsl_err("%s: lws_fts_fill failed\n",
132d4afb5ceSopenharmony_ci						 __func__);
133d4afb5ceSopenharmony_ci					close(fd);
134d4afb5ceSopenharmony_ci
135d4afb5ceSopenharmony_ci					goto bail;
136d4afb5ceSopenharmony_ci				}
137d4afb5ceSopenharmony_ci
138d4afb5ceSopenharmony_ci			} while (1);
139d4afb5ceSopenharmony_ci
140d4afb5ceSopenharmony_ci			close(fd);
141d4afb5ceSopenharmony_ci			optind++;
142d4afb5ceSopenharmony_ci		}
143d4afb5ceSopenharmony_ci
144d4afb5ceSopenharmony_ci		if (lws_fts_serialize(t)) {
145d4afb5ceSopenharmony_ci			lwsl_err("%s: serialize failed\n", __func__);
146d4afb5ceSopenharmony_ci
147d4afb5ceSopenharmony_ci			goto bail;
148d4afb5ceSopenharmony_ci		}
149d4afb5ceSopenharmony_ci
150d4afb5ceSopenharmony_ci		lws_fts_destroy(&t);
151d4afb5ceSopenharmony_ci		close(ft);
152d4afb5ceSopenharmony_ci
153d4afb5ceSopenharmony_ci		return 0;
154d4afb5ceSopenharmony_ci	}
155d4afb5ceSopenharmony_ci
156d4afb5ceSopenharmony_ci	/*
157d4afb5ceSopenharmony_ci	 * shift through argv searching for each token
158d4afb5ceSopenharmony_ci	 */
159d4afb5ceSopenharmony_ci
160d4afb5ceSopenharmony_ci	jtf = lws_fts_open(index_filepath);
161d4afb5ceSopenharmony_ci	if (!jtf)
162d4afb5ceSopenharmony_ci		goto bail;
163d4afb5ceSopenharmony_ci
164d4afb5ceSopenharmony_ci	while (optind < argc) {
165d4afb5ceSopenharmony_ci
166d4afb5ceSopenharmony_ci		struct lws_fts_result_autocomplete *ac;
167d4afb5ceSopenharmony_ci		struct lws_fts_result_filepath *fp;
168d4afb5ceSopenharmony_ci		uint32_t *l, n;
169d4afb5ceSopenharmony_ci
170d4afb5ceSopenharmony_ci		memset(&params, 0, sizeof(params));
171d4afb5ceSopenharmony_ci
172d4afb5ceSopenharmony_ci		params.needle = argv[optind];
173d4afb5ceSopenharmony_ci		params.flags = flags;
174d4afb5ceSopenharmony_ci		params.max_autocomplete = 20;
175d4afb5ceSopenharmony_ci		params.max_files = 20;
176d4afb5ceSopenharmony_ci
177d4afb5ceSopenharmony_ci		result = lws_fts_search(jtf, &params);
178d4afb5ceSopenharmony_ci
179d4afb5ceSopenharmony_ci		if (!result) {
180d4afb5ceSopenharmony_ci			lwsl_err("%s: search failed\n", __func__);
181d4afb5ceSopenharmony_ci			lws_fts_close(jtf);
182d4afb5ceSopenharmony_ci			goto bail;
183d4afb5ceSopenharmony_ci		}
184d4afb5ceSopenharmony_ci
185d4afb5ceSopenharmony_ci		ac = result->autocomplete_head;
186d4afb5ceSopenharmony_ci		fp = result->filepath_head;
187d4afb5ceSopenharmony_ci
188d4afb5ceSopenharmony_ci		if (!ac)
189d4afb5ceSopenharmony_ci			lwsl_notice("%s: no autocomplete results\n", __func__);
190d4afb5ceSopenharmony_ci
191d4afb5ceSopenharmony_ci		while (ac) {
192d4afb5ceSopenharmony_ci			lwsl_notice("%s: AC %s: %d agg hits\n", __func__,
193d4afb5ceSopenharmony_ci				((char *)(ac + 1)), ac->instances);
194d4afb5ceSopenharmony_ci
195d4afb5ceSopenharmony_ci			ac = ac->next;
196d4afb5ceSopenharmony_ci		}
197d4afb5ceSopenharmony_ci
198d4afb5ceSopenharmony_ci		if (!fp)
199d4afb5ceSopenharmony_ci			lwsl_notice("%s: no filepath results\n", __func__);
200d4afb5ceSopenharmony_ci
201d4afb5ceSopenharmony_ci		while (fp) {
202d4afb5ceSopenharmony_ci			lwsl_notice("%s: %s: (%d lines) %d hits \n", __func__,
203d4afb5ceSopenharmony_ci				(((char *)(fp + 1)) + fp->matches_length),
204d4afb5ceSopenharmony_ci				fp->lines_in_file, fp->matches);
205d4afb5ceSopenharmony_ci
206d4afb5ceSopenharmony_ci			if (fp->matches_length) {
207d4afb5ceSopenharmony_ci				l = (uint32_t *)(fp + 1);
208d4afb5ceSopenharmony_ci				n = 0;
209d4afb5ceSopenharmony_ci				while ((int)n++ < fp->matches)
210d4afb5ceSopenharmony_ci					lwsl_notice(" %d\n", *l++);
211d4afb5ceSopenharmony_ci			}
212d4afb5ceSopenharmony_ci			fp = fp->next;
213d4afb5ceSopenharmony_ci		}
214d4afb5ceSopenharmony_ci
215d4afb5ceSopenharmony_ci		lwsac_free(&params.results_head);
216d4afb5ceSopenharmony_ci
217d4afb5ceSopenharmony_ci		optind++;
218d4afb5ceSopenharmony_ci	}
219d4afb5ceSopenharmony_ci
220d4afb5ceSopenharmony_ci	lws_fts_close(jtf);
221d4afb5ceSopenharmony_ci
222d4afb5ceSopenharmony_ci	return 0;
223d4afb5ceSopenharmony_ci
224d4afb5ceSopenharmony_cibail1:
225d4afb5ceSopenharmony_ci	close(ft);
226d4afb5ceSopenharmony_cibail:
227d4afb5ceSopenharmony_ci	lwsl_user("FAILED\n");
228d4afb5ceSopenharmony_ci
229d4afb5ceSopenharmony_ci	return 1;
230d4afb5ceSopenharmony_ci}
231