Beispiel #1
0
    void reportJSON(Stats & info, const std::string & filename)
    {
        WriteBufferFromFile json_out(filename);

        std::lock_guard<std::mutex> lock(mutex);

        auto print_key_value = [&](auto key, auto value, bool with_comma = true)
        {
            json_out << double_quote << key << ": " << value << (with_comma ? ",\n" : "\n");
        };

        auto print_percentile = [&json_out, &info](auto percent, bool with_comma = true)
        {
            json_out << "\"" << percent << "\"" << ": " << info.sampler.quantileInterpolated(percent / 100.0) << (with_comma ? ",\n" : "\n");
        };

        json_out << "{\n";

        json_out << double_quote << "statistics" << ": {\n";

        double seconds = info.watch.elapsedSeconds();
        print_key_value("QPS", info.queries / seconds);
        print_key_value("RPS", info.read_rows / seconds);
        print_key_value("MiBPS", info.read_bytes / seconds);
        print_key_value("RPS_result", info.result_rows / seconds);
        print_key_value("MiBPS_result", info.result_bytes / seconds);
        print_key_value("num_queries", info.queries.load(), false);

        json_out << "},\n";

        json_out << double_quote << "query_time_percentiles" << ": {\n";

        for (int percent = 0; percent <= 90; percent += 10)
            print_percentile(percent);

        print_percentile(95);
        print_percentile(99);
        print_percentile(99.9);
        print_percentile(99.99, false);

        json_out << "}\n";

        json_out << "}\n";
    }
Beispiel #2
0
void process( redisContext *c )
{

	FCGX_Stream *in, *out, *err;
	FCGX_ParamArray envp;
	redisReply *r;
	
	json reason = { .type = STRING, .name = "reason", .str = NULL };
	json* failureEls[1] = { &reason };
	json success = { .type = OBJECT, .length = 0, .name = NULL, .objArr = NULL }; 
	json failure = { .type = OBJECT, .length = 1, .name = NULL, .objArr = failureEls }; 

	while ( FCGX_Accept( &in, &out, &err, &envp ) >= 0 )
	{
		
		// Check method
		if ( check_method_post( out, envp ) )
			continue;

		// Check user is logged in
		char sid[33];
		char *user = session( c, envp, sid );
		if ( !user )
		{
			header( out, 401, NULL );
			reason.str = "Not logged in.";
			json_out( out, &failure );
			continue;
		}

		// Initialize reused variables	
		reason.str = "";

		// Get contentlength
		long len = content_length( envp );
		
		// Get post params
		char *s;
		if ( !read_stream( &s, in, len ) )
		{
			header( out, 400, NULL );
			reason.str = "No parameters provided";
			json_out( out, &failure );
			continue;
		}

		// Parse POST params
		param *p;
		ssize_t num = convert_to_params( &p, s, "&", "=", -1 );
		
		// Get parameters
		char *courses = NULL, *date = NULL, *start = NULL, *finish = NULL, *students = NULL, *idStr = NULL;
		for ( int i = 0; i < num; ++i )
		{
			if ( !courses && !strcmp( p[i].name, "courses" ) ) {
				courses = p[i].value;
            } else if ( !date && !strcmp( p[i].name, "date" ) ) { 
                date = p[i].value;
            } else if ( !start && !strcmp( p[i].name, "start" ) ) { 
                start = p[i].value;
            } else if ( !finish && !strcmp( p[i].name, "finish" ) ) { 
                finish = p[i].value;
            } else if ( !students && !strcmp( p[i].name, "students" ) ) { 
                students = p[i].value;
			} else if ( !idStr && !strcmp( p[i].name, "id" ) ) {
				idStr = p[i].value;
			}
		}

		// Check all parameters entered
		if ( !courses || !date || !start || !finish || !students )
		{
			header( out, 400, NULL );
			reason.str = "All details must be entered.";
			json_out( out, &failure );
			goto err;
		}

		// URL decode components
		inplace_url_decode( courses );
		inplace_url_decode( date );
		inplace_url_decode( start );
		inplace_url_decode( finish );
		inplace_url_decode( students );

		// Get next tute id
		long long id = -1;
		if ( idStr ) {
			// Convert to long long 
			id = strtol( idStr, NULL, 10 );
			
			// Check user owns tute
			r = redisCommand( c, "SISMEMBER tute:tutor:%s %lld", user, id );
			if ( r->type != REDIS_REPLY_INTEGER )
			{
				header( out, 500, NULL );
				reason.str = "DB Error.";
				json_out( out, &failure );
				freeReplyObject( r );
				goto err;
			}
			if ( r->type != 1 )
			{
				header( out, 400, NULL );
				reason.str = "Invalid ID.";
				json_out( out, &failure );
				freeReplyObject( r );
				goto err;
			}
		} else {
			r = redisCommand( c, "INCR tute:tute:counter" );
			if ( r->type != REDIS_REPLY_INTEGER )
			{
				header( out, 500, NULL );
				reason.str = "Could not fetch tute counter.";
				json_out( out, &failure );
				freeReplyObject( r );
				goto err;
			}
			id = r->integer;
			freeReplyObject( r );
		}

		// Save tute
		r = redisCommand( c, "HMSET tute:tute:%lld tutor %s date %s start %s finish %s", id, user, date, start, finish );
		if ( r->type == REDIS_REPLY_ERROR )
		{
			header( out, 500, NULL );
			reason.str = "Could not save tute.";
			json_out( out, &failure );
			freeReplyObject( r );
			goto err;
		}
		freeReplyObject( r );

		// Save id to tutor
		r = redisCommand( c, "SADD tute:tutor:%s %lld", user, id );
		if ( r->type == REDIS_REPLY_ERROR )
		{
			header( out, 500, NULL );
			reason.str = "Could not save tute.";
			json_out( out, &failure );
			freeReplyObject( r );
			goto err;
		}
		freeReplyObject( r );

		// Parse codes
		param *course;
		ssize_t numCourses = convert_to_params( &course, courses, ";", ":", -1 ); 
		num = numCourses;
		while ( num-- )
		{
			// convert to lower
			to_lower( course[num].name );

			// Save each code to tute id
			r = redisCommand( c, "SADD tute:tute:%lld:courses %s", id, course[num].name );
			if ( r->type == REDIS_REPLY_ERROR )
			{
				header( out, 500, NULL );
				reason.str = "Could not save tute.";
				json_out( out, &failure );
				freeReplyObject( r );
				goto courseErr;
			}
			freeReplyObject( r );

			// Add tute id to each code
			r = redisCommand( c, "SADD tute:course:%s:tutes %lld", course[num].name, id );
			if ( r->type == REDIS_REPLY_ERROR )
			{
				header( out, 500, NULL );
				reason.str = "Could not save tute.";
				json_out( out, &failure );
				freeReplyObject( r );
				goto courseErr;
			}
			freeReplyObject( r );

		}
		
		// Parse students 
		param *student;
		num = convert_to_params( &student, students, ";", ":", -1 ); 
		while ( num-- )
		{
			// Add each student to tute
			r = redisCommand( c, "SADD tute:tute:%lld:students %s", id, student[num].name );
			if ( r->type == REDIS_REPLY_ERROR )
			{
				header( out, 500, NULL );
				reason.str = "Could not save tute.";
				json_out( out, &failure );
				freeReplyObject( r );
				goto studentErr;
			}
			freeReplyObject( r );

			// Save student data
			param *data;
			ssize_t fields = convert_to_params( &data, student[num].value, ",", "|", -1 );
			if ( fields ) { 

				char *college = NULL, *first = NULL, *last = NULL;	
				while ( fields-- )
				{
					if ( !college && !strcmp( data[fields].name, "college" ) ) {
						college = data[fields].value;
					} else if ( !first && !strcmp( data[fields].name, "first" ) ) {
						first = data[fields].value;
					} else if ( !last && !strcmp( data[fields].name, "last" ) ) {
						last = data[fields].value;
					}
				}
				
				if ( college && first && last )
				{
					r = redisCommand( c, "HMSET tute:student:%s college %s first %s last %s", student[num].name, college, first, last );
					if ( r->type == REDIS_REPLY_ERROR )
					{
						header( out, 500, NULL );
						reason.str = "Could not save tute.";
						json_out( out, &failure );
						freeReplyObject( r );
						free( data );
						goto studentErr;
					}
					freeReplyObject( r );
				}

				free( data );
			}

			// Add tute id to each student
			r = redisCommand( c, "SADD tute:attendee:%s %lld", student[num].name, id );
			if ( r->type == REDIS_REPLY_ERROR )
			{
				header( out, 500, NULL );
				reason.str = "Could not save tute.";
				json_out( out, &failure );
				freeReplyObject( r );
				goto studentErr;
			}
			freeReplyObject( r );

			// Add student to each course
			ssize_t n = numCourses;
			while ( n-- )
			{
				r = redisCommand( c, "SADD tute:course:%s:students %s", course[n].name, student[num].name );
				if ( r->type == REDIS_REPLY_ERROR )
				{
					header( out, 500, NULL );
					reason.str = "Could not save tute.";
					json_out( out, &failure );
					freeReplyObject( r );
					goto studentErr;
				}
				freeReplyObject( r );
			}

		}

		// Output success
		header( out, 200, sid );
		json_out( out, &success );
		
		studentErr:
			free( student ); // free params structure
		courseErr:
			free( course );
		err:
			free( user );
			free( p ); // Free params structure
			free( s ); // Free POST stream
	}
}

int main ( int argc, char *argv[] )
{
	return init( &process );
}