databaseRead.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. package lib
  2. import (
  3. "bytes"
  4. "crypto/rand"
  5. "encoding/json"
  6. )
  7. //topicPointer and textPointer should not be exported
  8. //mb move tweet reconstruction to dbRead from servers
  9. type Tweet struct {
  10. TopicPointer string
  11. TextPointer int
  12. Topics []string
  13. Text string
  14. RoundPosted int
  15. }
  16. var dbR = make(map[string][]Tweet)
  17. var archive = make(map[string][]Tweet)
  18. //has to be dividable by 32
  19. var minimumBlockSize int
  20. const roundsBeforeArchiving = 300
  21. var topicList []string
  22. var archiveTopicList []string
  23. func NewEntries(inputTweets []Tweet, whereTo int) {
  24. tmpdb := dbR
  25. if whereTo == 1 {
  26. tmpdb = archive
  27. }
  28. var position int = 0
  29. for _, tweet := range inputTweets {
  30. for index := range tweet.Topics {
  31. //new topic
  32. if _, ok := tmpdb[tweet.Topics[index]]; !ok {
  33. if whereTo == 0 {
  34. topicList = append(topicList, tweet.Topics[index])
  35. } else {
  36. archiveTopicList = append(archiveTopicList, tweet.Topics[index])
  37. }
  38. }
  39. //new tweet
  40. if index == 0 {
  41. position = len(tmpdb[tweet.Topics[0]])
  42. tmpdb[tweet.Topics[index]] = append(tmpdb[tweet.Topics[0]], tweet)
  43. } else {
  44. //known tweet
  45. //setting pointer for all other Topics
  46. topic := tweet.Topics[index]
  47. tweet.TopicPointer = tweet.Topics[0]
  48. tweet.TextPointer = position
  49. tweet.Topics = nil
  50. tweet.Text = ""
  51. tmpdb[topic] = append(tmpdb[topic], tweet)
  52. }
  53. }
  54. }
  55. if whereTo == 0 {
  56. dbR = tmpdb
  57. } else {
  58. archive = tmpdb
  59. }
  60. }
  61. //todo! add round to pirquery only get tweets that have been posted from that round onward
  62. func GetTweets(pirQuery []byte, dataLength int, whereFrom int) []byte {
  63. tmpdb := dbR
  64. if whereFrom == 1 {
  65. tmpdb = archive
  66. }
  67. minimumBlockSize = dataLength * maxTweetAmount(whereFrom)
  68. var wantedTopics = getNamesForTopics(pirQuery, whereFrom)
  69. tweetsToReturn := make([][]Tweet, len(wantedTopics))
  70. for index, wantedTopic := range wantedTopics {
  71. for _, tweet := range tmpdb[wantedTopic] {
  72. //new Tweet
  73. if tweet.Text != "" {
  74. tweet.RoundPosted = 0
  75. tweetsToReturn[index] = append(tweetsToReturn[index], tweet)
  76. } else {
  77. //"copied" tweet
  78. //find tweet with pointers
  79. tweet = tmpdb[tweet.TopicPointer][tweet.TextPointer]
  80. tweet.RoundPosted = 0
  81. tweetsToReturn[index] = append(tweetsToReturn[index], tweet)
  82. }
  83. }
  84. }
  85. return tweetsToByteArray(tweetsToReturn)
  86. }
  87. func maxTweetAmount(whereFrom int) int {
  88. tmpdb := dbR
  89. if whereFrom == 1 {
  90. tmpdb = archive
  91. }
  92. var max int = 0
  93. for i := range tmpdb {
  94. nrOfTweets := len(dbR[i])
  95. if nrOfTweets > max {
  96. max = nrOfTweets
  97. }
  98. }
  99. return max
  100. }
  101. func getNamesForTopics(wantedIndices []byte, whereFrom int) []string {
  102. var topicNames []string
  103. tmpTopicList := topicList
  104. if whereFrom == 1 {
  105. tmpTopicList = archiveTopicList
  106. }
  107. for index, element := range wantedIndices {
  108. if element == 1 {
  109. topicNames = append(topicNames, tmpTopicList[index])
  110. }
  111. }
  112. return topicNames
  113. }
  114. //transform struct to byte array for sending
  115. func tweetsToByteArray(tweetsToReturn [][]Tweet) []byte {
  116. tweetsAsBytes := make([]byte, minimumBlockSize)
  117. for _, block := range tweetsToReturn {
  118. var tweetToAppend []byte
  119. for _, tweet := range block {
  120. for _, topic := range tweet.Topics {
  121. tweetToAppend = append(tweetToAppend, []byte(topic)...)
  122. tweetToAppend = append(tweetToAppend, ","...)
  123. }
  124. //replaces last "," with ";" bc there is text following and not another topic
  125. tweetToAppend = tweetToAppend[:len(tweetToAppend)-1]
  126. tweetToAppend = append(tweetToAppend, []byte(";")[0])
  127. tweetToAppend = append(tweetToAppend, []byte(tweet.Text)...)
  128. tweetToAppend = append(tweetToAppend, []byte(";")[0])
  129. }
  130. //adds padding
  131. length := minimumBlockSize - len(tweetToAppend)
  132. padding := make([]byte, length)
  133. rand.Read(padding)
  134. tweetToAppend = append(tweetToAppend, padding...)
  135. Xor(tweetToAppend, tweetsAsBytes)
  136. }
  137. return tweetsAsBytes
  138. }
  139. //see func name
  140. func GetTopicList(whereFrom int) ([]byte, int) {
  141. tmpTopicList := topicList
  142. if whereFrom == 1 {
  143. tmpTopicList = archiveTopicList
  144. }
  145. if (len(tmpTopicList)) == 0 {
  146. return nil, 0
  147. }
  148. topicByteArray := new(bytes.Buffer)
  149. json.NewEncoder(topicByteArray).Encode(tmpTopicList)
  150. return topicByteArray.Bytes(), len(tmpTopicList)
  151. }
  152. //iterates through full dbR and moves old tweets to archive
  153. func CleanUpdbR(round int) {
  154. var tweetsToArchive []Tweet
  155. for j := range dbR {
  156. tweets := dbR[j]
  157. for i := len(tweets) - 1; i >= 0; i-- {
  158. if round-roundsBeforeArchiving == tweets[i].RoundPosted {
  159. //only adds the tweet to the archive when there is text
  160. if tweets[i].Text != "" {
  161. tweetsToArchive = append(tweetsToArchive, tweets[i])
  162. }
  163. //delets the tweet from the array
  164. tweets = append(tweets[:i], tweets[i+1:]...)
  165. }
  166. }
  167. dbR[j] = tweets
  168. }
  169. NewEntries(tweetsToArchive, 1)
  170. //redoes the whole dbR to correct pointers
  171. var tweetsToMain []Tweet
  172. for i := range dbR {
  173. tweets := dbR[i]
  174. for _, tweet := range tweets {
  175. if tweet.Text != "" {
  176. tweetsToMain = append(tweetsToMain, tweet)
  177. }
  178. }
  179. }
  180. dbR = nil
  181. dbR = make(map[string][]Tweet)
  182. topicList = nil
  183. NewEntries(tweetsToMain, 0)
  184. }