package lib import ( "bytes" "encoding/json" ) //topicPointer and textPointer should not be exported //mb move tweet reconstruction to dbRead from servers type Tweet struct { TopicPointer string TextPointer int Topics []string Text string RoundPosted int } var dbR = make(map[string][]Tweet) var archive = make(map[string][]Tweet) //has to be dividable by 32 var minimumBlockSize int const roundsBeforeArchiving = 3 var topicList []string var archiveTopicList []string func NewEntries(inputTweets []Tweet, whereTo int) { tmpdb := dbR if whereTo == 1 { tmpdb = archive } var position int = 0 for _, tweet := range inputTweets { for index := range tweet.Topics { //new topic if _, ok := tmpdb[tweet.Topics[index]]; !ok { if whereTo == 0 { topicList = append(topicList, tweet.Topics[index]) } else { archiveTopicList = append(archiveTopicList, tweet.Topics[index]) } } //new tweet if index == 0 { position = len(tmpdb[tweet.Topics[0]]) tmpdb[tweet.Topics[index]] = append(tmpdb[tweet.Topics[0]], tweet) } else { //known tweet //setting pointer for all other Topics topic := tweet.Topics[index] tweet.TopicPointer = tweet.Topics[0] tweet.TextPointer = position tweet.Topics = nil tweet.Text = "" tmpdb[topic] = append(tmpdb[topic], tweet) } } } if whereTo == 0 { dbR = tmpdb } else { archive = tmpdb } } //todo! add round to pirquery only get tweets that have been posted from that round onward func GetTweets(pirQuery []byte, dataLength int, whereFrom int) []byte { tmpdb := dbR if whereFrom == 1 { tmpdb = archive } minimumBlockSize = dataLength * maxTweetAmount(whereFrom) var wantedTopics = getNamesForTopics(pirQuery, whereFrom) tweetsToReturn := make([][]Tweet, len(wantedTopics)) for index, wantedTopic := range wantedTopics { for _, tweet := range tmpdb[wantedTopic] { //new Tweet if tweet.Text != "" { tweet.RoundPosted = 0 tweetsToReturn[index] = append(tweetsToReturn[index], tweet) } else { //"copied" tweet //find tweet with pointers tweet = tmpdb[tweet.TopicPointer][tweet.TextPointer] tweet.RoundPosted = 0 tweetsToReturn[index] = append(tweetsToReturn[index], tweet) } } } return tweetsToByteArray(tweetsToReturn) } func maxTweetAmount(whereFrom int) int { tmpdb := dbR if whereFrom == 1 { tmpdb = archive } var max int = 0 for i := range tmpdb { nrOfTweets := len(dbR[i]) if nrOfTweets > max { max = nrOfTweets } } return max } func getNamesForTopics(wantedIndices []byte, whereFrom int) []string { var topicNames []string tmpTopicList := topicList if whereFrom == 1 { tmpTopicList = archiveTopicList } for index, element := range wantedIndices { if element == 1 { topicNames = append(topicNames, tmpTopicList[index]) } } return topicNames } //transform struct to byte array for sending func tweetsToByteArray(tweetsToReturn [][]Tweet) []byte { tweetsAsBytes := make([]byte, minimumBlockSize) for _, block := range tweetsToReturn { var tweetToAppend []byte for _, tweet := range block { for _, topic := range tweet.Topics { tweetToAppend = append(tweetToAppend, []byte(topic)...) tweetToAppend = append(tweetToAppend, ","...) } //replaces last with ";", bc there is text following and not another topic tweetToAppend = tweetToAppend[:len(tweetToAppend)-1] tweetToAppend = append(tweetToAppend, []byte(";")[0]) tweetToAppend = append(tweetToAppend, []byte(tweet.Text)...) tweetToAppend = append(tweetToAppend, []byte(";")[0]) } //adds padding for i := len(tweetToAppend); i < minimumBlockSize; i++ { tweetToAppend = append(tweetToAppend, []byte(";")[0]) } Xor(tweetToAppend, tweetsAsBytes) } return tweetsAsBytes } //see func name func GetTopicList(whereFrom int) ([]byte, int) { tmpTopicList := topicList if whereFrom == 1 { tmpTopicList = archiveTopicList } if (len(tmpTopicList)) == 0 { return nil, 0 } topicByteArray := new(bytes.Buffer) json.NewEncoder(topicByteArray).Encode(tmpTopicList) return topicByteArray.Bytes(), len(tmpTopicList) } //iterates through full dbR and moves old tweets to archive func CleanUpdbR(round int) { var tweetsToArchive []Tweet for j := range dbR { tweets := dbR[j] for i := len(tweets) - 1; i >= 0; i-- { if round-roundsBeforeArchiving == tweets[i].RoundPosted { //only adds the tweet to the archive when there is text if tweets[i].Text != "" { tweetsToArchive = append(tweetsToArchive, tweets[i]) } //delets the tweet from the array tweets = append(tweets[:i], tweets[i+1:]...) } } dbR[j] = tweets } NewEntries(tweetsToArchive, 1) }