Review Board 1.7.16


Convert pbx_spool to use string fields

Review Request #168 - Created Feb. 19, 2009 and submitted

Mark Michelson
/trunk
Reviewers
asterisk-dev
Asterisk
Simple. Convert all the static buffers used in pbx_spool to be string fields. This will dramatically lower the amount of memory used when processing a call file.
It compiles.

Diff revision 2

This is not the most recent revision of the diff. The latest diff is revision 3. See what's changed.

1 2 3
1 2 3

  1. /trunk/pbx/pbx_spool.c: Loading...
/trunk/pbx/pbx_spool.c
Revision 167169 New Change
[20] 58 lines
[+20] [+] enum {
59

    
   
59

   
60
static char qdir[255];
60
static char qdir[255];
61
static char qdonedir[255];
61
static char qdonedir[255];
62

    
   
62

   
63
struct outgoing {
63
struct outgoing {
64
	char fn[256];

   
65
	int retries;                              /*!< Current number of retries */
64
	int retries;                              /*!< Current number of retries */
66
	int maxretries;                           /*!< Maximum number of retries permitted */
65
	int maxretries;                           /*!< Maximum number of retries permitted */
67
	int retrytime;                            /*!< How long to wait between retries (in seconds) */
66
	int retrytime;                            /*!< How long to wait between retries (in seconds) */
68
	int waittime;                             /*!< How long to wait for an answer */
67
	int waittime;                             /*!< How long to wait for an answer */
69
	long callingpid;                          /*!< PID which is currently calling */
68
	long callingpid;                          /*!< PID which is currently calling */
70
	int format;                               /*!< Formats (codecs) for this call */
69
	int format;                               /*!< Formats (codecs) for this call */
71
	
70
	AST_DECLARE_STRING_FIELDS (
72
	char tech[256];                           /*!< Which channel driver to use for outgoing call */
71
		AST_STRING_FIELD(fn);                 /*!< File name of call file */
73
	char dest[256];                           /*!< Which device/line to use for outgoing call */
72
		AST_STRING_FIELD(tech);               /*!< Which channel technology to use for outgoing call */
74

    
   
73
		AST_STRING_FIELD(dest);               /*!< Which device/line to use for outgoing call */
75
	char app[256];                            /*!< If application: Application name */
74
		AST_STRING_FIELD(app);                /*!< If application: Application name */
76
	char data[256];                           /*!< If applicatoin: Application data */
75
		AST_STRING_FIELD(data);               /*!< If application: Application data */
77

    
   
76
		AST_STRING_FIELD(exten);              /*!< If extension/context/priority: Extension in dialplan */
78
	char exten[AST_MAX_EXTENSION];            /*!< If extension/context/priority: Extension in dialplan */
77
		AST_STRING_FIELD(context);            /*!< If extension/context/priority: Dialplan context */
79
	char context[AST_MAX_CONTEXT];            /*!< If extension/context/priority: Dialplan context */
78
		AST_STRING_FIELD(cid_num);            /*!< CallerID Information: Number/extension */

    
   
79
		AST_STRING_FIELD(cid_name);           /*!< CallerID Information: Name */

    
   
80
		AST_STRING_FIELD(account);            /*!< account code */

    
   
81
	);
80
	int priority;                             /*!< If extension/context/priority: Dialplan priority */
82
	int priority;                             /*!< If extension/context/priority: Dialplan priority */
81

    
   

   
82
	char cid_num[256];                        /*!< CallerID Information: Number/extension */

   
83
	char cid_name[256];                       /*!< CallerID Information: Name */

   
84

    
   

   
85
	char account[AST_MAX_ACCOUNT_CODE];       /*!< account code */

   
86

    
   

   
87
	struct ast_variable *vars;                /*!< Variables and Functions */
83
	struct ast_variable *vars;                /*!< Variables and Functions */
88
	

   
89
	int maxlen;                               /*!< Maximum length of call */
84
	int maxlen;                               /*!< Maximum length of call */
90

    
   

   
91
	struct ast_flags options;                 /*!< options */
85
	struct ast_flags options;                 /*!< options */
92
};
86
};
93

    
   
87

   
94
static void init_outgoing(struct outgoing *o)
88
static int init_outgoing(struct outgoing *o)
95
{
89
{
96
	o->priority = 1;
90
	o->priority = 1;
97
	o->retrytime = 300;
91
	o->retrytime = 300;
98
	o->waittime = 45;
92
	o->waittime = 45;
99
	o->format = AST_FORMAT_SLINEAR;
93
	o->format = AST_FORMAT_SLINEAR;
100
	ast_set_flag(&o->options, SPOOL_FLAG_ALWAYS_DELETE);
94
	ast_set_flag(&o->options, SPOOL_FLAG_ALWAYS_DELETE);

    
   
95
	if (!(ast_string_field_init(o, 128))) {

    
   
96
		return -1;

    
   
97
	}

    
   
98
	return 0;
101
}
99
}
102

    
   
100

   
103
static void free_outgoing(struct outgoing *o)
101
static void free_outgoing(struct outgoing *o)
104
{
102
{
105
	if (o->vars) {
103
	if (o->vars) {
106
		ast_variables_destroy(o->vars);
104
		ast_variables_destroy(o->vars);
107
	}
105
	}

    
   
106
	ast_string_field_free_memory(o);
108
	ast_free(o);
107
	ast_free(o);
109
}
108
}
110

    
   
109

   
111
static int apply_outgoing(struct outgoing *o, char *fn, FILE *f)
110
static int apply_outgoing(struct outgoing *o, char *fn, FILE *f)
112
{
111
{
[+20] [20] 40 lines
[+20] static int apply_outgoing(struct outgoing *o, char *fn, FILE *f)
153
					c++;
152
					c++;
154
#if 0
153
#if 0
155
				printf("'%s' is '%s' at line %d\n", buf, c, lineno);
154
				printf("'%s' is '%s' at line %d\n", buf, c, lineno);
156
#endif
155
#endif
157
				if (!strcasecmp(buf, "channel")) {
156
				if (!strcasecmp(buf, "channel")) {
158
					ast_copy_string(o->tech, c, sizeof(o->tech));
157
					if ((c2 = strchr(c, '/'))) {
159
					if ((c2 = strchr(o->tech, '/'))) {

   
160
						*c2 = '\0';
158
						*c2 = '\0';
161
						c2++;
159
						c2++;
162
						ast_copy_string(o->dest, c2, sizeof(o->dest));
160
						ast_string_field_set(o, tech, c);

    
   
161
						ast_string_field_set(o, dest, c2);
163
					} else {
162
					} else {
164
						ast_log(LOG_NOTICE, "Channel should be in form Tech/Dest at line %d of %s\n", lineno, fn);
163
						ast_log(LOG_NOTICE, "Channel should be in form Tech/Dest at line %d of %s\n", lineno, fn);
165
						o->tech[0] = '\0';

   
166
					}
164
					}
167
				} else if (!strcasecmp(buf, "callerid")) {
165
				} else if (!strcasecmp(buf, "callerid")) {
168
					ast_callerid_split(c, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num));
166
					char cid_name[80] = {0}, cid_num[80] = {0};

    
   
167
					ast_callerid_split(c, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));

    
   
168
					ast_string_field_set(o, cid_num, cid_num);

    
   
169
					ast_string_field_set(o, cid_name, cid_name);
169
				} else if (!strcasecmp(buf, "application")) {
170
				} else if (!strcasecmp(buf, "application")) {
170
					ast_copy_string(o->app, c, sizeof(o->app));
171
					ast_string_field_set(o, app, c);
171
				} else if (!strcasecmp(buf, "data")) {
172
				} else if (!strcasecmp(buf, "data")) {
172
					ast_copy_string(o->data, c, sizeof(o->data));
173
					ast_string_field_set(o, data, c);
173
				} else if (!strcasecmp(buf, "maxretries")) {
174
				} else if (!strcasecmp(buf, "maxretries")) {
174
					if (sscanf(c, "%d", &o->maxretries) != 1) {
175
					if (sscanf(c, "%d", &o->maxretries) != 1) {
175
						ast_log(LOG_WARNING, "Invalid max retries at line %d of %s\n", lineno, fn);
176
						ast_log(LOG_WARNING, "Invalid max retries at line %d of %s\n", lineno, fn);
176
						o->maxretries = 0;
177
						o->maxretries = 0;
177
					}
178
					}
178
				} else if (!strcasecmp(buf, "codecs")) {
179
				} else if (!strcasecmp(buf, "codecs")) {
179
					ast_parse_allow_disallow(NULL, &o->format, c, 1);
180
					ast_parse_allow_disallow(NULL, &o->format, c, 1);
180
				} else if (!strcasecmp(buf, "context")) {
181
				} else if (!strcasecmp(buf, "context")) {
181
					ast_copy_string(o->context, c, sizeof(o->context));
182
					ast_string_field_set(o, context, c);
182
				} else if (!strcasecmp(buf, "extension")) {
183
				} else if (!strcasecmp(buf, "extension")) {
183
					ast_copy_string(o->exten, c, sizeof(o->exten));
184
					ast_string_field_set(o, exten, c);
184
				} else if (!strcasecmp(buf, "priority")) {
185
				} else if (!strcasecmp(buf, "priority")) {
185
					if ((sscanf(c, "%d", &o->priority) != 1) || (o->priority < 1)) {
186
					if ((sscanf(c, "%d", &o->priority) != 1) || (o->priority < 1)) {
186
						ast_log(LOG_WARNING, "Invalid priority at line %d of %s\n", lineno, fn);
187
						ast_log(LOG_WARNING, "Invalid priority at line %d of %s\n", lineno, fn);
187
						o->priority = 1;
188
						o->priority = 1;
188
					}
189
					}
[+20] [20] 33 lines
[+20] static int apply_outgoing(struct outgoing *o, char *fn, FILE *f)
222
							last = var;
223
							last = var;
223
						}
224
						}
224
					} else
225
					} else
225
						ast_log(LOG_WARNING, "Malformed \"%s\" argument.  Should be \"%s: variable=value\"\n", buf, buf);
226
						ast_log(LOG_WARNING, "Malformed \"%s\" argument.  Should be \"%s: variable=value\"\n", buf, buf);
226
				} else if (!strcasecmp(buf, "account")) {
227
				} else if (!strcasecmp(buf, "account")) {
227
					ast_copy_string(o->account, c, sizeof(o->account));
228
					ast_string_field_set(o, account, c);
228
				} else if (!strcasecmp(buf, "alwaysdelete")) {
229
				} else if (!strcasecmp(buf, "alwaysdelete")) {
229
					ast_set2_flag(&o->options, ast_true(c), SPOOL_FLAG_ALWAYS_DELETE);
230
					ast_set2_flag(&o->options, ast_true(c), SPOOL_FLAG_ALWAYS_DELETE);
230
				} else if (!strcasecmp(buf, "archive")) {
231
				} else if (!strcasecmp(buf, "archive")) {
231
					ast_set2_flag(&o->options, ast_true(c), SPOOL_FLAG_ARCHIVE);
232
					ast_set2_flag(&o->options, ast_true(c), SPOOL_FLAG_ARCHIVE);
232
				} else {
233
				} else {
233
					ast_log(LOG_WARNING, "Unknown keyword '%s' at line %d of %s\n", buf, lineno, fn);
234
					ast_log(LOG_WARNING, "Unknown keyword '%s' at line %d of %s\n", buf, lineno, fn);
234
				}
235
				}
235
			} else
236
			} else
236
				ast_log(LOG_NOTICE, "Syntax error at line %d of %s\n", lineno, fn);
237
				ast_log(LOG_NOTICE, "Syntax error at line %d of %s\n", lineno, fn);
237
		}
238
		}
238
	}
239
	}
239
	ast_copy_string(o->fn, fn, sizeof(o->fn));
240
	ast_string_field_set(o, fn, fn);
240
	if (ast_strlen_zero(o->tech) || ast_strlen_zero(o->dest) || (ast_strlen_zero(o->app) && ast_strlen_zero(o->exten))) {
241
	if (ast_strlen_zero(o->tech) || ast_strlen_zero(o->dest) || (ast_strlen_zero(o->app) && ast_strlen_zero(o->exten))) {
241
		ast_log(LOG_WARNING, "At least one of app or extension must be specified, along with tech and dest in file %s\n", fn);
242
		ast_log(LOG_WARNING, "At least one of app or extension must be specified, along with tech and dest in file %s\n", fn);
242
		return -1;
243
		return -1;
243
	}
244
	}
244
	return 0;
245
	return 0;
[+20] [20] 80 lines
[+20] [+] static int remove_from_queue(struct outgoing *o, const char *status)
325
{
326
{
326
	struct outgoing *o = data;
327
	struct outgoing *o = data;
327
	int res, reason;
328
	int res, reason;
328
	if (!ast_strlen_zero(o->app)) {
329
	if (!ast_strlen_zero(o->app)) {
329
		ast_verb(3, "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries);
330
		ast_verb(3, "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries);
330
		res = ast_pbx_outgoing_app(o->tech, o->format, o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
331
		res = ast_pbx_outgoing_app(o->tech, o->format, (void *) o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
331
		o->vars = NULL;
332
		o->vars = NULL;
332
	} else {
333
	} else {
333
		ast_verb(3, "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries);
334
		ast_verb(3, "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries);
334
		res = ast_pbx_outgoing_exten(o->tech, o->format, o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
335
		res = ast_pbx_outgoing_exten(o->tech, o->format, (void *) o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
335
		o->vars = NULL;
336
		o->vars = NULL;
336
	}
337
	}
337
	if (res) {
338
	if (res) {
338
		ast_log(LOG_NOTICE, "Call failed to go through, reason (%d) %s\n", reason, ast_channel_reason2str(reason));
339
		ast_log(LOG_NOTICE, "Call failed to go through, reason (%d) %s\n", reason, ast_channel_reason2str(reason));
339
		if (o->retries >= o->maxretries + 1) {
340
		if (o->retries >= o->maxretries + 1) {
[+20] [20] 33 lines
[+20] [+] static int scan_service(char *fn, time_t now, time_t atime)
373
	if (!(o = ast_calloc(1, sizeof(*o)))) {
374
	if (!(o = ast_calloc(1, sizeof(*o)))) {
374
		ast_log(LOG_WARNING, "Out of memory ;(\n");
375
		ast_log(LOG_WARNING, "Out of memory ;(\n");
375
		return -1;
376
		return -1;
376
	}
377
	}
377
	
378
	
378
	init_outgoing(o);
379
	if (init_outgoing(o)) {

    
   
380
		/* No need to call free_outgoing here since we know the failure

    
   
381
		 * was to allocate string fields and no variables have been allocated

    
   
382
		 * yet.

    
   
383
		 */

    
   
384
		ast_free(o);

    
   
385
		return -1;

    
   
386
	}
379

    
   
387

   
380
	/* Attempt to open the file */
388
	/* Attempt to open the file */
381
	if (!(f = fopen(fn, "r+"))) {
389
	if (!(f = fopen(fn, "r+"))) {
382
		remove_from_queue(o, "Failed");
390
		remove_from_queue(o, "Failed");
383
		free_outgoing(o);
391
		free_outgoing(o);
[+20] [20] 141 lines
  1. /trunk/pbx/pbx_spool.c: Loading...

https://reviewboard.asterisk.org/ runs on a server provided by Digium, Inc. and uses bandwidth donated to the open source Asterisk community by API Digital Communications in Huntsville, AL USA.
Please report problems with this site to asteriskteam@digium.com.