func NewAdData() *AdData {
	self := new(AdData)
	var err error
	self.votes_good, err = helpers.NewFileBackedMap("votes_good", 1024)
	if err != nil {
		panic(err)
	}
	self.votes_fraudulent, err = helpers.NewFileBackedMap("votes_fraudulent", 1024)
	if err != nil {
		panic(err)
	}
	self.votes_taxing, err = helpers.NewFileBackedMap("votes_taxing", 1024)
	if err != nil {
		panic(err)
	}
	self.votes_malicious, err = helpers.NewFileBackedMap("votes_malicious", 1024)
	if err != nil {
		panic(err)
	}
	self.voted_ad_type, err = helpers.NewFileBackedMap("voted_ad_type", 1048576)
	if err != nil {
		panic(err)
	}

	return self
}
func responseVoteForAd(w http.ResponseWriter, parameters map[string]string) {
	// Get the arguments
	ad_id := parameters["vote_ad"]
	ad_type := parameters["ad_type"]
	user_id := parameters["user_id"]

	// Figure out which type of vote it will be
	var all_ads *helpers.FileBackedMap
	var user_vote_type uint64 = AD_UNKNOWN
	switch ad_type {
	case "good":
		all_ads = g_all_ads.votes_good
		user_vote_type = AD_GOOD
	case "fraudulent":
		all_ads = g_all_ads.votes_fraudulent
		user_vote_type = AD_FRAUDULENT
	case "taxing":
		all_ads = g_all_ads.votes_taxing
		user_vote_type = AD_TAXING
	case "malicious":
		all_ads = g_all_ads.votes_malicious
		user_vote_type = AD_MALICIOUS
	default:
		http.Error(w, "Invalid ad_type", http.StatusBadRequest)
		return
	}

	// Initialize space for this user's ads
	user_ads, ok := g_user_ads[user_id]
	if !ok {
		user_ads, _ = helpers.NewFileBackedMap("user_"+user_id, 1024)
		g_user_ads[user_id] = user_ads
	}

	// Remove the previous vote, if there already is one for this ad
	if vote_type, ok := user_ads.Get(ad_id); ok {
		// FIXME: We don't really need to remove this, since we Set it again on the new vote.
		err := user_ads.Remove(ad_id)
		if err != nil {
			http.Error(w, "Failed to remove ad", http.StatusInternalServerError)
			log.Printf("%v\n", err)
			return
		}

		switch vote_type {
		case AD_GOOD:
			g_all_ads.votes_good.Decrement(ad_id)
		case AD_FRAUDULENT:
			g_all_ads.votes_fraudulent.Decrement(ad_id)
		case AD_TAXING:
			g_all_ads.votes_taxing.Decrement(ad_id)
		case AD_MALICIOUS:
			g_all_ads.votes_malicious.Decrement(ad_id)
		}
	}

	// Cast the new vote
	votes := all_ads.Increment(ad_id)
	err := user_ads.Set(ad_id, user_vote_type)
	if err != nil {
		http.Error(w, "Failed to set ad", http.StatusInternalServerError)
		log.Printf("%v\n", err)
		return
	}

	// Update the voted ad type
	err = updateVotedAdType(ad_id)
	if err != nil {
		http.Error(w, "Failed to update ad voted type", http.StatusInternalServerError)
		log.Printf("%v\n", err)
		return
	}

	// Save the time that the user voted
	g_user_ids[user_id] = time.Now()

	// Return the response
	fmt.Fprintf(w, "ad_id:%s, ad_type:%s, votes:%d\n", ad_id, ad_type, votes)
}