/roomserver/storage/sqlite3/storage.go

https://github.com/matrix-org/dendrite · Go · 175 lines · 126 code · 10 blank · 39 comment · 30 complexity · f582707ac849d49e94bce6a08e21d683 MD5 · raw file

  1. // Copyright 2017-2018 New Vector Ltd
  2. // Copyright 2019-2020 The Matrix.org Foundation C.I.C.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. package sqlite3
  16. import (
  17. "context"
  18. "database/sql"
  19. "github.com/matrix-org/dendrite/internal/caching"
  20. "github.com/matrix-org/dendrite/internal/config"
  21. "github.com/matrix-org/dendrite/internal/sqlutil"
  22. "github.com/matrix-org/dendrite/roomserver/storage/shared"
  23. "github.com/matrix-org/dendrite/roomserver/storage/tables"
  24. "github.com/matrix-org/dendrite/roomserver/types"
  25. "github.com/matrix-org/gomatrixserverlib"
  26. _ "github.com/mattn/go-sqlite3"
  27. )
  28. // A Database is used to store room events and stream offsets.
  29. type Database struct {
  30. shared.Database
  31. events tables.Events
  32. eventJSON tables.EventJSON
  33. eventTypes tables.EventTypes
  34. eventStateKeys tables.EventStateKeys
  35. rooms tables.Rooms
  36. transactions tables.Transactions
  37. prevEvents tables.PreviousEvents
  38. invites tables.Invites
  39. membership tables.Membership
  40. db *sql.DB
  41. writer sqlutil.Writer
  42. }
  43. // Open a sqlite database.
  44. // nolint: gocyclo
  45. func Open(dbProperties *config.DatabaseOptions, cache caching.RoomServerCaches) (*Database, error) {
  46. var d Database
  47. var err error
  48. if d.db, err = sqlutil.Open(dbProperties); err != nil {
  49. return nil, err
  50. }
  51. d.writer = sqlutil.NewExclusiveWriter()
  52. //d.db.Exec("PRAGMA journal_mode=WAL;")
  53. //d.db.Exec("PRAGMA read_uncommitted = true;")
  54. // FIXME: We are leaking connections somewhere. Setting this to 2 will eventually
  55. // cause the roomserver to be unresponsive to new events because something will
  56. // acquire the global mutex and never unlock it because it is waiting for a connection
  57. // which it will never obtain.
  58. d.db.SetMaxOpenConns(20)
  59. d.eventStateKeys, err = NewSqliteEventStateKeysTable(d.db)
  60. if err != nil {
  61. return nil, err
  62. }
  63. d.eventTypes, err = NewSqliteEventTypesTable(d.db)
  64. if err != nil {
  65. return nil, err
  66. }
  67. d.eventJSON, err = NewSqliteEventJSONTable(d.db)
  68. if err != nil {
  69. return nil, err
  70. }
  71. d.events, err = NewSqliteEventsTable(d.db)
  72. if err != nil {
  73. return nil, err
  74. }
  75. d.rooms, err = NewSqliteRoomsTable(d.db)
  76. if err != nil {
  77. return nil, err
  78. }
  79. d.transactions, err = NewSqliteTransactionsTable(d.db)
  80. if err != nil {
  81. return nil, err
  82. }
  83. stateBlock, err := NewSqliteStateBlockTable(d.db)
  84. if err != nil {
  85. return nil, err
  86. }
  87. stateSnapshot, err := NewSqliteStateSnapshotTable(d.db)
  88. if err != nil {
  89. return nil, err
  90. }
  91. d.prevEvents, err = NewSqlitePrevEventsTable(d.db)
  92. if err != nil {
  93. return nil, err
  94. }
  95. roomAliases, err := NewSqliteRoomAliasesTable(d.db)
  96. if err != nil {
  97. return nil, err
  98. }
  99. d.invites, err = NewSqliteInvitesTable(d.db)
  100. if err != nil {
  101. return nil, err
  102. }
  103. d.membership, err = NewSqliteMembershipTable(d.db)
  104. if err != nil {
  105. return nil, err
  106. }
  107. published, err := NewSqlitePublishedTable(d.db)
  108. if err != nil {
  109. return nil, err
  110. }
  111. redactions, err := NewSqliteRedactionsTable(d.db)
  112. if err != nil {
  113. return nil, err
  114. }
  115. d.Database = shared.Database{
  116. DB: d.db,
  117. Cache: cache,
  118. Writer: d.writer,
  119. EventsTable: d.events,
  120. EventTypesTable: d.eventTypes,
  121. EventStateKeysTable: d.eventStateKeys,
  122. EventJSONTable: d.eventJSON,
  123. RoomsTable: d.rooms,
  124. TransactionsTable: d.transactions,
  125. StateBlockTable: stateBlock,
  126. StateSnapshotTable: stateSnapshot,
  127. PrevEventsTable: d.prevEvents,
  128. RoomAliasesTable: roomAliases,
  129. InvitesTable: d.invites,
  130. MembershipTable: d.membership,
  131. PublishedTable: published,
  132. RedactionsTable: redactions,
  133. }
  134. return &d, nil
  135. }
  136. func (d *Database) SupportsConcurrentRoomInputs() bool {
  137. // This isn't supported in SQLite mode yet because of issues with
  138. // database locks.
  139. // TODO: Look at this again - the problem is probably to do with
  140. // the membership updaters and latest events updaters.
  141. return false
  142. }
  143. func (d *Database) GetLatestEventsForUpdate(
  144. ctx context.Context, roomInfo types.RoomInfo,
  145. ) (*shared.LatestEventsUpdater, error) {
  146. // TODO: Do not use transactions. We should be holding open this transaction but we cannot have
  147. // multiple write transactions on sqlite. The code will perform additional
  148. // write transactions independent of this one which will consistently cause
  149. // 'database is locked' errors. As sqlite doesn't support multi-process on the
  150. // same DB anyway, and we only execute updates sequentially, the only worries
  151. // are for rolling back when things go wrong. (atomicity)
  152. return shared.NewLatestEventsUpdater(ctx, &d.Database, nil, roomInfo)
  153. }
  154. func (d *Database) MembershipUpdater(
  155. ctx context.Context, roomID, targetUserID string,
  156. targetLocal bool, roomVersion gomatrixserverlib.RoomVersion,
  157. ) (*shared.MembershipUpdater, error) {
  158. // TODO: Do not use transactions. We should be holding open this transaction but we cannot have
  159. // multiple write transactions on sqlite. The code will perform additional
  160. // write transactions independent of this one which will consistently cause
  161. // 'database is locked' errors. As sqlite doesn't support multi-process on the
  162. // same DB anyway, and we only execute updates sequentially, the only worries
  163. // are for rolling back when things go wrong. (atomicity)
  164. return shared.NewMembershipUpdater(ctx, &d.Database, nil, roomID, targetUserID, targetLocal, roomVersion)
  165. }