接着上一篇,这次处理“维护当前可用的主题房间信息”问题。 每次使用startChild启动子进程的时候将当前的房间信息保存到ets表中。更重要的是每次主题房异常退出或重启都要更新对应的信息。
修改room_manager.erl中的内容:
新建一个函数来初始化房间信息表:
initTab()->
ets:
new(roominfo,[
public,
ordered_set,
named_table,
{keypos,#roominfo.id}
])
.
再添加对房间表数据操作的方法:
addRoomInfo(Record)->
#roominfo{name=Name,type=Type}=Record,
case isRoomUniq([],Name,Type)of
{found,_Id}->
{fail,room_exists};
{not_found}->
RoomId=id_generator:getnewid("room"),
ClientTableName=list_to_atom(?PRIFIX++integer_to_list(RoomId)),
Info=Record#roominfo{id=RoomId,tablename=ClientTableName},
ets:insert(roominfo, Info),
{success,Info}
end
.
setRoomAvailble(Id)->
case ets:lookup(roominfo, Id) of
Record->
ets:update_element(roominfo, Id, {#roominfo.status,1}),
ok;
[]->
ok
end
.
setRoomUnavailble(Id)->
case ets:lookup(roominfo, Id) of
Record->
ets:update_element(roominfo, Id, {#roominfo.status,0}),
ok;
[]->
ok
end
.
removeRoom(Id)->
ets:delete(roominfo, Id)
.
为了方便后面的操作,再提供两个方法,一个根据给定的属性获取对应的ID,一个是判断对应ID的房间是否存在:
getRoomProperty(Id,Proper)->
case ets:lookup(roominfo, Id) of
Record->
#roominfo{name=Name,
type=Type,
unum=Unum,
tablename=Tab,
status=Status,
creationDate=Crdate}=Record,
case Proper of
#roominfo.name->
{ok,Name};
#roominfo.type->
{ok,Type};
#roominfo.unum->
{ok,Unum};
#roominfo.tablename->
{ok,Tab};
#roominfo.status->
{ok,Status};
#roominfo.creationDate->
{ok,Crdate};
_Els->
{fail,illegal_property}
end;
_Els->
{fail,not_found}
end
.
isRoomUniq([],Name,Type)->
case ets:all(roominfo) of
[R|L]->
#roominfo{id=Id,name=TheName,type=TheType}=R,
case string:equal("Name",TheName) and string:equal(Type, TheType) of
true->
{found,Id};
false->
isRoomUniq([L],Name,Type)
end;
[]->
{not_found}
end
;
isRoomUniq([L],Name,Type)->
case ets:all(roominfo) of
[R|L]->
#roominfo{id=Id,name=TheName,type=TheType}=R,
case string:equal("Name",TheName) and string:equal(Type, TheType) of
true->
{found,Id};
false->
isRoomUniq([L],Name,Type)
end;
[]->
{not_found}
end
.
再修改chat_room的terminate,从表中删除相应的记录:
terminate(_Reason,State)->
#roominfo{id=Id}=State,
room_manager:removeRoom(Id)
.
再修改房间启动时的初始化方法,房间的ID和名称从外部传入:
init([Para])->
id_generator:start_link(),
#roominfo{id=RoomId,tablename=ClientTableName}=Para,
client_manager:init(ClientTableName),
case is_record(Para,roominfo)of
true->
{ok,#roominfo{unum=0}=Para,tablename=ClientTableName};
Els->
{ok,#roominfo{id=RoomId,unum=0,name="room"++integer_to_list(RoomId),tablename=ClientTableName,type="def"}}
end
.
暂时不对代码进行测试,等后面整体修改完成后再一起测。