databaseRead.go 5.6 KB

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