2018-10-24 23:01:21 +02:00
|
|
|
// Matrix Construct
|
|
|
|
//
|
|
|
|
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
|
|
|
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
|
|
|
|
//
|
|
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
|
|
// copyright notice and this permission notice is present in all copies. The
|
|
|
|
// full license for this software is available in the LICENSE file.
|
|
|
|
|
2019-08-13 07:59:27 +02:00
|
|
|
decltype(ircd::m::rooms::opts_default)
|
|
|
|
ircd::m::rooms::opts_default;
|
2018-10-24 23:01:21 +02:00
|
|
|
|
2020-02-29 03:03:05 +01:00
|
|
|
void
|
|
|
|
ircd::m::rooms::dump__file(const opts &opts,
|
|
|
|
const string_view &filename)
|
|
|
|
{
|
|
|
|
const fs::fd file
|
|
|
|
{
|
2022-06-18 21:05:17 +02:00
|
|
|
filename, fs::fd::opts
|
|
|
|
{
|
|
|
|
.mode = std::ios::out | std::ios::app,
|
|
|
|
},
|
2020-02-29 03:03:05 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
// POSIX_FADV_DONTNEED
|
|
|
|
fs::evict(file);
|
|
|
|
|
|
|
|
size_t len(0), num(0);
|
|
|
|
for_each(opts, [&](const auto &room_id)
|
|
|
|
{
|
|
|
|
const const_buffer bufs[]
|
|
|
|
{
|
|
|
|
room_id, "\n"_sv
|
|
|
|
};
|
|
|
|
|
|
|
|
len += fs::append(file, bufs);
|
|
|
|
++num;
|
|
|
|
|
|
|
|
char pbuf[48];
|
|
|
|
log::info
|
|
|
|
{
|
|
|
|
log, "dump[%s] rooms:%zu %s %s",
|
|
|
|
filename,
|
|
|
|
num,
|
|
|
|
pretty(pbuf, iec(len)),
|
|
|
|
string_view{room_id},
|
|
|
|
};
|
|
|
|
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
|
|
|
|
char pbuf[48];
|
|
|
|
log::notice
|
|
|
|
{
|
|
|
|
log, "dump[%s] complete rooms:%zu using %s",
|
|
|
|
filename,
|
|
|
|
num,
|
|
|
|
pretty(pbuf, iec(len)),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-10-24 23:08:14 +02:00
|
|
|
bool
|
2019-08-13 07:59:27 +02:00
|
|
|
ircd::m::rooms::has(const opts &opts)
|
2018-10-24 23:08:14 +02:00
|
|
|
{
|
2019-08-13 07:59:27 +02:00
|
|
|
return !for_each(opts, []
|
2022-07-04 22:15:53 +02:00
|
|
|
(const m::room::id &) noexcept
|
2018-10-24 23:08:14 +02:00
|
|
|
{
|
2019-08-13 07:59:27 +02:00
|
|
|
// false to break; for_each() returns false
|
|
|
|
return false;
|
|
|
|
});
|
2019-03-01 23:51:30 +01:00
|
|
|
}
|
|
|
|
|
2018-10-24 23:22:10 +02:00
|
|
|
size_t
|
2019-08-13 07:59:27 +02:00
|
|
|
ircd::m::rooms::count(const opts &opts)
|
2018-10-24 23:22:10 +02:00
|
|
|
{
|
2018-10-25 01:50:54 +02:00
|
|
|
size_t ret{0};
|
2019-08-13 07:59:27 +02:00
|
|
|
for_each(opts, [&ret]
|
2022-07-04 22:15:53 +02:00
|
|
|
(const m::room::id &) noexcept
|
2018-10-24 23:22:10 +02:00
|
|
|
{
|
2018-10-25 01:50:54 +02:00
|
|
|
++ret;
|
|
|
|
return true;
|
2019-08-13 07:59:27 +02:00
|
|
|
});
|
2018-10-24 23:22:10 +02:00
|
|
|
|
2018-10-25 01:50:54 +02:00
|
|
|
return ret;
|
2018-10-24 23:22:10 +02:00
|
|
|
}
|
|
|
|
|
2018-10-24 23:15:36 +02:00
|
|
|
bool
|
2019-08-13 07:59:27 +02:00
|
|
|
ircd::m::rooms::for_each(const room::id::closure_bool &closure)
|
2018-10-24 23:01:21 +02:00
|
|
|
{
|
2019-08-13 07:59:27 +02:00
|
|
|
return for_each(opts_default, closure);
|
2018-10-25 01:50:54 +02:00
|
|
|
}
|
|
|
|
|
2019-08-13 07:59:27 +02:00
|
|
|
bool
|
|
|
|
ircd::m::rooms::for_each(const opts &opts,
|
|
|
|
const room::id::closure_bool &closure)
|
2018-10-25 01:50:54 +02:00
|
|
|
{
|
2019-08-13 07:59:27 +02:00
|
|
|
bool ret{true};
|
2019-09-06 06:15:06 +02:00
|
|
|
const auto proffer{[&opts, &closure, &ret]
|
2019-08-13 07:59:27 +02:00
|
|
|
(const m::room::id &room_id)
|
2018-10-25 01:50:54 +02:00
|
|
|
{
|
2019-08-13 07:59:27 +02:00
|
|
|
if(opts.room_id && !opts.lower_bound)
|
2018-10-25 01:50:54 +02:00
|
|
|
{
|
2019-08-13 07:59:27 +02:00
|
|
|
ret = false;
|
|
|
|
return;
|
|
|
|
}
|
2018-10-25 00:18:07 +02:00
|
|
|
|
2019-09-08 01:33:24 +02:00
|
|
|
const m::room room
|
|
|
|
{
|
|
|
|
room_id
|
|
|
|
};
|
|
|
|
|
2019-08-13 07:59:27 +02:00
|
|
|
if(opts.room_id)
|
|
|
|
if(room_id < opts.room_id)
|
|
|
|
return;
|
2018-10-25 01:50:54 +02:00
|
|
|
|
2019-09-08 01:33:24 +02:00
|
|
|
if(opts.local_joined_only)
|
|
|
|
if(!local_joined(room))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(opts.remote_joined_only)
|
|
|
|
if(!remote_joined(room))
|
2019-08-13 13:43:04 +02:00
|
|
|
return;
|
|
|
|
|
2019-09-08 07:03:02 +02:00
|
|
|
if(opts.local_only)
|
|
|
|
if(!local_only(room))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(opts.remote_only)
|
|
|
|
if(local_only(room))
|
|
|
|
return;
|
|
|
|
|
2019-08-13 07:59:27 +02:00
|
|
|
if(opts.server && !opts.summary)
|
|
|
|
if(opts.server != room_id.host())
|
|
|
|
return;
|
2018-10-24 23:01:21 +02:00
|
|
|
|
2019-09-14 02:26:28 +02:00
|
|
|
if(opts.join_rule && !opts.summary)
|
2019-09-08 01:33:24 +02:00
|
|
|
if(!join_rule(room, opts.join_rule))
|
2019-08-13 07:59:27 +02:00
|
|
|
return;
|
2018-10-24 23:01:21 +02:00
|
|
|
|
2023-01-25 05:39:03 +01:00
|
|
|
if(opts.server && opts.request_node_id && my_host(opts.server))
|
|
|
|
if(!room::aliases(room_id).has_server(opts.server))
|
|
|
|
return;
|
|
|
|
|
2019-09-06 06:15:06 +02:00
|
|
|
if(opts.room_alias)
|
|
|
|
{
|
|
|
|
const auto match_alias_prefix{[&opts](const auto &alias)
|
|
|
|
{
|
|
|
|
return !startswith(alias, opts.room_alias);
|
|
|
|
}};
|
|
|
|
|
2019-09-08 01:33:24 +02:00
|
|
|
if(room::aliases(room).for_each(match_alias_prefix))
|
2019-09-06 05:28:43 +02:00
|
|
|
return; // no match
|
2019-09-06 06:15:06 +02:00
|
|
|
}
|
2019-09-06 05:28:43 +02:00
|
|
|
|
2019-09-08 01:33:24 +02:00
|
|
|
ret = closure(room);
|
2019-08-13 07:59:27 +02:00
|
|
|
}};
|
2018-10-24 23:01:21 +02:00
|
|
|
|
2019-09-06 06:15:06 +02:00
|
|
|
// branch for public rooms of a specific user
|
|
|
|
if(opts.user_id)
|
|
|
|
{
|
|
|
|
const user::rooms user_rooms
|
|
|
|
{
|
|
|
|
opts.user_id
|
|
|
|
};
|
|
|
|
|
|
|
|
return user_rooms.for_each(user::rooms::closure_bool{[&proffer, &ret]
|
|
|
|
(const room::id &room_id, const string_view &membership)
|
|
|
|
{
|
|
|
|
proffer(room_id);
|
|
|
|
return ret;
|
|
|
|
}});
|
|
|
|
}
|
|
|
|
|
2019-08-13 07:59:27 +02:00
|
|
|
// branch for optimized public rooms searches.
|
|
|
|
if(opts.summary)
|
2018-10-24 23:01:21 +02:00
|
|
|
{
|
2019-08-13 07:59:27 +02:00
|
|
|
const room::id::buf public_room_id
|
2018-10-24 23:01:21 +02:00
|
|
|
{
|
2019-08-13 07:59:27 +02:00
|
|
|
"!public", my_host()
|
2018-10-24 23:01:21 +02:00
|
|
|
};
|
|
|
|
|
2019-09-06 05:29:17 +02:00
|
|
|
const room::state state
|
|
|
|
{
|
|
|
|
public_room_id
|
|
|
|
};
|
|
|
|
|
2019-09-15 04:51:08 +02:00
|
|
|
state.for_each("ircd.rooms.summary", [&opts, &proffer, &ret]
|
2019-08-13 07:59:27 +02:00
|
|
|
(const string_view &type, const string_view &state_key, const event::idx &event_idx)
|
2018-10-24 23:01:21 +02:00
|
|
|
{
|
2019-09-15 04:51:08 +02:00
|
|
|
const auto &[room_id, origin]
|
2019-09-14 02:41:26 +02:00
|
|
|
{
|
2019-09-15 01:03:38 +02:00
|
|
|
rooms::summary::unmake_state_key(state_key)
|
2019-09-14 02:41:26 +02:00
|
|
|
};
|
|
|
|
|
2019-09-15 04:51:08 +02:00
|
|
|
if(opts.server && origin != opts.server)
|
|
|
|
return true;
|
|
|
|
|
2019-09-14 02:41:26 +02:00
|
|
|
proffer(room_id);
|
2019-08-13 07:59:27 +02:00
|
|
|
return ret;
|
2019-09-15 04:51:08 +02:00
|
|
|
});
|
2019-09-06 05:29:17 +02:00
|
|
|
|
2019-09-14 02:41:26 +02:00
|
|
|
return ret;
|
2018-10-24 23:01:21 +02:00
|
|
|
}
|
|
|
|
|
2020-02-29 04:41:15 +01:00
|
|
|
ctx::dock dock;
|
|
|
|
size_t fetch {0}, fetched {0};
|
|
|
|
const auto fetcher{[&]
|
2019-08-13 07:59:27 +02:00
|
|
|
(const string_view &type, const event::idx &event_idx)
|
2018-10-24 23:01:21 +02:00
|
|
|
{
|
2020-02-29 04:41:15 +01:00
|
|
|
++fetch;
|
|
|
|
fetched += m::get(std::nothrow, event_idx, "room_id", proffer);
|
|
|
|
dock.notify_one();
|
2019-08-13 07:59:27 +02:00
|
|
|
return ret;
|
2020-02-29 04:41:15 +01:00
|
|
|
}};
|
|
|
|
|
|
|
|
size_t prefetch {0}, prefetched {0};
|
|
|
|
const auto prefetcher{[&]
|
|
|
|
(const string_view &type, const event::idx &event_idx)
|
|
|
|
{
|
|
|
|
++prefetch;
|
|
|
|
prefetched += m::prefetch(event_idx, "room_id");
|
2022-07-04 22:15:53 +02:00
|
|
|
dock.wait([&]() noexcept
|
2020-02-29 04:41:15 +01:00
|
|
|
{
|
|
|
|
return fetch + opts.prefetch > prefetch;
|
|
|
|
});
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}};
|
|
|
|
|
|
|
|
if(!opts.prefetch)
|
|
|
|
return events::type::for_each_in("m.room.create", fetcher);
|
|
|
|
|
|
|
|
const ctx::context prefetch_worker
|
|
|
|
{
|
|
|
|
"m.rooms.prefetch", [&prefetcher]
|
|
|
|
{
|
|
|
|
events::type::for_each_in("m.room.create", prefetcher);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
return events::type::for_each_in("m.room.create", fetcher);
|
2018-10-25 00:18:07 +02:00
|
|
|
}
|
2019-09-08 04:54:15 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// ircd::m::rooms::opts::opts
|
|
|
|
//
|
|
|
|
|
|
|
|
ircd::m::rooms::opts::opts(const string_view &input)
|
|
|
|
noexcept
|
|
|
|
:room_id
|
|
|
|
{
|
|
|
|
valid(m::id::ROOM, input)?
|
|
|
|
m::id::room{input}:
|
|
|
|
m::id::room{}
|
|
|
|
}
|
|
|
|
,server
|
|
|
|
{
|
|
|
|
startswith(input, ':')?
|
|
|
|
lstrip(input, ':'):
|
|
|
|
string_view{}
|
|
|
|
}
|
|
|
|
,room_alias
|
|
|
|
{
|
|
|
|
valid(m::id::ROOM_ALIAS, input)?
|
|
|
|
m::id::room_alias{input}:
|
|
|
|
m::id::room_alias{}
|
|
|
|
}
|
|
|
|
,user_id
|
|
|
|
{
|
|
|
|
valid(m::id::USER, input)?
|
|
|
|
m::id::user{input}:
|
|
|
|
m::id::user{}
|
|
|
|
}
|
|
|
|
,local_only
|
|
|
|
{
|
|
|
|
has(input, "local_only")
|
|
|
|
}
|
|
|
|
,remote_only
|
|
|
|
{
|
|
|
|
has(input, "remote_only")
|
|
|
|
}
|
|
|
|
,local_joined_only
|
|
|
|
{
|
|
|
|
has(input, "local_joined_only")
|
|
|
|
}
|
|
|
|
,remote_joined_only
|
|
|
|
{
|
|
|
|
has(input, "remote_joined_only")
|
|
|
|
}
|
|
|
|
,search_term
|
|
|
|
{
|
|
|
|
!room_id && !server && !room_alias && !user_id
|
|
|
|
&& !local_only && !remote_only
|
|
|
|
&& !local_joined_only && !remote_joined_only?
|
|
|
|
input:
|
|
|
|
string_view{}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
}
|