databaseRead.go 5.7 KB

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