databaseRead.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. package lib
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  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. var roundsBeforeArchiving = 2
  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. //fmt.Println("topic to put in", tweet.Topics[index])
  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, pubKey [32]byte) []byte {
  65. //fmt.Println("query", pirQuery)
  66. //fmt.Println("dbR", dbR)
  67. tmpdb := dbR
  68. if whereFrom == 1 {
  69. tmpdb = archive
  70. }
  71. minimumBlockSize = dataLength * maxTweetAmount(whereFrom)
  72. var wantedTopics = getNamesForTopics(pirQuery, whereFrom)
  73. tweetsToReturn := make([][]Tweet, len(wantedTopics))
  74. for index, wantedTopic := range wantedTopics {
  75. for _, tweet := range tmpdb[wantedTopic] {
  76. //fmt.Println(tweet)
  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. return tweetsToByteArray(tweetsToReturn, whereFrom)
  91. }
  92. func maxTweetAmount(whereFrom int) int {
  93. tmpdb := dbR
  94. if whereFrom == 1 {
  95. tmpdb = archive
  96. }
  97. var max int = 0
  98. for i := range tmpdb {
  99. nrOfTweets := len(dbR[i])
  100. if nrOfTweets > max {
  101. max = nrOfTweets
  102. }
  103. }
  104. return max
  105. }
  106. func getNamesForTopics(wantedIndices []byte, whereFrom int) []string {
  107. var topicNames []string
  108. tmpTopicList := topicList
  109. if whereFrom == 1 {
  110. tmpTopicList = archiveTopicList
  111. }
  112. for index, element := range wantedIndices {
  113. if element == 1 {
  114. topicNames = append(topicNames, tmpTopicList[index])
  115. }
  116. }
  117. return topicNames
  118. }
  119. //transform struct to byte array for sending
  120. func tweetsToByteArray(tweetsToReturn [][]Tweet, whereFrom int) []byte {
  121. tweetsAsBytes := make([]byte, minimumBlockSize)
  122. for blockIndex, block := range tweetsToReturn {
  123. var topicPadding []string
  124. var blockToAppend []byte
  125. for _, tweet := range block {
  126. for topicIndex, topic := range tweet.Topics {
  127. blockToAppend = append(blockToAppend, []byte(topic)...)
  128. blockToAppend = append(blockToAppend, ","...)
  129. //gets the topic used for padding
  130. if topicIndex > 0 {
  131. topicPadding = append(topicPadding, topic)
  132. }
  133. }
  134. //replaces last "," with ";;" bc there is text following and not another topic
  135. blockToAppend = blockToAppend[:len(blockToAppend)-1]
  136. blockToAppend = append(blockToAppend, []byte(";;")[:]...)
  137. blockToAppend = append(blockToAppend, []byte(tweet.Text)...)
  138. blockToAppend = append(blockToAppend, []byte(";")[0])
  139. }
  140. //adds padding
  141. blockToAppend = append(blockToAppend, []byte(";;;")[:]...)
  142. remainingLength := minimumBlockSize - len(blockToAppend)
  143. //fmt.Println("block", string(blockToAppend))
  144. if blockIndex == 0 {
  145. // fmt.Println("tweet", string(blockToAppend))
  146. }
  147. //grouping using topic from recovered tweets
  148. index := 0
  149. for len(topicPadding) > index && remainingLength > 0 && topicPadding[index] != "" {
  150. paddingTweet, err := getNextTweet(topicPadding[index], index, whereFrom)
  151. if err {
  152. break
  153. }
  154. if remainingLength < len(paddingTweet) {
  155. break
  156. }
  157. blockToAppend = append(blockToAppend, paddingTweet...)
  158. remainingLength -= len(paddingTweet)
  159. index++
  160. }
  161. if blockIndex == 0 {
  162. // fmt.Println("tweetPadded", string(blockToAppend))
  163. }
  164. padding := bytes.Repeat([]byte(";"), remainingLength)
  165. blockToAppend = append(blockToAppend, padding...)
  166. Xor(blockToAppend, tweetsAsBytes)
  167. //fmt.Println(tweetsAsBytes)
  168. }
  169. //fmt.Println("length Returned", len(tweetsAsBytes))
  170. return tweetsAsBytes
  171. }
  172. //gets the Tweet at index from wantedTopic for padding
  173. func getNextTweet(wantedTopic string, index, whereFrom int) ([]byte, bool) {
  174. tmpdb := dbR
  175. if whereFrom == 1 {
  176. tmpdb = archive
  177. }
  178. var tweetToReturn Tweet
  179. for tweetIndex, tweet := range tmpdb[wantedTopic] {
  180. if len(tmpdb[wantedTopic]) <= index {
  181. return nil, true
  182. } else if tweetIndex < index {
  183. continue
  184. } else if tweetIndex > index {
  185. break
  186. }
  187. //new Tweet
  188. if tweet.Text != "" {
  189. tweet.RoundPosted = 0
  190. tweetToReturn = tweet
  191. } else {
  192. //"copied" tweet
  193. //find tweet with pointers
  194. tweet = tmpdb[tweet.TopicPointer][tweet.TextPointer]
  195. tweet.RoundPosted = 0
  196. tweetToReturn = tweet
  197. }
  198. }
  199. //fmt.Println("nextTweet", tweetToReturn)
  200. var tweetToReturnBytes []byte
  201. for _, topic := range tweetToReturn.Topics {
  202. tweetToReturnBytes = append(tweetToReturnBytes, []byte(topic)...)
  203. tweetToReturnBytes = append(tweetToReturnBytes, ","...)
  204. }
  205. //replaces last "," with ";;" bc there is text following and not another topic
  206. tweetToReturnBytes = tweetToReturnBytes[:len(tweetToReturnBytes)-1]
  207. tweetToReturnBytes = append(tweetToReturnBytes, []byte(";;")[:]...)
  208. tweetToReturnBytes = append(tweetToReturnBytes, []byte(tweetToReturn.Text)...)
  209. tweetToReturnBytes = append(tweetToReturnBytes, []byte(";")[0])
  210. return tweetToReturnBytes, false
  211. }
  212. //see func name
  213. func GetTopicList(whereFrom int) ([]byte, int) {
  214. tmpTopicList := topicList
  215. if whereFrom == 1 {
  216. tmpTopicList = archiveTopicList
  217. }
  218. if (len(tmpTopicList)) == 0 {
  219. return nil, 0
  220. }
  221. topicByteArray := new(bytes.Buffer)
  222. json.NewEncoder(topicByteArray).Encode(tmpTopicList)
  223. return topicByteArray.Bytes(), len(tmpTopicList)
  224. }
  225. //iterates through full dbR and moves old tweets to archive
  226. func CleanUpdbR(round int) {
  227. //doesnt work
  228. return
  229. if roundsBeforeArchiving-round == 0 {
  230. var tweetsToArchive []Tweet
  231. for j := range dbR {
  232. tweets := dbR[j]
  233. for i := len(tweets) - 1; i >= 0; i-- {
  234. if round-roundsBeforeArchiving+1 == tweets[i].RoundPosted {
  235. //only adds the tweet to the archive when there is text
  236. if tweets[i].Text != "" {
  237. tweetsToArchive = append(tweetsToArchive, tweets[i])
  238. }
  239. //delets the tweet from the array
  240. row := append(tweets[:i], tweets[i+1:]...)
  241. tweets = row
  242. }
  243. }
  244. dbR[j] = tweets
  245. }
  246. NewEntries(tweetsToArchive, 1)
  247. roundsBeforeArchiving = roundsBeforeArchiving + roundsBeforeArchiving
  248. //redoes the whole dbR to correct pointers
  249. var tweetsToMain []Tweet
  250. for i := range dbR {
  251. tweets := dbR[i]
  252. for _, tweet := range tweets {
  253. if tweet.Text != "" {
  254. tweetsToMain = append(tweetsToMain, tweet)
  255. }
  256. }
  257. }
  258. dbR = nil
  259. dbR = make(map[string][]Tweet)
  260. topicList = nil
  261. fmt.Println("tweetsToMain", tweetsToMain)
  262. NewEntries(tweetsToMain, 0)
  263. }
  264. }