Example #1
0
void ActivityWebView::goToCallback(string text)
{
    string url;

    remove_tag(text, "<", ">");
    if (text.substr(0, 7) != "http://" && text.substr(0, 8) != "https://")
        url = "http://";

    url += text;

    elm_web_uri_set(web, url.c_str());
    elm_object_focus_set(web, true);
}
static inline struct boundary_tag* absorb_right( struct boundary_tag *tag )
{
	struct boundary_tag *right = tag->split_right;

		remove_tag( right );		// Remove right from free pages.

		tag->real_size   += right->real_size;

		tag->split_right  = right->split_right;
		if ( right->split_right != NULL )
					right->split_right->split_left = tag;

	return tag;
}
Example #3
0
void FileStore::operation(Operation* operation)
{
	Selection* const selection = operation->get_selection();

	if(operation->get_delete())
	{
		//delete the selected files
		//TODO
	}
	else
	{
		//add/remove tags

		for(Tag tag: operation->get_add_tags())
			add_tag(selection, tag);

		for(Tag tag: operation->get_remove_tags())
			remove_tag(selection, tag);
	}

	delete operation;
}
void free(void *ptr)
{
	int index;
	struct boundary_tag *tag;

	if ( ptr == NULL ) return;

	liballoc_lock();


		tag = (struct boundary_tag*)((unsigned int)ptr - sizeof( struct boundary_tag ));

		if ( tag->magic != LIBALLOC_MAGIC )
		{
			liballoc_unlock();		// release the lock
			return;
		}



		// MELT LEFT...
		while ( (tag->split_left != NULL) && (tag->split_left->index >= 0) )
		{
			tag = melt_left( tag );
			remove_tag( tag );
		}

		// MELT RIGHT...
		while ( (tag->split_right != NULL) && (tag->split_right->index >= 0) )
		{
			tag = absorb_right( tag );
		}


		// Where is it going back to?
		index = getexp( tag->real_size - sizeof(struct boundary_tag) );
		if ( index < MINEXP ) index = MINEXP;

		// A whole, empty block?
		if ( (tag->split_left == NULL) && (tag->split_right == NULL) )
		{

			if ( l_completePages[ index ] == MAXCOMPLETE )
			{
				// Too many standing by to keep. Free this one.
				unsigned int pages = tag->real_size / l_pageSize;

				if ( (tag->real_size % l_pageSize) != 0 ) pages += 1;
				if ( pages < l_pageCount ) pages = l_pageCount;

				liballoc_free( tag, pages );
				liballoc_unlock();
				return;
			}


			l_completePages[ index ] += 1;	// Increase the count of complete pages.
		}


		// ..........


	insert_tag( tag, index );
	liballoc_unlock();
}
void *malloc(uint64_t size)
{
	int index;
	void *ptr;
	struct boundary_tag *tag = NULL;

	liballoc_lock();

		if ( l_initialized == 0 )
		{
			for ( index = 0; index < MAXEXP; index++ )
			{
				l_freePages[index] = NULL;
				l_completePages[index] = 0;
			}
			l_initialized = 1;
		}

		index = getexp( size ) + MODE;
		if ( index < MINEXP ) index = MINEXP;


		// Find one big enough.
			tag = l_freePages[ index ];				// Start at the front of the list.
			while ( tag != NULL )
			{
					// If there's enough space in this tag.
				if ( (tag->real_size - sizeof(struct boundary_tag))
								>= (size + sizeof(struct boundary_tag) ) )
				{
					break;
				}

				tag = tag->next;
			}


			// No page found. Make one.
			if ( tag == NULL )
			{
				if ( (tag = allocate_new_tag( size )) == NULL )
				{
					liballoc_unlock();
					return NULL;
				}

				index = getexp( tag->real_size - sizeof(struct boundary_tag) );
			}
			else
			{
				remove_tag( tag );

				if ( (tag->split_left == NULL) && (tag->split_right == NULL) )
					l_completePages[ index ] -= 1;
			}

		// We have a free page.  Remove it from the free pages list.

		tag->size = size;

		// Removed... see if we can re-use the excess space.

		unsigned int remainder = tag->real_size - size - sizeof( struct boundary_tag ) * 2; // Support a new tag + remainder

		if ( ((int)(remainder) > 0) /*&& ( (tag->real_size - remainder) >= (1<<MINEXP))*/ )
		{
			int childIndex = getexp( remainder );

			if ( childIndex >= 0 )
			{
				struct boundary_tag *new_tag = split_tag( tag );

				new_tag = new_tag;	// Get around the compiler warning about unused variables.
			}
		}



	ptr = (void*)((unsigned int)tag + sizeof( struct boundary_tag ) );

	liballoc_unlock();
	return ptr;
}
Example #6
0
   /** finds tags that have been added or removed or updated */
   void update_tags( const comment_object& c )const {
      try {

      auto hot = calculate_hot(c);

      comment_metadata meta;

      if( c.json_metadata.size() ){
         meta = fc::json::from_string( c.json_metadata ).as<comment_metadata>();
      }

      set<string> lower_tags;
      for( const auto& tag : meta.tags )
         lower_tags.insert(fc::to_lower( tag ) );

      lower_tags.insert( fc::to_lower(c.category) );


      /// the universal tag applies to everything safe for work or nsfw with a positive payout
      if( c.net_rshares >= 0 ||
          (lower_tags.find( "spam" ) == lower_tags.end() &&
           lower_tags.find( "nsfw" ) == lower_tags.end() &&
           lower_tags.find( "test" ) == lower_tags.end() )  )
      {
         lower_tags.insert( string() ); /// add it to the universal tag
      }

      meta.tags = lower_tags; /// TODO: std::move???

      const auto& comment_idx = _db.get_index_type<tag_index>().indices().get<by_comment>();
      auto citr = comment_idx.lower_bound( c.id );

      map<string, const tag_object*> existing_tags;
      vector<const tag_object*> remove_queue;
      while( citr != comment_idx.end() && citr->comment == c.id ) {
         const tag_object* tag = &*citr;
         ++citr;
         if( meta.tags.find( tag->tag ) == meta.tags.end() ) {
            remove_queue.push_back(tag);
         } else {
            existing_tags[tag->tag] = tag;
         }
      }

      for( const auto& tag : meta.tags ) {
         auto existing = existing_tags.find(tag);
         if( existing == existing_tags.end() ) {
            create_tag( tag, c, hot );
         } else {
            update_tag( *existing->second, c, hot );
         }
      }

      for( const auto& item : remove_queue )
         remove_tag(*item);

      if( c.parent_author.size() )
      {
         update_tags( _db.get_comment( c.parent_author, c.parent_permlink ) );
      }
     } FC_CAPTURE_LOG_AND_RETHROW( (c) )
   }
Example #7
0
void free(void *ptr)
{
	int index;
	struct boundary_tag *tag;

	if ( ptr == NULL ) return;

	liballoc_lock();


		tag = (struct boundary_tag*)((unsigned int)ptr - sizeof( struct boundary_tag ));

		if ( tag->magic != LIBALLOC_MAGIC )
		{
			liballoc_unlock();		// release the lock
			return;
		}



		#ifdef DEBUG
		l_inuse -= tag->size;
		printf("free: %x, %i, %i\n", ptr, (int)l_inuse / 1024, (int)l_allocated / 1024 );
		#endif


		// MELT LEFT...
		while ( (tag->split_left != NULL) && (tag->split_left->index >= 0) )
		{
			#ifdef DEBUG
			printf("Melting tag left into available memory. Left was %i, becomes %i (%i)\n", tag->split_left->real_size, tag->split_left->real_size + tag->real_size, tag->split_left->real_size );
			#endif
			tag = melt_left( tag );
			remove_tag( tag );
		}

		// MELT RIGHT...
		while ( (tag->split_right != NULL) && (tag->split_right->index >= 0) )
		{
			#ifdef DEBUG
			printf("Melting tag right into available memory. This was was %i, becomes %i (%i)\n", tag->real_size, tag->split_right->real_size + tag->real_size, tag->split_right->real_size );
			#endif
			tag = absorb_right( tag );
		}


		// Where is it going back to?
		index = getexp( tag->real_size - sizeof(struct boundary_tag) );
		if ( index < MINEXP ) index = MINEXP;

		// A whole, empty block?
		if ( (tag->split_left == NULL) && (tag->split_right == NULL) )
		{

			if ( l_completePages[ index ] == MAXCOMPLETE )
			{
				// Too many standing by to keep. Free this one.
				unsigned int pages = tag->real_size / l_pageSize;

				if ( (tag->real_size % l_pageSize) != 0 ) pages += 1;
				if ( pages < l_pageCount ) pages = l_pageCount;

				liballoc_free( tag, pages );

				#ifdef DEBUG
				l_allocated -= pages * l_pageSize;
				printf("Resource freeing %x of %i pages\n", tag, pages );
				dump_array();
				#endif

				liballoc_unlock();
				return;
			}


			l_completePages[ index ] += 1;	// Increase the count of complete pages.
		}


		// ..........


		insert_tag( tag, index );

	#ifdef DEBUG
	printf("Returning tag with %i bytes (requested %i bytes), which has exponent: %i\n", tag->real_size, tag->size, index );
	dump_array();
	#endif

	liballoc_unlock();
}
Example #8
0
void *malloc(size_t size)
{
	int index;
	void *ptr;
	struct boundary_tag *tag = NULL;

	liballoc_lock();

		if ( l_initialized == 0 )
		{
			#ifdef DEBUG
			printf("%s\n","liballoc initializing.");
			#endif
			for ( index = 0; index < MAXEXP; index++ )
			{
				l_freePages[index] = NULL;
				l_completePages[index] = 0;
			}
			l_initialized = 1;
		}

		index = getexp( size ) + MODE;
		if ( index < MINEXP ) index = MINEXP;


		// Find one big enough.
			tag = l_freePages[ index ];				// Start at the front of the list.
			while ( tag != NULL )
			{
					// If there's enough space in this tag.
				if ( (tag->real_size - sizeof(struct boundary_tag))
								>= (size + sizeof(struct boundary_tag) ) )
				{
					#ifdef DEBUG
					printf("Tag search found %i >= %i\n",(tag->real_size - sizeof(struct boundary_tag)), (size + sizeof(struct boundary_tag) ) );
					#endif
					break;
				}

				tag = tag->next;
			}


			// No page found. Make one.
			if ( tag == NULL )
			{
				if ( (tag = allocate_new_tag( size )) == NULL )
				{
					liballoc_unlock();
					return NULL;
				}

				index = getexp( tag->real_size - sizeof(struct boundary_tag) );
			}
			else
			{
				remove_tag( tag );

				if ( (tag->split_left == NULL) && (tag->split_right == NULL) )
					l_completePages[ index ] -= 1;
			}

		// We have a free page.  Remove it from the free pages list.

		tag->size = size;

		// Removed... see if we can re-use the excess space.

		#ifdef DEBUG
		printf("Found tag with %i bytes available (requested %i bytes, leaving %i), which has exponent: %i (%i bytes)\n", tag->real_size - sizeof(struct boundary_tag), size, tag->real_size - size - sizeof(struct boundary_tag), index, 1<<index );
		#endif

		unsigned int remainder = tag->real_size - size - sizeof( struct boundary_tag ) * 2; // Support a new tag + remainder

		if ( ((int)(remainder) > 0) /*&& ( (tag->real_size - remainder) >= (1<<MINEXP))*/ )
		{
			int childIndex = getexp( remainder );

			if ( childIndex >= 0 )
			{
				#ifdef DEBUG
				printf("Seems to be splittable: %i >= 2^%i .. %i\n", remainder, childIndex, (1<<childIndex) );
				#endif

				struct boundary_tag *new_tag = split_tag( tag );

				new_tag = new_tag;	// Get around the compiler warning about unused variables.

				#ifdef DEBUG
				printf("Old tag has become %i bytes, new tag is now %i bytes (%i exp)\n", tag->real_size, new_tag->real_size, new_tag->index );
				#endif
			}
		}



	ptr = (void*)((unsigned int)tag + sizeof( struct boundary_tag ) );



	#ifdef DEBUG
	l_inuse += size;
	printf("malloc: %x,  %i, %i\n", ptr, (int)l_inuse / 1024, (int)l_allocated / 1024 );
	dump_array();
	#endif


	liballoc_unlock();
	return ptr;
}
int main(int argc, char **argv) {
    const char *filename = "/system/build.prop";
    const char *propname = "ro.build.fingerprint";
    const char *tag = NULL;
    int do_remove = 0, do_number = 0;

    int opt;
    while ((opt = getopt(argc, argv, "f:p:rn")) != -1) {
        switch (opt) {
        case 'f': filename = optarg; break;
        case 'p': propname = optarg; break;
        case 'r': do_remove = 1; break;
        case 'n': do_number = 1; break;
        case '?': return 2;
        }
    }

    if (argc != optind + 1) {
        fprintf(stderr,
            "usage: add-property-tag [flags] tag-to-add\n"
            "flags: -f /dir/file.prop (default /system/build.prop)\n"
            "       -p prop.name (default ro.build.fingerprint)\n"
            "       -r (if set, remove the tag rather than adding it)\n"
            "       -n (if set, add and increment a number after the tag)\n");
        return 2;
    }

    tag = argv[optind];
    FILE *input = fopen(filename, "r");
    if (input == NULL) {
        fprintf(stderr, "can't read %s: %s\n", filename, strerror(errno));
        return 1;
    }

    char tmpname[PATH_MAX];
    snprintf(tmpname, sizeof(tmpname), "%s.tmp", filename);
    FILE *output = fopen(tmpname, "w");
    if (output == NULL) {
        fprintf(stderr, "can't write %s: %s\n", tmpname, strerror(errno));
        return 1;
    }

    int found = 0;
    char line[4096];
    while (fgets(line, sizeof(line), input)) {
        if (!should_tag(line, propname)) {
            fputs(line, output);  // Pass through unmodified
        } else {
            found = 1;
            int number = remove_tag(line, tag);
            if (do_remove) {
                fputs(line, output);  // Remove the tag but don't re-add it
            } else {
                write_tagged(output, line, tag, number + do_number);
            }
        }
    }

    fclose(input);
    fclose(output);

    if (!found) {
        fprintf(stderr, "property %s not found in %s\n", propname, filename);
        remove(tmpname);
        return 1;
    }

    if (rename(tmpname, filename)) {
        fprintf(stderr, "can't rename %s to %s: %s\n",
            tmpname, filename, strerror(errno));
        remove(tmpname);
        return 1;
    }

    return 0;
}
Example #10
0
   /** finds tags that have been added or removed or updated */
   void update_tags( const comment_object& c )const {
      try {

      auto hot = calculate_hot(c);

      comment_metadata meta;

      if( c.json_metadata.size() )
      {
         try
         {
            meta = fc::json::from_string( c.json_metadata ).as<comment_metadata>();
         }
         catch( const fc::exception& e )
         {
            // Do nothing on malformed json_metadata
         }
      }

      set<string> lower_tags;
      for( const auto& tag : meta.tags )
         lower_tags.insert(fc::to_lower( tag ) );

      lower_tags.insert( fc::to_lower(c.category) );


      bool safe_for_work = false;
      /// the universal tag applies to everything safe for work or nsfw with a positive payout
      if( c.net_rshares >= 0 ||
          (lower_tags.find( "spam" ) == lower_tags.end() &&
           lower_tags.find( "nsfw" ) == lower_tags.end() &&
           lower_tags.find( "test" ) == lower_tags.end() )  )
      {
         safe_for_work = true;
         lower_tags.insert( string() ); /// add it to the universal tag
      }

      meta.tags = lower_tags; /// TODO: std::move???
      if( meta.tags.size() > 7 ) {
         //wlog( "ignoring post ${a} because it has ${n} tags",("a", c.author + "/"+c.permlink)("n",meta.tags.size()));
         if( safe_for_work )
            meta.tags = set<string>({"", c.parent_permlink});
         else
            meta.tags.clear();
      }


      const auto& comment_idx = _db.get_index_type<tag_index>().indices().get<by_comment>();
      auto citr = comment_idx.lower_bound( c.id );

      map<string, const tag_object*> existing_tags;
      vector<const tag_object*> remove_queue;
      while( citr != comment_idx.end() && citr->comment == c.id ) {
         const tag_object* tag = &*citr;
         ++citr;
         if( meta.tags.find( tag->tag ) == meta.tags.end()  ) {
            remove_queue.push_back(tag);
         } else {
            existing_tags[tag->tag] = tag;
         }
      }

      for( const auto& tag : meta.tags ) {
         auto existing = existing_tags.find(tag);
         if( existing == existing_tags.end() ) {
            create_tag( tag, c, hot );
         } else {
            update_tag( *existing->second, c, hot );
         }
      }

      for( const auto& item : remove_queue )
         remove_tag(*item);

      if( c.parent_author.size() )
      {
         update_tags( _db.get_comment( c.parent_author, c.parent_permlink ) );
      }
     } FC_CAPTURE_LOG_AND_RETHROW( (c) )
   }
int Sn_Syntax_Highlight(ClientData clientData, Tcl_Interp * interp, int argc, char **argv)
{
	register TkText *textPtr = NULL;
	Tcl_CmdInfo infoPtr;
	int result = TCL_OK;
	int del = 0;
	char *argv0 = argv[0];
	int wargc;
	char *wargv[10];
	char *language;
	char *idx1;
	char *idx2;
	char *text_widget;
	char endpos[TK_POS_CHARS];
	char begpos[TK_POS_CHARS];
	int val;
	int (*high_func) () = NULL;
	void (*flush_lex_scanner) () = NULL;
	void (*high_init_func) (int ms, int lineno, int charno, void (**func) (), void *idx1, void *idx2) = NULL;
	Tcl_CmdProc *text_proc;
	int update = 0;
	TkTextIndex lex_index1;
	TkTextIndex lex_index2;
	TkTextIndex lex_end_index;
	char prev_begpos[TK_POS_CHARS];
	int lex_buf_size = 0;

	eos_read = 0;

	while (argc > 1 && argv[1][0] == '-') {
		if(strncmp(argv[1], "-delete", 5) == 0) {
			del = 1;
			argc--;
			argv++;
		} else if(strncmp(argv[1], "-delall", 5) == 0) {
			del = -1;
			argc--;
			argv++;
		} else if(strncmp(argv[1], "-update", 4) == 0) {
			lex_buf_size = 256;	/* It is probably not necessary to fill */
			/* the complete lex buffer. */
			update = 1;
			argc--;
			argv++;
		} else
			break;
	}

	if(argc != 4 && argc != 5) {
		Tcl_AppendResult(interp, "wrong # args: should be \"", argv0, " ?-delete? ?-delall? language text_widget index1 ?index2?", NULL);

		return TCL_ERROR;
	}

	language = argv[1];
	text_widget = argv[2];
	idx1 = argv[3];
	idx2 = argc == 5 ? argv[4] : idx1;

	LOGGER((LOGFP, "highlight lang: <%s> text: <%s> idx1: <%s> idx2: <%s>\n", language, text_widget, idx1, idx2));
	if(strcmp(language, "tcl") == 0) {
		high_func = tcl_highlight_lex;
		high_init_func = tcl_highlight_init_func;
	} else if(strcmp(language, "c++") == 0) {
		high_func = c_highlight_lex;
		high_init_func = c_highlight_init_func;
	} else if(strcmp(language, "java") == 0) {
		high_func = java_highlight_lex;
		high_init_func = java_highlight_init_func;
	} else if(strcmp(language, "chill") == 0) {
		high_func = ch_highlight_lex;
		high_init_func = ch_highlight_init_func;
	} else if(strcmp(language, "verilog") == 0) {
		high_func = verilog_highlight_lex;
		high_init_func = verilog_highlight_init_func;
	} else if(strcmp(language, "python") == 0) {
		high_func = py_highlight_lex;
		high_init_func = py_highlight_init_func;
	}

	if(!high_func) {
		return TCL_OK;
	}

	if(!Tcl_GetCommandInfo(interp, text_widget, &infoPtr)) {
		Tcl_AppendResult(interp, "wrong # \"", text_widget, "\" does not exist", (char *) NULL);
		return TCL_ERROR;
	}

	textPtr = (TkText *) infoPtr.clientData;
	Tcl_Preserve((ClientData) textPtr);
	text_proc = (Tcl_CmdProc *) infoPtr.proc;

	if(del) {
		remove_tag(textPtr, interp, text_widget, del, idx1, idx2);
	}

	TkTextGetIndex(interp, textPtr, "end", &lex_end_index);

	if(TkTextGetIndex(interp, textPtr, idx1, &lex_index1) != TCL_OK || TkTextGetIndex(interp, textPtr, idx2, &lex_index2) != TCL_OK) {
		result = TCL_ERROR;
		goto done;
	}
	if(TkTextIndexCmp(&lex_index1, &lex_index2) >= 0) {
		result = TCL_OK;
		goto done;
	}
	high_init_func(lex_buf_size, TkBTreeLineIndex(lex_index1.linePtr) + 1,
		       lex_index1.CHARINDEX, &flush_lex_scanner, (void *) &lex_index1, (void *) &lex_end_index);

	wargc = 0;
	wargv[wargc++] = text_widget;
	wargv[wargc++] = "tag";
	wargv[wargc++] = "add";
	wargv[wargc++] = NULL;
	wargv[wargc++] = begpos;
	wargv[wargc++] = endpos;

	strcpy(prev_begpos, idx1);
	while ((val = (*high_func) ()) != 0) {
		sprintf(begpos, "%d.%d", paf_high_pos.beg_lineno, paf_high_pos.beg_charno);
		sprintf(endpos, "%d.%d", paf_high_pos.end_lineno, paf_high_pos.end_charno);
		wargv[3] = high_tag_names[val];

		if(update) {
			int tag_argc = 0;
			char *tag_argv[10];
			char *p_end;
			int cou;
			int tag_off;

			tag_argv[tag_argc++] = text_widget;
			tag_argv[tag_argc++] = "tag";
			tag_argv[tag_argc++] = "prevrange";
			tag_off = tag_argc;
			tag_argv[tag_argc++] = NULL;
			tag_argv[tag_argc++] = endpos;
			for (cou = 1; cou <= PAF_HIGH_STRING; cou++) {
				tag_argv[tag_off] = high_tag_names[cou];
				Tcl_ResetResult(interp);
				TkTextTagCmd(textPtr, interp, tag_argc, tag_argv);

				p_end = strchr(interp->result, ' ');
				/* Check whether it is synchronized ! */
				if(p_end && strcmp(p_end + 1, endpos) == 0) {
					eos_read = 1;
					/* It will get flex recognized that no further
					 * input is available. */
					flush_lex_scanner();
					break;
				}
			}
			LOGGER((LOGFP, "Add %s %d %s %s\n", high_tag_names[val], val, begpos, endpos));
		}
		if(update) {
			int tag_argc = 0;
			char *tag_argv[10];
			int cou;
			int tag_off;

			tag_argv[tag_argc++] = text_widget;
			tag_argv[tag_argc++] = "tag";
			tag_argv[tag_argc++] = "remove";
			tag_off = tag_argc;
			tag_argv[tag_argc++] = NULL;
			tag_argv[tag_argc++] = prev_begpos;
			tag_argv[tag_argc++] = endpos;

			for (cou = 1; cou <= PAF_HIGH_STRING; cou++) {
				tag_argv[tag_off] = high_tag_names[cou];
				TkTextTagCmd(textPtr, interp, tag_argc, tag_argv);
			}
			strcpy(prev_begpos, endpos);
		}
		TkTextTagCmd(textPtr, interp, wargc, wargv);
	}
done:
	Tcl_Release((ClientData) textPtr);

	return result;
}
Example #12
0
/* Gets a reply from the cache */
static int
cache_daap_query_get(struct cache_command *cmd)
{
#define Q_TMPL "SELECT reply FROM replies WHERE query = ?;"
  sqlite3_stmt *stmt;
  char *query;
  int datalen;
  int ret;

  query = cmd->arg.query;
  remove_tag(query, "session-id");
  remove_tag(query, "revision-number");

  // Look in the DB
  ret = sqlite3_prepare_v2(g_db_hdl, Q_TMPL, -1, &stmt, 0);
  if (ret != SQLITE_OK)
    {
      DPRINTF(E_LOG, L_CACHE, "Error preparing query for cache update: %s\n", sqlite3_errmsg(g_db_hdl));
      free(query);
      return -1;
    }

  sqlite3_bind_text(stmt, 1, query, -1, SQLITE_STATIC);

  ret = sqlite3_step(stmt);
  if (ret != SQLITE_ROW)  
    {
      if (ret != SQLITE_DONE)
	DPRINTF(E_LOG, L_CACHE, "Error stepping query for cache update: %s\n", sqlite3_errmsg(g_db_hdl));
      goto error_get;
    }

  datalen = sqlite3_column_bytes(stmt, 0);

  if (!cmd->arg.evbuf)
    {
      DPRINTF(E_LOG, L_CACHE, "Error: DAAP reply evbuffer is NULL\n");
      goto error_get;
    }

  ret = evbuffer_add(cmd->arg.evbuf, sqlite3_column_blob(stmt, 0), datalen);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_CACHE, "Out of memory for DAAP reply evbuffer\n");
      goto error_get;
    }

  ret = sqlite3_finalize(stmt);
  if (ret != SQLITE_OK)
    DPRINTF(E_LOG, L_CACHE, "Error finalizing query for getting cache: %s\n", sqlite3_errmsg(g_db_hdl));

  DPRINTF(E_INFO, L_CACHE, "Cache hit: %s\n", query);

  free(query);

  return 0;

 error_get:
  sqlite3_finalize(stmt);
  free(query);
  return -1;  
#undef Q_TMPL
}
Example #13
0
/* Adds the query to the list of queries for which we will build and cache a reply */
static int
cache_daap_query_add(struct cache_command *cmd)
{
#define Q_TMPL "INSERT OR REPLACE INTO queries (user_agent, query, msec, timestamp) VALUES ('%q', '%q', %d, %" PRIi64 ");"
#define Q_CLEANUP "DELETE FROM queries WHERE id NOT IN (SELECT id FROM queries ORDER BY timestamp DESC LIMIT 20);"
  char *query;
  char *errmsg;
  int ret;

  if (!cmd->arg.ua)
    {
      DPRINTF(E_LOG, L_CACHE, "Couldn't add slow query to cache, unknown user-agent\n");

      goto error_add;
    }

  // Currently we are only able to pre-build and cache these reply types
  if ( (strncmp(cmd->arg.query, "/databases/1/containers/", strlen("/databases/1/containers/")) != 0) &&
       (strncmp(cmd->arg.query, "/databases/1/groups?", strlen("/databases/1/groups?")) != 0) &&
       (strncmp(cmd->arg.query, "/databases/1/items?", strlen("/databases/1/items?")) != 0) &&
       (strncmp(cmd->arg.query, "/databases/1/browse/", strlen("/databases/1/browse/")) != 0) )
    goto error_add;

  remove_tag(cmd->arg.query, "session-id");
  remove_tag(cmd->arg.query, "revision-number");

  query = sqlite3_mprintf(Q_TMPL, cmd->arg.ua, cmd->arg.query, cmd->arg.msec, (int64_t)time(NULL));
  if (!query)
    {
      DPRINTF(E_LOG, L_CACHE, "Out of memory making query string.\n");

      goto error_add;
    }

  ret = sqlite3_exec(g_db_hdl, query, NULL, NULL, &errmsg);
  if (ret != SQLITE_OK)
    {
      DPRINTF(E_LOG, L_CACHE, "Error adding query to query list: %s\n", errmsg);

      sqlite3_free(query);
      sqlite3_free(errmsg);
      goto error_add;
    }

  sqlite3_free(query);

  DPRINTF(E_INFO, L_CACHE, "Slow query (%d ms) added to cache: '%s' (user-agent: '%s')\n", cmd->arg.msec, cmd->arg.query, cmd->arg.ua);

  free(cmd->arg.ua);
  free(cmd->arg.query);

  // Limits the size of the cache to only contain replies for 20 most recent queries
  ret = sqlite3_exec(g_db_hdl, Q_CLEANUP, NULL, NULL, &errmsg);
  if (ret != SQLITE_OK)
    {
      DPRINTF(E_LOG, L_CACHE, "Error cleaning up query list before update: %s\n", errmsg);
      sqlite3_free(errmsg);
      return -1;
    }

  cache_daap_trigger();

  return 0;

 error_add:
  if (cmd->arg.ua)
    free(cmd->arg.ua);

  if (cmd->arg.query)
    free(cmd->arg.query);

  return -1;
#undef Q_CLEANUP
#undef Q_TMPL
}