[crossfire] Moving server towards a modularized system?

Mark Wedel mwedel at sonic.net
Wed Jan 25 02:50:38 CST 2006


tchize wrote:
<much about removing code removed>

  I agree that removing/disabling code is a valuable feature.  I'm just not sure
that any of the methods either of us have talked about is really a good method.

  From my point of view, making it really easy/convenient for developers to
disable code is less important than a method where it can be done on the server.

  And when I say 'on the server', I mean literally through a running crossfire
server, and not by shell login.  I'd see the most likely scenariou that a DM on
a server that does not have shell access seeing that applying an item (or some
other action) is causing the server to crash, and thus wants to disable that.

  IMO, having the server unlink .so files probably isn't a great solution (and in
fact, may not always work, as the .so files may be installed with a uid
different than what the server runs under).

  Also, disabling at an entire module level may not be desirable.  In my example
above, you may want to disable the applying of items, but still want ot be able
to get descriptions of items, identify them, etc.

  Likewise, any disabling of functions should be persistent accross runs until
re-enable.  Disabling that apply function doesn't do much good if something else
crashes the server and it is enable again.

  So what I started thinking was you could have a module control, with things like:

<operation type> <operation name> <operation value>, eg:
function scroll:apply disable

  (operation name would be module:function name, with potential wildcards, so you
could do something like)

function scroll: disable

to disable all scroll code.

  This then allows other things like:

variable scroll:max_level 25

  To set module values to various things.

  this requires support of the module initialization code (checking to see if it
shouldn't set the callback, change global variable, etc).  If callbacks aren't
used, the first line of various functions could be things like:

  if (!module.apply) return;

  That is marginally more complex than other methods we have talked about, but
probably more flexible (I do especially like the clearer documentation of
setting variables and how they effect things).  I'd also think that once this
glue code was written for one module, it could pretty easily be re-used for
everything else.


>> IMO, compiling/not compiling something isn't an issue - if something is so
>>  broken that it doesn't even compile, it should be fixed ASAP or be
>> removed.
> 
> Yes, assuming it's easily fixable (does not take 3 days of work).

  Well, if it takes 3 days of work to fix, then perhaps it should be removed, or
disabled from the make system.

  After all, right now at least, the current built environment isn't especially
graceful about continuing when it fails to compile a file (you can always do
make -k)

  And I'd personally be concerned anytime I see something failing to compile.
But as modules, it should at least be able to disable compilation of that one
problematic file without affecting anything else.


> 
> If you don't put the modules in plugins (at least what we could modularize
> from current server code) you would have two things - 1) code to manage hard
> linked modules (eg arrays of module callbacks to explores and so on) - 2)
> code to manage additionnal behaviour which could be requested by plugins (be
> it python, animator or another one)
> 
> That mean during modularization process, at each place we consider splitting
> appart code in modules we have to handle separetly - main server module -
> plugin managment code
> 
> This is twice the effort during the modularization process.

  I disagree it would be twice the effort.  It _may_ be more work - it certainly
wouldn't be quite as consistent.

  But if you pluginize a lot of code, I'd say there is more code that would need
to be rewitten/changed than if it was modularized.


> This isn't enough for modules. Of course modules can be gathered .a and
> gathered a link time. But you also need to clearly separate them. Currently
> it has nothing of modularized. A piece of code in random map can call
> functions present in the socket, a piece of code in weather can call
> functions in maploader. Same for piece of code in protocol which makes call
> to maploader.c

  I don't see how you can avoid that.

  At the most basic level, almost any module of code is going need to talk to the
socket (draw_info commands at most basic, but I can also see need for lots of
update object commands).

  Now you can perhaps wrap some of those functions or use callbacks, but that
really isn't changing anything.

  If we are talking about apply code again, the module will need to know about
the NDI_ values as well as perhaps the UPD_ values.  Now the plugin could have
its own private file, but then somewhere in that plugin logic, it has to convert
those values (PG_BLUE to NDI_BLUE or whatever).

  And unfortunately, I'm not really sure how many of the current top level 
include files have dependencies removed.  Certainly, some clean up and 
seperation could be done (files like includes.h, define.h are pretty meaningless 
names).  But there is the mess that maps need to know about objects, objects 
need to know about maps, player need to know about objects and vice versa.


> 
> To me, be it link time modules (.a) or runtime modules (.so), the work to do
> is the same, except this - plugin will need a bit of 'load library code'
> mainly already present in code - in .a it will be difficult to enforce strict
> separation in the future.

  One question I don't know the answer to is duplicate symbol names.

  For example, I write a module and have a function called apply().  There is 
another module that also has a function called apply().  I know in linking at 
compile time will catch this - I'm not sure what will happen with dlopen.


> If you have modularization in form 'plugin +sth else' you have to do twice
> the job as plugin will mainly need to plug at same places the modules will
> need to interact.

  Maybe.  But there are lots of places right now where there is no plugin glue 
for various actions.

  So in that case, you have to add the event plugin glue, convert the existing 
code to be 'plugin compliant', which may or may not be a big deal depending on 
what that means.  In comparison, converting to a module may just be a simple 
test/make callback type of thing

  But this is more a case by case issue - depends on the operation in question.

  All that said, I think we can discuss this a long time, but that isn't helping 
any of this get done.

  What I'd personally suggest:

1) Make a list, in priority order, what we are trying to accomplish.  Is it 
making the code easier to deal with?  How important is being able to disable 
portions of the code?   I'd think that a solution that can be done in small 
steps is better than one that requires a single major rewirte.  Estimate the 
time to do this.  A perfect solution that will take years to complete isn't very 
useful.  A solution that covers 80% (or top 3 points/whatever) that can be done 
in 3 months becomes more appealing.

2) From your discussion in this, does that mean you're willing to lead/take on 
this project?  Is there someone else?  All this discussion is basically 
meaningless unless someone is out there that is going to do the work.

3) When person from point #2 is identified, I'd say they should do the following:
A) Roll all this up and make a proposal of what they plan to do (or at least do 
first).  This should include some fairly detailed description - saying something 
like 'I'm going to pluginize objects' is pretty meaningless.
B) Part of A, provide an example of the code to be used, if reasonable.  For 
example, if redoing the object code, provide code of redoing one object type (it 
could even be a fairly trivial object), just so everyone can see what the final 
form is really going to look like.
C) Presuming good agreement on point B, go ahead and start working on this on a 
more major fashion.

  This may be a bit cumbersome, but if we're going to do this,  I think it is 
really important it be done in a way that is going to be clearly better an 
easier to use.

  While the current code isn't all that good, at least I, and probably the other 
old hand developers, do know where things are.  It'd be stupid to rearrange the 
code so that virtually no one knows where anything is anymore, and it not really 
being any easier to find stuff under the new code.





More information about the crossfire mailing list