+2005-04-07 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * configure.in: no more checks for aio_*.
+
2005-04-05 Zoltan Varga <vargaz@freemail.hu>
* configure.in: Fix isinf detection on solaris.
AC_MSG_RESULT(no)
])
- dnl *********************
- dnl *** Check for AIO ***
- dnl *********************
- AC_MSG_CHECKING([for SIGEV_THREAD definition])
- dnl Some systems (FreeBSD at least) may have aio_read
- dnl but don't support/define SIGEV_THREAD.
- AC_TRY_COMPILE([
- #include <sys/signal.h>
- ],[
- int x = SIGEV_THREAD;
- ],[
- ac_cv_c_sigev_thread=yes
- AC_MSG_RESULT(yes)
- ],[
- AC_MSG_RESULT(no)
- ])
-
- if test "$ac_cv_c_sigev_thread" = "yes" ; then
- AC_CHECK_HEADERS(aio.h sys/aio.h)
- AC_CHECK_LIB(rt, aio_read, [ LIBS="$LIBS -lrt" ],)
- SIGVAL_PTR="undefined"
- if test "$ac_cv_header_aio_h" = "yes" -o "$ac_cv_header_sys_aio_h" = "yes" ; then
- AC_CHECK_MEMBER(union sigval.sigval_ptr,SIGVAL_PTR="sigval_ptr",, [
- #include <sys/signal.h>
- ])
- AC_CHECK_MEMBER(union sigval.sival_ptr,SIGVAL_PTR="sival_ptr",, [
- #include <sys/signal.h>
- ])
- if test "$SIGVAL_PTR" = "undefined" ; then
- AC_MSG_ERROR([Unable to detect field name in 'union sigval'])
- fi
- fi
- AC_DEFINE_UNQUOTED(SIGVAL_PTR,$SIGVAL_PTR,[Pointer field name in 'union sigval'])
- fi
-
dnl **********************************
dnl *** Checks for MonoPosixHelper ***
dnl **********************************
+2005-04-08 Raja R Harinath <rharinath@novell.com>
+
+ * profiles/basic.make (do-profile-check): Handle some possible
+ timestamp problems. Hopefully fix #74280.
+
2005-03-30 Zoltan Varga <vargaz@freemail.hu>
* rules.make (INSTALL_DATA): Pass -c to install.
echo "*** The compiler '$(EXTERNAL_MCS)' doesn't appear to be usable." 1>&2 ; \
if test -f $(topdir)/class/lib/monolite/mcs.exe; then \
echo "*** Falling back to using pre-compiled binaries. Be warned, this may not work." 1>&2 ; \
+ ( cd $(topdir)/jay && $(MAKE) ); \
+ ( cd $(topdir)/mcs && $(MAKE) PROFILE=basic cs-parser.cs ); \
( cd $(topdir)/class/lib/monolite/ && cp *.exe *.dll ../basic ); \
- ( cd $(topdir)/jay && $(MAKE) ); ( cd $(topdir)/mcs && $(MAKE) PROFILE=basic cs-parser.cs ); \
- touch $(topdir)/class/lib/basic/*; \
+ case `ls -1t $(topdir)/class/lib/basic/mcs.exe $(topdir)/mcs/cs-parser.cs | sed 1q` in \
+ $(topdir)/class/lib/basic/mcs.exe) : ;; \
+ *) sleep 5; cp $(topdir)/class/lib/monolite/mcs.exe $(topdir)/class/lib/basic ;; \
+ esac; \
else \
echo "*** You need a C# compiler installed to build MCS. (make sure mcs works from the command line)" 1>&2 ; \
echo "*** Read INSTALL.txt for information on how to bootstrap a Mono installation." 1>&2 ; \
+2005-04-07 Jordi Mas i Hernandez <jordi@ximian.com>\r
+\r
+ * LinkLabel.cs: move drawing code into the theme\r
+ * ThemeWin32Classic.cs: drawing code and painting background bugfix\r
+ * Theme.cs: define DrawLinkLabel method \r
+\r
2005-04-05 Jackson Harper <jackson@ximian.com>
* BindingContext.cs: Use weak references so these bad actors don't
private LinkArea link_area;
private LinkBehavior link_behavior;
private LinkCollection link_collection;
- private bool link_visited;
- private Font link_font;
+ private bool link_visited;
private bool link_click;
- private Piece[] pieces;
- private int num_pieces;
+ internal Piece[] pieces;
+ internal int num_pieces;\r
+ internal Font link_font;
private Cursor override_cursor;
private DialogResult dialog_result;
}
}
- private Color GetLinkColor (Piece piece, int i)
+ internal Color GetLinkColor (Piece piece, int i)
{
Color color;
internal new void Draw ()
{
- Color color;
-
- //dc.FillRectangle (label_br_back_color, area);
- ThemeEngine.Current.CPDrawBorderStyle (DeviceContext, ClientRectangle, BorderStyle);
-
- if (Links.Count == 1 && Links[0].Start == 0 && Links[0].Length == -1) {
-
- color = GetLinkColor (pieces[0], 0);
- DeviceContext.DrawString (Text, Font, ThemeEngine.Current.ResPool.GetSolidBrush (color),
- ClientRectangle, string_format);
- return;
- }
-
- for (int i = 0; i < num_pieces; i++) {
-
- color = GetLinkColor (pieces[i], i);
-
- if (pieces[i].link == null)
- DeviceContext.DrawString (pieces[i].text, Font, ThemeEngine.Current.ResPool.GetSolidBrush (Color.Black),
- pieces[i].rect.X, pieces[i].rect.Y, string_format);
- else
- DeviceContext.DrawString (pieces[i].text, link_font, ThemeEngine.Current.ResPool.GetSolidBrush (color),
- pieces[i].rect.X, pieces[i].rect.Y, string_format);
- }
-
+ ThemeEngine.Current.DrawLinkLabel (DeviceContext, ClientRectangle, this);\r
DrawImage (DeviceContext, Image, ClientRectangle, image_align);
}
#endregion // Label
#region LinkLabel
+ public abstract void DrawLinkLabel (Graphics dc, Rectangle clip_rectangle, LinkLabel label);
#endregion // LinkLabel
#region ListBox
{
dc.FillRectangle (ResPool.GetSolidBrush (label.BackColor), clip_rectangle);
- CPDrawBorderStyle (dc, clip_rectangle, label.BorderStyle);
+ CPDrawBorderStyle (dc, label.ClientRectangle, label.BorderStyle);
if (label.Enabled) {
dc.DrawString (label.Text, label.Font, ResPool.GetSolidBrush (label.ForeColor), clip_rectangle, label.string_format);
return new Size (100, 23);
}
}
- #endregion // Label
-
+ #endregion // Label\r
+\r
+ #region LinkLabel\r
+ public override void DrawLinkLabel (Graphics dc, Rectangle clip_rectangle, LinkLabel label)\r
+ {\r
+ Color color;\r
+\r
+ dc.FillRectangle (ResPool.GetSolidBrush (label.BackColor), clip_rectangle);\r
+ CPDrawBorderStyle (dc, label.ClientRectangle, label.BorderStyle);\r
+\r
+ if (label.Links.Count == 1 && label.Links[0].Start == 0 && label.Links[0].Length == -1) {\r
+\r
+ color = label.GetLinkColor (label.pieces[0], 0);\r
+ dc.DrawString (label.Text, label.Font, ResPool.GetSolidBrush (color),\r
+ label.ClientRectangle, label.string_format);\r
+ return;\r
+ }\r
+\r
+ for (int i = 0; i < label.num_pieces; i++) {\r
+\r
+ color = label.GetLinkColor (label.pieces[i], i);\r
+\r
+ if (label.pieces[i].link == null)\r
+ dc.DrawString (label.pieces[i].text, label.Font, ResPool.GetSolidBrush (Color.Black),\r
+ label.pieces[i].rect.X, label.pieces[i].rect.Y, label.string_format);\r
+ else\r
+ dc.DrawString (label.pieces[i].text, label.link_font, ResPool.GetSolidBrush (color),\r
+ label.pieces[i].rect.X, label.pieces[i].rect.Y, label.string_format);\r
+ } \r
+\r
+ }\r
+ #endregion // LinkLabel\r
#region ListBox
// Drawing
+2005-04-07 Sureshkumar T <tsureshkumar@novell.com>
+
+ * Mono.Data.Tds.dll.sources: In Mono.Data.Tds.Protocol
+ Added TdsAsyncResult.cs & TdsAsyncState.cs.
+
2004-08-14 Geoff Norton <gnorton@customerdna.com>
* Mono.Data.Tds.Protocol/TdsComm.cs:
+2005-04-07 Sureshkumar T <tsureshkumar@novell.com>
+ Ankit Jain <radical@corewars.org>
+
+ * TdsComm.cs: GetPhysicalPacket is devided further into seperate
+ methods GetPhysicalPacketHeader and
+ GetPhysicalPacketData. Implemented asynchronous ReadPacket method.
+
+ * ITds.cs: Added additional methods for asynchronous operations.
+
+ * Tds.cs: Implemented base methods for asynchronous
+ operations. Version specific derivatives should override for
+ specific operations.
+
+ * Tds70.cs: For stored procedure, "exec" is prefixed by
+ default. Implemented asynchronous method for asynchronous command
+ execution.
+
+ * TdsAsyncState.cs: Added. Internal asynchronous state object.
+
+ * TdsAsyncResult.cs: Added. Internal asynchronous result
+ implementation.
+
2005-04-04 Sureshkumar T <tsureshkumar@novell.com>
* Tds50.cs: Pass parameters to the server. cut & paste from
event TdsInternalInfoMessageEventHandler TdsInfoMessage;
#endregion // Events
+
+#if NET_2_0
+ #region Asynchronous Methods
+ IAsyncResult BeginExecuteNonQuery (string sql,
+ TdsMetaParameterCollection parameters,
+ AsyncCallback callback,
+ object state);
+ void EndExecuteNonQuery (IAsyncResult ar);
+ IAsyncResult BeginExecuteQuery (string sql,
+ TdsMetaParameterCollection parameters,
+ AsyncCallback callback,
+ object state);
+ void EndExecuteQuery (IAsyncResult ar);
+
+ IAsyncResult BeginExecuteProcedure (string prolog,
+ string epilog,
+ string cmdText,
+ bool IsNonQuery,
+ TdsMetaParameterCollection parameters,
+ AsyncCallback callback,
+ object state);
+ void EndExecuteProcedure (IAsyncResult ar);
+
+ void WaitFor (IAsyncResult ar);
+ void CheckAndThrowException (IAsyncResult ar);
+
+ #endregion //Asynchronous Methods
+#endif // NET_2_0
+
}
}
}
#endregion // Private Methods
+
+#if NET_2_0
+ #region asynchronous methods
+ protected IAsyncResult BeginExecuteQueryInternal (string sql, bool wantResults,
+ AsyncCallback callback, object state)
+ {
+ moreResults = true;
+ doneProc = false;
+ messages.Clear ();
+ outputParameters.Clear ();
+
+ TdsAsyncResult ar = new TdsAsyncResult (callback, state);
+ ar.TdsAsyncState.WantResults = wantResults;
+
+ Comm.StartPacket (TdsPacketType.Query);
+ Comm.Append (sql);
+ Comm.SendPacket ();
+
+ Comm.BeginReadPacket (new AsyncCallback(OnBeginExecuteQueryCallback),
+ ar);
+ return ar;
+ }
+
+ protected void EndExecuteQueryInternal (IAsyncResult ar)
+ {
+ if (!ar.IsCompleted)
+ ar.AsyncWaitHandle.WaitOne ();
+ TdsAsyncResult result = (TdsAsyncResult) ar;
+ if (result.IsCompletedWithException)
+ throw result.Exception;
+ }
+
+ protected void OnBeginExecuteQueryCallback (IAsyncResult ar)
+ {
+ TdsAsyncResult result = (TdsAsyncResult) ar.AsyncState;
+ TdsAsyncState tdsState = (TdsAsyncState) result.TdsAsyncState;
+
+ try {
+ Comm.EndReadPacket (ar);
+ if (!tdsState.WantResults)
+ SkipToEnd ();
+ } catch (Exception e) {
+ result.MarkComplete (e);
+ return;
+ }
+ result.MarkComplete ();
+ }
+
+
+ public virtual IAsyncResult BeginExecuteNonQuery (string sql,
+ TdsMetaParameterCollection parameters,
+ AsyncCallback callback,
+ object state)
+ {
+ // abstract, kept to be backward compatiable.
+ throw new NotImplementedException ("should not be called!");
+ }
+
+ public virtual void EndExecuteNonQuery (IAsyncResult ar)
+ {
+ // abstract method
+ throw new NotImplementedException ("should not be called!");
+ }
+
+ public virtual IAsyncResult BeginExecuteQuery (string sql,
+ TdsMetaParameterCollection parameters,
+ AsyncCallback callback,
+ object state)
+ {
+ // abstract, kept to be backward compatiable.
+ throw new NotImplementedException ("should not be called!");
+ }
+
+ public virtual void EndExecuteQuery (IAsyncResult ar)
+ {
+ // abstract method
+ throw new NotImplementedException ("should not be called!");
+ }
+
+ public virtual IAsyncResult BeginExecuteProcedure (string prolog,
+ string epilog,
+ string cmdText,
+ bool IsNonQuery,
+ TdsMetaParameterCollection parameters,
+ AsyncCallback callback,
+ object state)
+ {
+ throw new NotImplementedException ("should not be called!");
+ }
+
+ public virtual void EndExecuteProcedure (IAsyncResult ar)
+ {
+ // abstract method
+ throw new NotImplementedException ("should not be called!");
+ }
+
+ public void WaitFor (IAsyncResult ar)
+ {
+ if (! ar.IsCompleted)
+ ar.AsyncWaitHandle.WaitOne ();
+ }
+
+ public void CheckAndThrowException (IAsyncResult ar)
+ {
+ TdsAsyncResult result = (TdsAsyncResult) ar;
+ if (result.IsCompleted && result.IsCompletedWithException)
+ throw result.Exception;
+ }
+
+ #endregion // asynchronous methods
+#endif // NET_2_0
+
+
}
}
}
}
}
- if (count > 0 || exec.Length > 0)
- exec = "exec " + exec;
-
- return String.Format ("{0}{1}{2}{3} {4}\n{5}", declare.ToString (), set.ToString (), exec, procedure, BuildParameters (), select.ToString ());
+ exec = "exec " + exec;
+
+ string sql = String.Format ("{0}{1}{2}{3} {4}\n{5}", declare.ToString (), set.ToString (), exec, procedure, BuildParameters (), select.ToString ());
+ return sql;
}
public override bool Connect (TdsConnectionParameters connectionParameters)
}
#endregion // Methods
+
+#if NET_2_0
+ #region Asynchronous Methods
+ public override IAsyncResult BeginExecuteNonQuery (string cmdText,
+ TdsMetaParameterCollection parameters,
+ AsyncCallback callback,
+ object state)
+ {
+ Parameters = parameters;
+ string sql = cmdText;
+ if (Parameters != null && Parameters.Count > 0)
+ sql = BuildExec (cmdText);
+
+ IAsyncResult ar = BeginExecuteQueryInternal (sql, false, callback, state);
+ return ar;
+ }
+
+ public override void EndExecuteNonQuery (IAsyncResult ar)
+ {
+ EndExecuteQueryInternal (ar);
+ }
+
+ public override IAsyncResult BeginExecuteQuery (string cmdText,
+ TdsMetaParameterCollection parameters,
+ AsyncCallback callback,
+ object state)
+ {
+ Parameters = parameters;
+ string sql = cmdText;
+ if (Parameters != null && Parameters.Count > 0)
+ sql = BuildExec (cmdText);
+
+ IAsyncResult ar = BeginExecuteQueryInternal (sql, true, callback, state);
+ return ar;
+ }
+
+ public override void EndExecuteQuery (IAsyncResult ar)
+ {
+ EndExecuteQueryInternal (ar);
+ }
+
+
+ public override IAsyncResult BeginExecuteProcedure (string prolog,
+ string epilog,
+ string cmdText,
+ bool IsNonQuery,
+ TdsMetaParameterCollection parameters,
+ AsyncCallback callback,
+ object state)
+ {
+
+
+ Parameters = parameters;
+ string pcall = BuildProcedureCall (cmdText);
+ string sql = String.Format ("{0};{1};{2};", prolog, pcall, epilog);
+
+ IAsyncResult ar = BeginExecuteQueryInternal (sql, !IsNonQuery, callback, state);
+ return ar;
+ }
+
+ public override void EndExecuteProcedure (IAsyncResult ar)
+ {
+ EndExecuteQueryInternal (ar);
+ }
+
+
+
+ #endregion // Asynchronous Methods
+#endif // NET_2_0
+
}
}
--- /dev/null
+//
+// Mono.Data.Tds.Protocol.TdsAsyncResult.cs
+//
+// Author:
+// T Sureshkumar <tsureshkumar@novell.com>
+// Ankit Jain <radical@corewars.org>
+
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+
+#if NET_2_0
+using System;
+using System.Threading;
+
+namespace Mono.Data.Tds.Protocol
+{
+ internal class TdsAsyncResult : IAsyncResult
+ {
+ private TdsAsyncState _tdsState;
+ private WaitHandle _waitHandle;
+ private bool _completed = false;
+ private bool _completedSyncly = false;
+ private AsyncCallback _userCallback;
+ private object _retValue;
+ private Exception _exception = null;
+
+ public TdsAsyncResult (AsyncCallback userCallback, TdsAsyncState tdsState)
+ {
+ _tdsState = tdsState;
+ _userCallback = userCallback;
+ _waitHandle = new ManualResetEvent (false);
+ }
+
+ public TdsAsyncResult (AsyncCallback userCallback, object state)
+ {
+ _tdsState = new TdsAsyncState (state);
+ _userCallback = userCallback;
+ _waitHandle = new ManualResetEvent (false);
+ }
+
+
+ public object AsyncState
+ {
+ get { return _tdsState.UserState; }
+ }
+
+ internal TdsAsyncState TdsAsyncState
+ {
+ get { return _tdsState; }
+ }
+
+ public WaitHandle AsyncWaitHandle
+ {
+ get { return _waitHandle; }
+
+ }
+
+ public bool IsCompleted
+ {
+ get { return _completed; }
+ }
+
+ public bool IsCompletedWithException
+ {
+ get { return _exception != null; }
+ }
+
+ public Exception Exception
+ {
+ get { return _exception; }
+ }
+
+ public bool CompletedSynchronously
+ {
+ get { return _completedSyncly; }
+ }
+
+ internal object ReturnValue
+ {
+ get { return _retValue; }
+ set { _retValue = value; }
+ }
+
+ internal void MarkComplete ()
+ {
+ _completed = true;
+ _exception = null;
+ ((ManualResetEvent)_waitHandle).Set ();
+
+ if (_userCallback != null)
+ _userCallback (this);
+ }
+
+ internal void MarkComplete (Exception e)
+ {
+ _completed = true;
+ _exception = e;
+ ((ManualResetEvent)_waitHandle).Set ();
+
+ if (_userCallback != null)
+ _userCallback (this);
+ }
+ }
+}
+
+#endif // NET_2_0
--- /dev/null
+//
+// Mono.Data.Tds.Protocol.TdsAsyncState.cs
+//
+// Author:
+// T Sureshkumar <tsureshkumar@novell.com>
+// Ankit Jain <radical@corewars.org>
+//
+
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using System;
+using System.Net.Sockets;
+
+
+namespace Mono.Data.Tds.Protocol {
+ internal class TdsAsyncState
+ {
+ object _userState;
+ bool _wantResults = false;
+
+ public TdsAsyncState (object userState)
+ {
+ _userState = userState;
+ }
+
+ public object UserState
+ {
+ get {return _userState;}
+ set {_userState = value;}
+ }
+
+ public bool WantResults
+ {
+ get {return _wantResults;}
+ set {_wantResults = value;}
+ }
+
+ }
+}
+#endif // NET_2_0
private void GetPhysicalPacket ()
{
- int nread = 0;
+ int dataLength = GetPhysicalPacketHeader ();
+ GetPhysicalPacketData (dataLength);
+ }
+ private int GetPhysicalPacketHeader ()
+ {
+ int nread = 0;
+
// read the header
while (nread < 8)
nread += stream.Read (tmpBuf, nread, 8 - nread);
if (len < 0) {
throw new Exception (String.Format ("Confused by a length of {0}", len));
}
+
+ return len;
- // now get the data
- nread = 0;
- while (nread < len) {
- nread += stream.Read (inBuffer, nread, len - nread);
+ }
+
+ private void GetPhysicalPacketData (int length)
+ {
+ // now get the data
+ int nread = 0;
+ while (nread < length) {
+ nread += stream.Read (inBuffer, nread, length - nread);
}
packetsReceived++;
// adjust the bookkeeping info about the incoming buffer
- inBufferLength = len;
+ inBufferLength = length;
inBufferIndex = 0;
- }
+ }
+
private static int Ntohs (byte[] buf, int offset)
{
}
#endregion // Methods
+#if NET_2_0
+ #region Async Methods
+
+ public IAsyncResult BeginReadPacket (AsyncCallback callback, object stateObject)
+ {
+ TdsAsyncResult ar = new TdsAsyncResult (callback, stateObject);
+
+ stream.BeginRead (tmpBuf, 0, 8, new AsyncCallback(OnReadPacketCallback), ar);
+ return ar;
+ }
+
+ /// <returns>Packet size in bytes</returns>
+ public int EndReadPacket (IAsyncResult ar)
+ {
+ if (!ar.IsCompleted)
+ ar.AsyncWaitHandle.WaitOne ();
+ return (int) ((TdsAsyncResult) ar).ReturnValue;
+ }
+
+
+ public void OnReadPacketCallback (IAsyncResult socketAsyncResult)
+ {
+ TdsAsyncResult ar = (TdsAsyncResult) socketAsyncResult.AsyncState;
+ int nread = stream.EndRead (socketAsyncResult);
+
+ while (nread < 8)
+ nread += stream.Read (tmpBuf, nread, 8 - nread);
+
+ TdsPacketType packetType = (TdsPacketType) tmpBuf[0];
+ if (packetType != TdsPacketType.Logon && packetType != TdsPacketType.Query && packetType != TdsPacketType.Reply)
+ {
+ throw new Exception (String.Format ("Unknown packet type {0}", tmpBuf[0]));
+ }
+
+ // figure out how many bytes are remaining in this packet.
+ int len = Ntohs (tmpBuf, 2) - 8;
+
+ if (len >= inBuffer.Length)
+ inBuffer = new byte[len];
+
+ if (len < 0) {
+ throw new Exception (String.Format ("Confused by a length of {0}", len));
+ }
+
+ GetPhysicalPacketData (len);
+ int value = len + 8;
+ ar.ReturnValue = ((object)value); // packet size
+ ar.MarkComplete ();
+ }
+
+ #endregion // Async Methods
+#endif // NET_2_0
+
}
}
Mono.Data.Tds.Protocol/TdsTimeoutException.cs
Mono.Data.Tds.Protocol/TdsVersion.cs
Mono.Data.Tds.Protocol/TODOAttribute.cs
+Mono.Data.Tds.Protocol/TdsAsyncState.cs
+Mono.Data.Tds.Protocol/TdsAsyncResult.cs
+2005-04-07 Sebastien Pouliot <sebastien@ximian.com>
+
+ * SslCipherSuite.cs: Fix calculation (sequence number) for the server
+ side stream. Patch by Brian Ritchie.
+
2005-02-04 Sebastien Pouliot <sebastien@ximian.com>
* Reverting last changes in SslClientStream and RecordProtocol. This
block.Write(this.pad1);
if (this.Context is ClientContext)
{
- block.Write(this.Context.ReadSequenceNumber);
+ block.Write(this.Context.WriteSequenceNumber);
}
else
{
- block.Write(this.Context.WriteSequenceNumber);
+ block.Write(this.Context.ReadSequenceNumber);
}
block.Write((byte)contentType);
block.Write((short)fragment.Length);
#endregion
}
-}
\ No newline at end of file
+}
+2005-04-07 Sebastien Pouliot <sebastien@ximian.com>
+
+ * postmulti.cs: New. Async POST tests using HttpWebRequest.
+ * Makefile: Build postmulti tool.
+ * README: updated instructions with the new postmulti tool.
+
2005-04-06 Sebastien Pouliot <sebastien@ximian.com>
* postecho.cs: Added an ICertificatePolicy to ease testing with
clean-local:
rm -f *.exe *.mdb *.pdb
-sources = postecho.cs
+sources = postecho.cs postmulti.cs
DISTFILES = $(sources)
dist-local: dist-default
-all: postecho.exe
+all: postecho.exe postmulti.exe
-postecho.exe: $(sources)
- $(CSCOMPILE) /target:exe /out:$@ $(sources)
+postecho.exe: postecho.cs
+ $(CSCOMPILE) /target:exe /out:$@ $^
+
+postmulti.exe: postmulti.cs
+ $(CSCOMPILE) /target:exe /out:$@ $^
wise not result wise) if you test with the MS runtime.
+POSTMULTI
+
+To run the postmulti tool your web server(s) must have a script present to
+return the TEST variable value to the tool.
+
+The tool use async HttpWebRequest|Response to send and receive a fixed (in
+source code, default is 1 megabytes) length buffer from all URLs specified
+on the command line.
+
+The WaitHandle class has a limit of 64 handles. Supplying more than 64 URLs
+on the command-line will result in a NotSupportedException exception.
+
+
+NOTES
+
Available server-side scripts
1. sendback.asp
--- /dev/null
+//
+// postmulti.cs: Multi-sessions TLS/SSL Test Program
+// based on tlstest.cs, tlsmulti.cs and postecho.cs
+//
+// Author:
+// Sebastien Pouliot <sebastien@ximian.com>
+//
+// Copyright (C) 2004-2005 Novell (http://www.novell.com)
+//
+
+using System;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Reflection;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Threading;
+
+using Mono.Security.Protocol.Tls;
+
+public class State {
+
+ static ArrayList handleList = new ArrayList ();
+
+ private int id;
+ private HttpWebRequest request;
+ private ManualResetEvent handle;
+
+ public State (int id, HttpWebRequest req)
+ {
+ this.id = id;
+ request = req;
+ handle = new ManualResetEvent (false);
+ handleList.Add (handle);
+ }
+
+ public int Id {
+ get { return id; }
+ }
+
+ public HttpWebRequest Request {
+ get { return request; }
+ }
+
+ public void Complete ()
+ {
+ handle.Set ();
+ }
+
+ static public void WaitAll ()
+ {
+ if (handleList.Count > 0) {
+ WaitHandle[] handles = (WaitHandle[]) handleList.ToArray (typeof (WaitHandle));
+ WaitHandle.WaitAll (handles);
+ handleList.Clear ();
+ }
+ }
+}
+
+public class MultiTest {
+
+ public const int buffersize = 1024 * 1024;
+
+ static byte[] data = new byte [buffersize];\r
+
+ public static void Main (string[] args)
+ {
+ ServicePointManager.CertificatePolicy = new TestCertificatePolicy ();
+
+ string postdata = "TEST=";
+ byte[] bytes = Encoding.Default.GetBytes (postdata);
+
+ // prepare test buffer
+ for (int i = 0; i < buffersize; i++)\r
+ data[i] = 65;
+
+ int id = 1;
+ foreach (string url in args) {
+ Console.WriteLine ("POST #{0} at {1}", id, url);
+ HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
+ req.Method = "POST";
+ req.ContentType = "application/x-www-form-urlencoded";
+ req.ContentLength = 5 + data.Length;
+
+ Stream output = req.GetRequestStream ();
+ output.Write (bytes, 0, bytes.Length);\r
+ output.Write (data, 0, data.Length);
+ output.Close ();
+
+ State s = new State (id++, req);
+ req.BeginGetResponse (new AsyncCallback (ResponseCallback), s);
+ }
+
+ State.WaitAll ();
+ }
+
+ private static void ResponseCallback (IAsyncResult result)
+ {
+ State state = ((State) result.AsyncState);
+ HttpWebResponse response = (HttpWebResponse) state.Request.EndGetResponse (result);
+
+ Stream stream = response.GetResponseStream ();
+ StreamReader sr = new StreamReader (stream, Encoding.UTF8);
+ string received = sr.ReadToEnd ();
+
+ if (data.Length != received.Length) {\r
+ Console.WriteLine ("ECHO #{0} - Invalid length {1}. Expected {2}", state.Id, received.Length, data.Length);\r
+ } else {
+ bool ok = true;\r
+ for (int i = 0; i < received.Length; i++) {\r
+ if (received[i] != 'A') {
+ ok = false;\r
+ Console.WriteLine ("ECHO #{0} - Error at position #{1} - received '{2}'", state.Id, i, received[i]);\r
+ break;\r
+ }
+ }
+ if (ok)\r
+ Console.WriteLine ("ECHO #{0} - Result OK (length: {1})", state.Id, received.Length);\r
+ }\r
+
+ state.Complete ();
+ }
+
+ public class TestCertificatePolicy : ICertificatePolicy {
+
+ public bool CheckValidationResult (ServicePoint sp, X509Certificate certificate, WebRequest request, int error)
+ {
+ // whatever the reason we do not stop the SSL connection
+ return true;
+ }
+ }
+}
+2005-04-07 Sebastien Pouliot <sebastien@ximian.com>
+
+ * tlsmulti.cs: New. Async GET tests using HttpWebRequest.
+ * Makefile: Build tlsmulti tool.
+
2004-02-25 Sebastien Pouliot <sebastien@ximian.com>
* tlstest.cs: Updated to support Basic and Digest authentication. Also
clean-local:
rm -f *.exe *.pdb
-sources = tlstest.cs
+sources = tlstest.cs tlsmulti.cs
DISTFILES = $(sources)
dist-local: dist-default
-all: tlstest.exe
+all: tlstest.exe tlsmulti.exe
-tlstest.exe: $(sources)
- $(CSCOMPILE) /target:exe /out:$@ $(sources)
+tlstest.exe: tlstest.cs
+ $(CSCOMPILE) /target:exe /out:$@ $^
+
+tlsmulti.exe: tlsmulti.cs
+ $(CSCOMPILE) /target:exe /out:$@ $^
--- /dev/null
+//
+// tlsmulti.cs: Multi-sessions TLS/SSL Test Program
+// based on tlstest.cs
+//
+// Author:
+// Sebastien Pouliot <sebastien@ximian.com>
+//
+// Copyright (C) 2004-2005 Novell (http://www.novell.com)
+//
+
+using System;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Reflection;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Threading;
+
+using Mono.Security.Protocol.Tls;
+
+public class State {
+
+ static ArrayList handleList = new ArrayList ();
+
+ private int id;
+ private HttpWebRequest request;
+ private ManualResetEvent handle;
+
+ public State (int id, HttpWebRequest req)
+ {
+ this.id = id;
+ request = req;
+ handle = new ManualResetEvent (false);
+ handleList.Add (handle);
+ }
+
+ public int Id {
+ get { return id; }
+ }
+
+ public HttpWebRequest Request {
+ get { return request; }
+ }
+
+ public void Complete ()
+ {
+ handle.Set ();
+ }
+
+ static public void WaitAll ()
+ {
+ if (handleList.Count > 0) {
+ WaitHandle[] handles = (WaitHandle[]) handleList.ToArray (typeof (WaitHandle));
+ WaitHandle.WaitAll (handles);
+ handleList.Clear ();
+ }
+ }
+}
+
+public class MultiTest {
+
+ public static void Main (string[] args)
+ {
+ if (args.Length > 64) {
+ Console.WriteLine ("WaitHandle has a limit of 64 handles so you cannot process {0} URLs.", args.Length);
+ return;
+ }
+
+ ServicePointManager.CertificatePolicy = new TestCertificatePolicy ();
+
+ int id = 1;
+ foreach (string url in args) {
+ Console.WriteLine ("GET #{0} at {1}", id, url);
+ HttpWebRequest wreq = (HttpWebRequest) WebRequest.Create (url);
+ State s = new State (id++, wreq);
+ wreq.BeginGetResponse (new AsyncCallback (ResponseCallback), s);
+ }
+
+ State.WaitAll ();
+ }
+
+ private static void ResponseCallback (IAsyncResult result)
+ {
+ State state = ((State) result.AsyncState);
+ HttpWebResponse response = (HttpWebResponse) state.Request.EndGetResponse (result);
+
+ Stream stream = response.GetResponseStream ();
+ StreamReader sr = new StreamReader (stream, Encoding.UTF8);
+ sr.ReadToEnd ();
+
+ Console.WriteLine ("END #{0}", state.Id);\r
+ state.Complete ();
+ }
+
+ public class TestCertificatePolicy : ICertificatePolicy {
+
+ public bool CheckValidationResult (ServicePoint sp, X509Certificate certificate, WebRequest request, int error)
+ {
+ // whatever the reason we do not stop the SSL connection
+ return true;
+ }
+ }
+}
+2005-04-08 Raja R Harinath <rharinath@novell.com>
+
+ * Makefile (EXTRA_DISTFILES): Add support file
+ Test/.../InstallerAssembly.cs.
+
2005-03-24 Muthu Kannan <t.manki@gmail.com>
* Makefile (test-local): Create InstallerAssembly.dll for unit
LIB_MCS_FLAGS = /r:$(corlib) /r:System.dll /r:System.Xml.dll /r:System.Runtime.Serialization.Formatters.Soap.dll
TEST_MCS_FLAGS = $(LIB_MCS_FLAGS)
-EXTRA_DISTFILES = Test/ChangeLog
+EXTRA_DISTFILES = Test/ChangeLog Test/System.Configuration.Install/InstallerAssembly.cs
include ../../build/library.make
if (value)
Context = new InstallContext (Path + ".InstallLog", null);
else
- Context = new InstallContext (null, CommandLine);
+ Context = new InstallContext (Path + ".InstallLog", CommandLine);
useNewContext = value;
}
}
foreach (Type t in getInstallersFromAssembly (Assembly)) {
Installer i = (Installer) Activator.CreateInstance (t);
+ i.Context = this.Context;
Installers.Add (i);
}
}
return ret;
}
+ private bool isInstallable ()
+ {
+ try {
+ CheckIfInstallable (Path);
+ } catch (Exception e) {
+ Context.LogMessage ("Assembly " + Path + " does not have any public installers in it.");
+ return false;
+ }
+ return true;
+ }
+
public override void Install (IDictionary state)
{
// Make sure that the assembly is installable
- CheckIfInstallable (Path);
+ if (! isInstallable ())
+ return;
addSubInstallers ();
state = new Hashtable ();
string stateFile = System.IO.Path.ChangeExtension (this.Path, STATE_FILE_EXT);
try {
- Console.WriteLine ("Starting installation");
+ string logFilePath = Context.Parameters ["LogFile"];
+ if (logFilePath != null && logFilePath != "")
+ Console.WriteLine ("Installation log for assembly " + Path + " is found at " + logFilePath);
+ Context.LogMessage ("Starting installation of assembly: " + Path);
base.Install (state);
} finally {
// Serialise state
file.Close ();
}
}
- Console.WriteLine ("Completed installation");
+ Context.LogMessage ("Installation completed");
}
public override void Commit (IDictionary state)
{
+ // Make sure that the assembly is installable
+ if (! isInstallable ())
+ return;
+
addSubInstallers ();
string stateFile = System.IO.Path.ChangeExtension (this.Path, STATE_FILE_EXT);
// Read serialised state
file.Close ();
}
+ Context.LogMessage ("Starting commit of assembly: " + Path);
base.Commit (state);
+ Context.LogMessage ("Commit completed");
}
public override void Rollback (IDictionary state)
{
+ // Make sure that the assembly is installable
+ if (! isInstallable ())
+ return;
+
addSubInstallers ();
string stateFile = System.IO.Path.ChangeExtension (this.Path, STATE_FILE_EXT);
file.Close ();
}
+ Context.LogMessage ("Starting rollback of assembly: " + Path);
base.Rollback (state);
File.Delete (stateFile);
+ Context.LogMessage ("Rollback completed");
}
public override void Uninstall (IDictionary state)
{
+ // Make sure that the assembly is installable
+ if (! isInstallable ())
+ return;
+
addSubInstallers ();
string stateFile = System.IO.Path.ChangeExtension (this.Path, STATE_FILE_EXT);
state = null;
}
+ string logFilePath = Context.Parameters ["LogFile"];
+ if (logFilePath != null && logFilePath != "")
+ Console.WriteLine ("Installation log for assembly " + Path + " is found at " + logFilePath);
+
+ Context.LogMessage ("Starting uninstallation of assembly: " + Path);
base.Uninstall (state);
File.Delete (stateFile);
+ Context.LogMessage ("Uninstallation completed");
}
}
+2005-04-07 Muthu Kannan <t.manki@gmail.com>
+
+ * AssemblyInstaller.cs (UseNewContext): Set default path.
+ (Install,Commit,Rollback,Uninstall): Log events.
+ * Installer.cs (Install, Commit, Rollback,Uninstall):
+ Don't set installer context when invoking subinstallers.
+ * InstallContext.cs (ParseCommandLine): Fix handling of '--'
+ options.
+ * TransactedInstaller.cs (Install): Fix typo.
+
2005-03-24 Muthu Kannan <t.manki@gmail.com>
Near-complete implementation of System.Configuration.Install.
foreach (string a in args) {
// Remove leading / or - or --
string x = a; // I am using x instead of a
- if (x.StartsWith ("/") || x.StartsWith ("-"))
- x = x.Substring (1);
- else if (a.StartsWith ("--"))
+ if (a.StartsWith ("--"))
x = x.Substring (2);
+ else if (x.StartsWith ("/") || x.StartsWith ("-"))
+ x = x.Substring (1);
int index;
if ((index = x.IndexOf ("=")) == -1) {
for (i = 0; i <= maxi; ++i) {
IDictionary ht = new Hashtable ();
try {
- Installers [i].Context = this.Context;
Installers [i].Install (ht);
} finally {
state.Add (STATE_PREFIX + i.ToString(), ht);
for (int i = 0; i <= lastInstaller; ++i) {
try {
- Installers [i].Context = this.Context;
Installers [i].Commit (states [i]);
} catch (Exception e) {
caught = e;
for (int i = 0; i <= lastInstaller; ++i) {
try {
- Installers [i].Context = this.Context;
Installers [i].Rollback (states [i]);
} catch (Exception e) {
caught = e;
for (int i = 0; i <= lastInstaller; ++i) {
try {
- Installers [i].Context = this.Context;
Installers [i].Uninstall (states [i]);
} catch (Exception e) {
caught = e;
}
try {
- Context.LogMessage ("Installation phasing completed successfully -- starting commit.");
+ Context.LogMessage ("Installation phase completed successfully -- starting commit.");
Commit (state);
} catch (Exception e) {
Context.LogMessage ("Commit failed.");
+2005-04-08 Raja R Harinath <rharinath@novell.com>
+
+ * Makefile (EXTRA_DISTFILES): Add app_test_2.0.config.
+
+2005-04-07 Sureshkumar T <tsureshkumar@novell.com>
+
+ * System.Data.dll.sources: In System.Data.SqlClient
+ Added SqlAsyncState.cs & SqlAsyncResult.cs
+
2005-04-04 Sureshkumar T <tsureshkumar@novell.com>
* System.Data_test.dll.sources: Added
Test/System.Xml/region.xml \
Test/System.Xml/region.xsd \
Test/System.Xml/store.xsd \
- Mono.Data.SqlExpressions/Parser.jay
+ Mono.Data.SqlExpressions/Parser.jay \
+ app_test_2.0.config
BUILT_SOURCES = Mono.Data.SqlExpressions/Parser.cs
+2005-04-07 Sureshkumar T <tsureshkumar@novell.com>
+ Ankit Jain <radical@corewars.org>
+
+ * SqlConnection.cs: Implemented additional connection string
+ property "Asynchronous Processing".
+
+ * SqlCommand.cs: Implemented Asynchronous command execution API.
+
+ * SqlAsyncState.cs: A internal state object for asynchronous
+ operations.
+
+ * SqlAsyncResult.cs: Added. Class to hold result for asynchronous
+ queries.
+
2005-03-28 Sureshkumar T <tsureshkumar@novell.com>
* SqlCommand.cs: Execute: Add a semicolon at the end of
--- /dev/null
+//
+// System.Data.SqlClient.SqlAsyncResult.cs
+//
+// Author:
+// T Sureshkumar <tsureshkumar@novell.com>
+// Ankit Jain <radical@corewars.org>
+//
+
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+
+#if NET_2_0
+using System;
+using System.Threading;
+
+namespace System.Data.SqlClient
+{
+ internal class SqlAsyncResult : IAsyncResult
+ {
+ private SqlAsyncState _sqlState;
+ private WaitHandle _waitHandle;
+ private bool _completed = false;
+ private bool _completedSyncly = false;
+ private bool _ended = false;
+ private AsyncCallback _userCallback = null;
+ private object _retValue;
+ private string _endMethod;
+ private IAsyncResult _internal;
+
+ public SqlAsyncResult (AsyncCallback userCallback, SqlAsyncState sqlState)
+ {
+ _sqlState = sqlState;
+ _userCallback = userCallback;
+ _waitHandle = new ManualResetEvent (false);
+ }
+
+ public SqlAsyncResult (AsyncCallback userCallback, object state)
+ {
+ _sqlState = new SqlAsyncState (state);
+ _userCallback = userCallback;
+ _waitHandle = new ManualResetEvent (false);
+ }
+
+ public object AsyncState
+ {
+ get { return _sqlState.UserState; }
+ }
+
+ internal SqlAsyncState SqlAsyncState
+ {
+ get { return _sqlState; }
+ }
+
+ public WaitHandle AsyncWaitHandle
+ {
+ get { return _waitHandle; }
+
+ }
+
+ public bool IsCompleted
+ {
+ get { return _completed; }
+ }
+
+ public bool CompletedSynchronously
+ {
+ get { return _completedSyncly; }
+ }
+
+ internal object ReturnValue
+ {
+ get { return _retValue; }
+ set { _retValue = value; }
+ }
+
+ public string EndMethod
+ {
+ get { return _endMethod; }
+ set { _endMethod = value; }
+ }
+
+ public bool Ended
+ {
+ get { return _ended; }
+ set { _ended = value; }
+ }
+
+
+ internal IAsyncResult InternalResult
+ {
+ get { return _internal; }
+ set { _internal = value; }
+ }
+
+ public AsyncCallback BubbleCallback
+ {
+ get { return new AsyncCallback (Bubbleback); }
+
+ }
+
+ internal void MarkComplete ()
+ {
+ _completed = true;
+ ((ManualResetEvent)_waitHandle).Set ();
+
+ if (_userCallback != null)
+ _userCallback (this);
+ }
+
+ public void Bubbleback (IAsyncResult ar)
+ {
+ this.MarkComplete ();
+ }
+ }
+}
+
+#endif // NET_2_0
--- /dev/null
+//
+// System.Data.SqlClient.SqlAsyncState.cs
+//
+// Author:
+// T Sureshkumar <tsureshkumar@novell.com>
+// Ankit Jain <radical@corewars.org>
+//
+
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using System;
+using System.Net.Sockets;
+
+
+namespace System.Data.SqlClient
+{
+ internal class SqlAsyncState
+ {
+ object _userState;
+
+ public SqlAsyncState (object userState)
+ {
+ _userState = userState;
+ }
+
+ public object UserState
+ {
+ get {return _userState;}
+ set {_userState = value;}
+ }
+ }
+}
+#endif // NET_2_0
throw new InvalidOperationException ("There is already an open DataReader associated with this Connection which must be closed first.");
if (Connection.XmlReader != null)
throw new InvalidOperationException ("There is already an open XmlReader associated with this Connection which must be closed first.");
+#if NET_2_0
+ if (method.StartsWith ("Begin") && !Connection.AsyncProcessing)
+ throw new InvalidOperationException ("This Connection object is not " +
+ "in Asynchronous mode. Use 'Asynchronous" +
+ " Processing = true' to set it.");
+#endif // NET_2_0
}
#if NET_2_0
#endif // NET_2_0
#endregion // Methods
+
+#if NET_2_0
+ #region Asynchronous Methods
+
+ internal IAsyncResult BeginExecuteInternal (CommandBehavior behavior,
+ bool wantResults,
+ AsyncCallback callback,
+ object state)
+ {
+ IAsyncResult ar = null;
+ Connection.Tds.RecordsAffected = 0;
+ TdsMetaParameterCollection parms = Parameters.MetaParameters;
+ if (preparedStatement == null) {
+ bool schemaOnly = ((behavior & CommandBehavior.SchemaOnly) > 0);
+ bool keyInfo = ((behavior & CommandBehavior.KeyInfo) > 0);
+
+ StringBuilder sql1 = new StringBuilder ();
+ StringBuilder sql2 = new StringBuilder ();
+
+ if (schemaOnly || keyInfo)
+ sql1.Append ("SET FMTONLY OFF;");
+ if (keyInfo) {
+ sql1.Append ("SET NO_BROWSETABLE ON;");
+ sql2.Append ("SET NO_BROWSETABLE OFF;");
+ }
+ if (schemaOnly) {
+ sql1.Append ("SET FMTONLY ON;");
+ sql2.Append ("SET FMTONLY OFF;");
+ }
+
+ switch (CommandType) {
+ case CommandType.StoredProcedure:
+ string prolog = "";
+ string epilog = "";
+ if (keyInfo || schemaOnly)
+ prolog = sql1.ToString ();
+ if (keyInfo || schemaOnly)
+ epilog = sql2.ToString ();
+ Connection.Tds.BeginExecuteProcedure (prolog,
+ epilog,
+ CommandText,
+ !wantResults,
+ parms,
+ callback,
+ state);
+
+ break;
+ case CommandType.Text:
+ string sql = String.Format ("{0}{1};{2}", sql1.ToString (), CommandText, sql2.ToString ());
+ if (wantResults)
+ ar = Connection.Tds.BeginExecuteQuery (sql, parms,
+ callback, state);
+ else
+ ar = Connection.Tds.BeginExecuteNonQuery (sql, parms, callback, state);
+ break;
+ }
+ }
+ else
+ Connection.Tds.ExecPrepared (preparedStatement, parms, CommandTimeout, wantResults);
+
+ return ar;
+
+ }
+
+ internal void EndExecuteInternal (IAsyncResult ar)
+ {
+ SqlAsyncResult sqlResult = ( (SqlAsyncResult) ar);
+ Connection.Tds.WaitFor (sqlResult.InternalResult);
+ Connection.Tds.CheckAndThrowException (sqlResult.InternalResult);
+ }
+
+ public IAsyncResult BeginExecuteNonQuery ()
+ {
+ return BeginExecuteNonQuery (null, null);
+ }
+
+ public IAsyncResult BeginExecuteNonQuery (AsyncCallback callback, object state)
+ {
+ ValidateCommand ("BeginExecuteNonQuery");
+ SqlAsyncResult ar = new SqlAsyncResult (callback, state);
+ ar.EndMethod = "EndExecuteNonQuery";
+ ar.InternalResult = BeginExecuteInternal (CommandBehavior.Default, false, ar.BubbleCallback, ar);
+ return ar;
+ }
+
+ public int EndExecuteNonQuery (IAsyncResult ar)
+ {
+ ValidateAsyncResult (ar, "EndExecuteNonQuery");
+ EndExecuteInternal (ar);
+
+ int ret;
+ if (commandType == CommandType.StoredProcedure)
+ ret = -1;
+ else {
+ // .NET documentation says that except for INSERT, UPDATE and
+ // DELETE where the return value is the number of rows affected
+ // for the rest of the commands the return value is -1.
+ if ((CommandText.ToUpper().IndexOf("UPDATE")!=-1) ||
+ (CommandText.ToUpper().IndexOf("INSERT")!=-1) ||
+ (CommandText.ToUpper().IndexOf("DELETE")!=-1))
+ ret = Connection.Tds.RecordsAffected;
+ else
+ ret = -1;
+ }
+ GetOutputParameters ();
+ ( (SqlAsyncResult) ar).Ended = true;
+ return ret;
+ }
+
+ public IAsyncResult BeginExecuteReader ()
+ {
+ return BeginExecuteReader (null, null, CommandBehavior.Default);
+ }
+
+ public IAsyncResult BeginExecuteReader (CommandBehavior behavior)
+ {
+ return BeginExecuteReader (null, null, behavior);
+ }
+
+ public IAsyncResult BeginExecuteReader (AsyncCallback callback, object state)
+ {
+ return BeginExecuteReader (callback, state, CommandBehavior.Default);
+ }
+
+ public IAsyncResult BeginExecuteReader (AsyncCallback callback, object state, CommandBehavior behavior)
+ {
+ ValidateCommand ("BeginExecuteReader");
+ this.behavior = behavior;
+ SqlAsyncResult ar = new SqlAsyncResult (callback, state);
+ ar.EndMethod = "EndExecuteReader";
+ IAsyncResult tdsResult = BeginExecuteInternal (behavior, true,
+ ar.BubbleCallback, state);
+ ar.InternalResult = tdsResult;
+ return ar;
+ }
+
+ public SqlDataReader EndExecuteReader (IAsyncResult ar)
+ {
+ ValidateAsyncResult (ar, "EndExecuteReader");
+ EndExecuteInternal (ar);
+ SqlDataReader reader = null;
+ try {
+ reader = new SqlDataReader (this);
+ }
+ catch (TdsTimeoutException e) {
+ // if behavior is closeconnection, even if it throws exception
+ // the connection has to be closed.
+ if ((behavior & CommandBehavior.CloseConnection) != 0)
+ Connection.Close ();
+ throw SqlException.FromTdsInternalException ((TdsInternalException) e);
+ } catch (SqlException) {
+ // if behavior is closeconnection, even if it throws exception
+ // the connection has to be closed.
+ if ((behavior & CommandBehavior.CloseConnection) != 0)
+ Connection.Close ();
+
+ throw;
+ }
+
+ ( (SqlAsyncResult) ar).Ended = true;
+ return reader;
+ }
+
+ public IAsyncResult BeginExecuteXmlReader (AsyncCallback callback, object state)
+ {
+ ValidateCommand ("BeginExecuteXmlReader");
+ SqlAsyncResult ar = new SqlAsyncResult (callback, state);
+ ar.EndMethod = "EndExecuteXmlReader";
+ ar.InternalResult = BeginExecuteInternal (behavior, true,
+ ar.BubbleCallback, state);
+ return ar;
+ }
+
+ public XmlReader EndExecuteXmlReader (IAsyncResult ar)
+ {
+ ValidateAsyncResult (ar, "EndExecuteXmlReader");
+ EndExecuteInternal (ar);
+ SqlDataReader reader = new SqlDataReader (this);
+ SqlXmlTextReader textReader = new SqlXmlTextReader (reader);
+ XmlReader xmlReader = new XmlTextReader (textReader);
+ ( (SqlAsyncResult) ar).Ended = true;
+ return xmlReader;
+ }
+
+
+ internal void ValidateAsyncResult (IAsyncResult ar, string endMethod)
+ {
+ if (ar == null)
+ throw new ArgumentException ("result passed is null!");
+ if (! (ar is SqlAsyncResult))
+ throw new ArgumentException (String.Format ("cannot test validity of types {0}",
+ ar.GetType ()
+ ));
+ SqlAsyncResult result = (SqlAsyncResult) ar;
+
+ if (result.EndMethod != endMethod)
+ throw new InvalidOperationException (String.Format ("Mismatched {0} called for AsyncResult. " +
+ "Expected call to {1} but {0} is called instead.",
+ endMethod,
+ result.EndMethod
+ ));
+ if (result.Ended)
+ throw new InvalidOperationException (String.Format ("The method {0} cannot be called " +
+ "more than once for the same AsyncResult.",
+ endMethod));
+
+ }
+
+ #endregion // Asynchronous Methods
+#endif // NET_2_0
}
}
parameters["POOLING"] = "true";
if (null == parameters.Get ("WORKSTATION ID") && null == parameters.Get ("WSID"))
parameters["WORKSTATION ID"] = Dns.GetHostName();
+#if NET_2_0
+ if (null == parameters.Get ("ASYNC") &&
+ null == parameters.Get ("ASYNCHRONOUS PROCESSING"))
+ parameters ["ASYNCHRONOUS PROCESSING"] = "false";
+#endif
}
private void SetProperties (NameValueCollection parameters)
#if NET_2_0
case "MULTIPLEACTIVERESULTSETS":
break;
+ case "ASYNCHRONOUS PROCESSING" :
+ case "ASYNC" :
+ async = ConvertToBoolean (name, value);
+ break;
#endif
case "NET" :
case "NETWORK" :
}
#endregion // Methods
+
+#if NET_2_0
+ #region Fields Net 2
+
+ bool async = false;
+
+ #endregion // Fields Net 2
+
+ #region Properties Net 2
+
+ [DataSysDescription ("Enable Asynchronous processing, 'Asynchrouse Processing=true/false' in the ConnectionString.")]
+ [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+ internal bool AsyncProcessing {
+ get { return async; }
+ }
+
+ #endregion // Properties Net 2
+
+#endif // NET_2_0
+
}
}
System.Data.SqlClient/SqlNotificationInfo.cs
System.Data.SqlClient/SqlNotificationSource.cs
System.Data.SqlClient/ISqlNotificationReceiver.cs
+System.Data.SqlClient/SqlAsyncState.cs
+System.Data.SqlClient/SqlAsyncResult.cs
System.Data.SqlClient/SqlClientPermission.cs
System.Data.SqlClient/SqlClientPermissionAttribute.cs
System.Data.SqlClient/SqlCommand.cs
+2005-04-07 Lluis Sanchez Gual <lluis@novell.com>
+
+ * DataRowCollection.cs: Fix the signature of the Add method
+ for NET_2_0.
+
2005-03-16 Atsushi Enomoto <atsushi@ximian.com>
* DataRow.cs : on importing row, it was copying data from incorrect
/// <summary>
/// Creates a row using specified values and adds it to the DataRowCollection.
/// </summary>
+#if NET_2_0
+ public virtual DataRow Add (params object[] values)
+#else
public virtual DataRow Add (object[] values)
+#endif
{
if (values.Length > table.Columns.Count)
throw new ArgumentException ("The array is larger than the number of columns in the table.");
DbProviderFactory - done
DbConnectionFactory
- Add nunit test cases for these.
+ Add nunit test cases for these. - done
* Create Factory classes & methods for Providers.
Factory methods for SqlClient - done.
Factory methods for Odbc provider - done.
Factory methods for OleDb provider
-** DbConnectionStringBuilder - done (not added to sources list).
- This uses Generic.Collections.Dictionary, which has not yet
- been implemented. Once it is done, this can be added to sources.
+* DbConnectionStringBuilder - done
+
+Asynchronous Command Execution ((target: mono 1.2 PROFILE=net_2_0)
+==================================================================
+
+* Implement the following Asynchronous Execution Commands for SqlClient
+
+ - BeginExecuteNonQuery (2 overrides) - done
+ - BeginExecuteReader (3 overrides) - done
+ - BegineExecuteXmlReader - done
+
+ - Implement corresponding asynchronous methods in Tds driver - done
+
+* Pending
+
+ - Provide Stand Alone test cases
+ - Check whether the result column is xml while doing
+ EndExecuteXmlReader.
+
+
+Test Cases
+==========
+
+* Provide a single consistent test fixture for all data providers
+ available in Test/ProviderTests
+
+* NUnit-ize Provider Tests
+
+* Make these tests to be able to run by command
+ make run-test PROVIDER=mysql # to run tests marked for mysql & SQL92.
+
+* Provide SQL92 complaint scripts for shema & data, to be loaded
+ irrelevant of data providers.
+
+2005-04-07 Boris Kirzner <borisk@mainsoft.com>
+
+ * DirectoryServicesDirectoryEntryTest.cs:
+ - Rethrow AssertionException so the test will fail if Assert.Fail is called inside try/catch.
+ - Additional test case for Properties.
+ - Additional test case for DeleteTree.
+ - More testing for RefreshCache.
+
+
2005-03-29 Boris Kirzner <borisk@mainsoft.com>
* DirectoryServicesDirectoryEntryTest.cs:
barakTsabariDE.CommitChanges();\r
Assert.Fail("Object " + barakTsabariDN + " was not deleted from server.");\r
}\r
+ catch(AssertionException ae) {\r
+ throw ae;\r
+ }\r
catch (Exception e) {\r
// do nothing\r
}\r
barakTsabariDE.CommitChanges();\r
Assert.Fail("Object " + barakTsabariDN + " was not moved from old location on the server.");\r
}\r
+ catch(AssertionException ae) {\r
+ throw ae;\r
+ }\r
catch (Exception e) {\r
// do nothing\r
}\r
barakTsabariDE.CommitChanges();\r
Assert.Fail("Object " + barakTsabariDN + " was not renamed on the server.");\r
}\r
+ catch(AssertionException ae) {\r
+ throw ae;\r
+ }\r
catch (Exception e) {\r
// do nothing\r
}\r
barakTsabariDE.CommitChanges();\r
Assert.Fail("Object " + barakTsabariDN + " was not deleted from server.");\r
}\r
+ catch(AssertionException ae) {\r
+ throw ae;\r
+ }\r
catch (Exception e) {\r
// do nothing\r
}\r
barakTsabariDE.CommitChanges();\r
Assert.Fail("Object " + barakTsabariDN + " was not moved from old location on the server.");\r
}\r
+ catch(AssertionException ae) {\r
+ throw ae;\r
+ }\r
catch (Exception e) {\r
// do nothing\r
}\r
barakTsabariDE.CommitChanges();\r
Assert.Fail("Object " + barakTsabariDN + " was not renamed on the server.");\r
}\r
+ catch(AssertionException ae) {\r
+ throw ae;\r
+ }\r
catch (Exception e) {\r
// do nothing\r
}\r
\r
\r
[Test]\r
- public void DirectoryEntry_Properties()\r
+ public void DirectoryEntry_Properties1()\r
{\r
de = new DirectoryEntry(LDAPServerConnectionString);\r
\r
Assert.AreEqual(((PropertyValueCollection)de.Properties["dc"]).Value,"myhosting");\r
Assert.AreEqual(((PropertyValueCollection)de.Properties["description"]).Value,"My wonderful company as much text as you want to place in this line up to 32Kcontinuation data for the line above must have <CR> or <CR><LF> i.e. ENTER works on both Windows and *nix system - new line MUST begin with ONE SPACE");\r
Assert.AreEqual(((PropertyValueCollection)de.Properties["o"]).Value,"Example, Inc.");\r
+\r
+ // ensure that properties are not accessible after removing an entry from the server\r
+ string barakTsabariDN = LDAPServerRoot + "cn=Barak Tsabari,ou=Human Resources,ou=people,dc=myhosting,dc=example";\r
+ de = new DirectoryEntry(barakTsabariDN,\r
+ LDAPServerUsername,\r
+ LDAPServerPassword,\r
+ AuthenticationTypes.ServerBind);\r
+ \r
+ de.DeleteTree();\r
+ \r
+ try {\r
+ int i = de.Properties.Count;\r
+ Assert.Fail("Properties should not be accessible after deleting an entry from the server");\r
+ }\r
+ catch(AssertionException ae) {\r
+ throw ae;\r
+ }\r
+ catch(Exception e) {\r
+ // supress exception\r
+ }\r
+\r
+ try {\r
+ string s = (string)((PropertyValueCollection)de.Properties["dc"]).Value;\r
+ Assert.Fail("Properties should not be accessible after deleting an entry from the server");\r
+ }\r
+ catch(AssertionException ae) {\r
+ throw ae;\r
+ }\r
+ catch(Exception e) {\r
+ // supress exception\r
+ }\r
+ }\r
+\r
+ [Test]\r
+ public void DirectoryEntry_Properties2()\r
+ {\r
+ // delete entry, create a new one (the same) and access properties of the old object\r
+ string barakTsabariDN = LDAPServerRoot + "cn=Barak Tsabari,ou=Human Resources,ou=people,dc=myhosting,dc=example";\r
+ de = new DirectoryEntry(barakTsabariDN,\r
+ LDAPServerUsername,\r
+ LDAPServerPassword,\r
+ AuthenticationTypes.ServerBind);\r
+\r
+ // cause to properties loading\r
+ Assert.AreEqual(de.Properties.Count,6);\r
+ Assert.AreEqual(((PropertyValueCollection)de.Properties["sn"]).Value,"Tsabari");\r
+\r
+ // delete entry\r
+ de.DeleteTree();\r
+\r
+ // the local property chache is still accessible\r
+ Assert.AreEqual(de.Properties.Count,6);\r
+ Assert.AreEqual(((PropertyValueCollection)de.Properties["sn"]).Value,"Tsabari");\r
+\r
+ de.CommitChanges();\r
+\r
+ // the local property chache is still accessible\r
+ ((PropertyValueCollection)de.Properties["sn"]).Value = "Barbari";\r
+\r
+ // create the entry back again\r
+ DirectoryEntry ouHumanResources = new DirectoryEntry( LDAPServerRoot + "ou=Human Resources,ou=people,dc=myhosting,dc=example",\r
+ LDAPServerUsername,\r
+ LDAPServerPassword,\r
+ AuthenticationTypes.ServerBind);\r
+ DirectoryEntry cnBarakTsabari = ouHumanResources.Children.Add("cn=Barak Tsabari","Class");\r
+ ((PropertyValueCollection)cnBarakTsabari.Properties["objectClass"]).Add("person");\r
+ ((PropertyValueCollection)cnBarakTsabari.Properties["objectClass"]).Add("organizationalPerson");\r
+ cnBarakTsabari.Properties["cn"].Value = "Barak Tsabari";\r
+ cnBarakTsabari.Properties["facsimileTelephoneNumber"].Value = "+1 906 777 8853";\r
+ ((PropertyValueCollection)cnBarakTsabari.Properties["ou"]).Add("Human Resources");\r
+ ((PropertyValueCollection)cnBarakTsabari.Properties["ou"]).Add("People");\r
+ cnBarakTsabari.Properties["sn"].Value = "Tsabari";\r
+ cnBarakTsabari.Properties["telephoneNumber"].Value = "+1 906 777 8854";\r
+ cnBarakTsabari.CommitChanges();\r
+ \r
+ // the local property chache is still accessible\r
+ Assert.AreEqual(((PropertyValueCollection)de.Properties["sn"]).Value,"Barbari");\r
+\r
+ // Refresh from server\r
+ de.RefreshCache();\r
+ // ensure the properties of an entry are still accessible through the old object\r
+ Assert.AreEqual(((PropertyValueCollection)de.Properties["sn"]).Value,"Tsabari");\r
+\r
}\r
\r
\r
de.CommitChanges(); \r
Assert.Fail("Object " + johnSmithDN + " was not deleted from server");\r
}\r
+ catch(AssertionException ae) {\r
+ throw ae;\r
+ }\r
+ catch(Exception e) {\r
+ Console.WriteLine(e.StackTrace);\r
+ // do nothing\r
+ }\r
+ }\r
+\r
+ [Test]\r
+ public void DirectoryEntry_DeleteTree2()\r
+ {\r
+ string johnSmithDN = LDAPServerRoot + "cn=John Smith,ou=Human Resources,ou=people,dc=myhosting,dc=example";\r
+\r
+ Assert.IsTrue(DirectoryEntry.Exists(johnSmithDN));\r
+ // two objects refer to the same entry\r
+ de = new DirectoryEntry(johnSmithDN,\r
+ LDAPServerUsername,\r
+ LDAPServerPassword,\r
+ AuthenticationTypes.ServerBind);\r
+\r
+ DirectoryEntry johnSmithDE = new DirectoryEntry(johnSmithDN,\r
+ LDAPServerUsername,\r
+ LDAPServerPassword,\r
+ AuthenticationTypes.ServerBind);\r
+\r
+ johnSmithDE.Properties["telephoneNumber"].Value = "+972 3 9999999";\r
+\r
+ // check that the second entry is not accessible after the first is deleted\r
+ de.DeleteTree();\r
+ de.CommitChanges();\r
+\r
+ try {\r
+ johnSmithDE.CommitChanges(); \r
+ Assert.Fail("Object " + johnSmithDN + " should not be accessible");\r
+ }\r
+ catch(AssertionException ae) {\r
+ throw ae;\r
+ }\r
catch(Exception e) {\r
// do nothing\r
}\r
\r
de.RefreshCache();\r
\r
- Assert.AreEqual(((PropertyValueCollection)de.Properties["description"]).Value,oldValue); \r
+ Assert.AreEqual(((PropertyValueCollection)de.Properties["description"]).Value,oldValue);\r
+ \r
+ // call RefeshCache on new entry prior to submitting it to the server shoud fail\r
+ string newEmployeeDN = LDAPServerRoot + "cn=New Employee,ou=Human Resources,ou=people,dc=myhosting,dc=example";\r
+ string humanResourcesDN = LDAPServerRoot + "ou=Human Resources,ou=people,dc=myhosting,dc=example";\r
+\r
+ DirectoryEntry humanResourcesDE = new DirectoryEntry( humanResourcesDN,\r
+ LDAPServerUsername,\r
+ LDAPServerPassword,\r
+ AuthenticationTypes.ServerBind);\r
+\r
+ DirectoryEntry newEmployeeDE = humanResourcesDE.Children.Add("cn=New Employee","Class");\r
+ Assert.AreEqual(newEmployeeDE.Properties["cn"].Value,null);\r
+\r
+ ((PropertyValueCollection)newEmployeeDE.Properties["objectClass"]).Add("person");\r
+ ((PropertyValueCollection)newEmployeeDE.Properties["objectClass"]).Add("organizationalPerson");\r
+ newEmployeeDE.Properties["cn"].Value = "New Employee";\r
+ newEmployeeDE.Properties["sn"].Value = "Employee";\r
+ newEmployeeDE.Properties["ou"].Value = "Human Resources";\r
+\r
+ Assert.AreEqual(newEmployeeDE.Properties["cn"].Value,"New Employee");\r
+\r
+ try {\r
+ newEmployeeDE.RefreshCache();\r
+ Assert.Fail("Call to RefreshCache did not fail");\r
+ }\r
+ catch(AssertionException ae) {\r
+ throw ae;\r
+ }\r
+ catch (Exception e) {\r
+ // supress exception\r
+ }\r
+\r
+ Assert.AreEqual(newEmployeeDE.Properties["cn"].Value,"New Employee");\r
+\r
+ newEmployeeDE.CommitChanges();\r
+\r
+ // now it should work without any problem\r
+ newEmployeeDE.RefreshCache();\r
+\r
+ Assert.AreEqual(newEmployeeDE.Properties["cn"].Value,"New Employee");\r
}\r
\r
[Test]\r
+2005-04-07 Lluis Sanchez Gual <lluis@novell.com>
+
+ * System.Web.dll.sources: Added new files:
+ System.Web.UI.WebControls/ObjectDataSourceFilteringEventArgs.cs
+ System.Web.UI.WebControls/ObjectDataSourceFilteringEventHandler.cs
+
2005-04-01 Lluis Sanchez Gual <lluis@novell.com>
* System.Web.dll.sources: Added new files:
internal AutoGeneratedField (AutoGeneratedFieldProperties fieldProperties)
{
DataField = fieldProperties.DataField;
+ SortExpression = fieldProperties.DataField;
DataType = fieldProperties.Type;
HeaderText = fieldProperties.Name;
ReadOnly = fieldProperties.IsReadOnly;
}
set {
ViewState ["ReadOnly"] = value;
+ OnFieldChanged ();
}
}
}
set {
ViewState ["HtmlEncode"] = true;
+ OnFieldChanged ();
}
}
if (DataField == ThisExpression)
return controlContainer.ToString ();
else {
- IDataItemContainer dic = controlContainer as IDataItemContainer;
+ IDataItemContainer dic = (IDataItemContainer) controlContainer;
if (boundProperty == null) {
- ICustomTypeDescriptor desc = dic.DataItem as ICustomTypeDescriptor;
- if (desc != null) {
- boundProperty = desc.GetProperties () [DataField];
- if (boundProperty != null)
- return boundProperty.GetValue (dic.DataItem);
- } else {
- PropertyInfo pi = dic.DataItem.GetType ().GetProperty (DataField);
- if (pi != null)
- return pi.GetValue (dic.DataItem, null);
- }
- throw new InvalidOperationException ("Property '" + DataField + "' not found in data bound item");
+ boundProperty = TypeDescriptor.GetProperties (dic.DataItem) [DataField];
+ if (boundProperty == null)
+ new InvalidOperationException ("Property '" + DataField + "' not found in object of type " + dic.DataItem.GetType());
}
return boundProperty.GetValue (dic.DataItem);
}
DataControlFieldCell cell = (DataControlFieldCell) sender;
if (cell.Controls.Count > 0) {
TextBox box = cell.Controls [0] as TextBox;
- box.Text = FormatDataValue (GetValue (cell.BindingContainer), SupportsHtmlEncode && HtmlEncode);
+ object val = GetValue (cell.BindingContainer);
+ box.Text = val != null ? val.ToString() : "";
}
else
cell.Text = FormatDataValue (GetValue (cell.BindingContainer), SupportsHtmlEncode && HtmlEncode);
[WebCategoryAttribute ("Data")]\r
[DefaultValueAttribute ("")]\r
+ [TypeConverterAttribute ("System.Web.UI.Design.DataSourceViewSchemaConverter, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
public virtual string DataTextField {
get {
object ob = ViewState ["DataTextField"];
base.InitializeCell (cell, cellType, rowState, rowIndex);
}
- protected virtual void OnDataBindField (object sender, EventArgs e)
+ void OnDataBindField (object sender, EventArgs e)
{
DataControlFieldCell cell = (DataControlFieldCell) sender;
DataControlButton btn = (DataControlButton) cell.Controls [0];
{
IDataItemContainer dic = controlContainer as IDataItemContainer;
if (boundProperty == null) {
- ICustomTypeDescriptor desc = dic.DataItem as ICustomTypeDescriptor;
- if (desc != null) {
- boundProperty = desc.GetProperties () [DataTextField];
- if (boundProperty != null)
- return boundProperty.GetValue (dic.DataItem);
- } else {
- PropertyInfo pi = dic.DataItem.GetType ().GetProperty (DataTextField);
- if (pi != null)
- return pi.GetValue (dic.DataItem, null);
- }
- throw new InvalidOperationException ("Property '" + DataTextField + "' not found in data bound item");
+ boundProperty = TypeDescriptor.GetProperties (dic.DataItem) [DataTextField];
+ if (boundProperty == null)
+ new InvalidOperationException ("Property '" + DataTextField + "' not found in object of type " + dic.DataItem.GetType());
}
return boundProperty.GetValue (dic.DataItem);
}
+2005-04-07 Lluis Sanchez Gual <lluis@novell.com>
+
+ * ButtonField.cs: Get data item properties using TypeDescriptor.
+ Made OnDataBindField private.
+ * ObjectDataSourceView.cs: Implemented support for Delete and
+ Insert operations, support for filtering and sorting,
+ conflict detection, etc. It's now complete.
+ * ObjectDataSource.cs: Completed most of functionality. Only
+ caching support is missing.
+ * ObjectDataSourceFilteringEventHandler.cs: New event handler.
+ * TreeNode.cs: Get data item properties using TypeDescriptor.
+ * PagerSettings.cs: Flush.
+ * ObjectDataSourceFilteringEventArgs.cs: New event args.
+ * GridView.cs: Get data item properties using TypeDescriptor
+ and cache them. Properly set descending order in the sort
+ expression. In UpdateRow, make sure we get the old values
+ before the control is bound again.
+ * ImageField.cs: Implemented.
+ * AutoGeneratedField.cs: Initialize the field's sort
+ expression in the constructor.
+ * MenuItem.cs: Get data item properties using TypeDescriptor.
+ * BoundField.cs: Get data item properties using TypeDescriptor.
+ * CheckBoxField.cs: Added missing attributes.
+ * TemplateField.cs: Implemented.
+
2005-04-07 Gonzalo Paniagua Javier <gonzalo@ximian.com>
* UnitConverter.cs:
[AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public class CheckBoxField : BoundField
{
+ [EditorBrowsableAttribute (EditorBrowsableState.Never)]\r
+ [BrowsableAttribute (false)]\r
+ [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]\r
public override bool ConvertEmptyStringToNull {
get { throw GetNotSupportedPropException ("ConvertEmptyStringToNull"); }
set { throw GetNotSupportedPropException ("ConvertEmptyStringToNull"); }
}
+ [EditorBrowsableAttribute (EditorBrowsableState.Never)]\r
+ [BrowsableAttribute (false)]\r
+ [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]\r
public override string DataFormatString {
get { throw GetNotSupportedPropException ("DataFormatString"); }
set { throw GetNotSupportedPropException ("DataFormatString"); }
}
+ [EditorBrowsableAttribute (EditorBrowsableState.Never)]\r
+ [BrowsableAttribute (false)]\r
+ [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]\r
public override bool HtmlEncode {
get { throw GetNotSupportedPropException ("HtmlEncode"); }
set { throw GetNotSupportedPropException ("HtmlEncode"); }
}
+ [EditorBrowsableAttribute (EditorBrowsableState.Never)]\r
+ [BrowsableAttribute (false)]\r
+ [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]\r
public override string NullDisplayText {
get { throw GetNotSupportedPropException ("NullDisplayText"); }
set { throw GetNotSupportedPropException ("NullDisplayText"); }
ITemplate pagerTemplate;
ITemplate emptyDataTemplate;
+
+ PropertyDescriptor[] cachedKeyProperties;
// View state
DataControlFieldCollection columns;
if (retVal.Count > 0)
return (AutoGeneratedFieldProperties[]) retVal.ToArray (typeof(AutoGeneratedFieldProperties));
-
- throw new HttpException(HttpRuntime.FormatResourceString("DataGrid_NoAutoGenColumns", ID));
+ else
+ return new AutoGeneratedFieldProperties [0];
}
protected virtual GridViewRow CreateRow (int rowIndex, int dataSourceIndex, DataControlRowType rowType, DataControlRowState rowState)
DataControlField[] fields = new DataControlField [fieldCollection.Count];
fieldCollection.CopyTo (fields, 0);
- foreach (DataControlField field in fields)
+ foreach (DataControlField field in fields) {
field.Initialize (AllowSorting, this);
+ if (EnableSortingAndPagingCallbacks)
+ field.ValidateSupportsCallback ();
+ }
// Main table creation
IOrderedDictionary CreateRowDataKey (GridViewRow row)
{
- OrderedDictionary dic = new OrderedDictionary ();
- ICustomTypeDescriptor desc = row.DataItem as ICustomTypeDescriptor;
- if (desc != null && DataKeyNames != null) {
- PropertyDescriptorCollection props = desc.GetProperties ();
- foreach (string key in DataKeyNames) {
- PropertyDescriptor prop = props [key];
- dic [key] = prop.GetValue (row.DataItem);
+ if (cachedKeyProperties == null) {
+ PropertyDescriptorCollection props = TypeDescriptor.GetProperties (row.DataItem);
+ cachedKeyProperties = new PropertyDescriptor [DataKeyNames.Length];
+ for (int n=0; n<DataKeyNames.Length; n++) {
+ PropertyDescriptor p = props [DataKeyNames[n]];
+ if (p == null)
+ new InvalidOperationException ("Property '" + DataKeyNames[n] + "' not found in object of type " + row.DataItem.GetType());
+ cachedKeyProperties [n] = p;
}
}
+
+ OrderedDictionary dic = new OrderedDictionary ();
+ foreach (PropertyDescriptor p in cachedKeyProperties)
+ dic [p.Name] = p.GetValue (row.DataItem);
return dic;
}
SelectArguments.RetrieveTotalRowCount = true;
}
- if (sortExpression != "")
- SelectArguments.SortExpression = sortExpression;
-
+ if (sortExpression != "") {
+ if (sortDirection == SortDirection.Ascending)
+ SelectArguments.SortExpression = sortExpression;
+ else
+ SelectArguments.SortExpression = sortExpression + " DESC";
+ }
+
+ cachedKeyProperties = null;
base.DataBind ();
}
if (PageIndex > 0) newIndex = PageIndex - 1;
break;
default:
- newIndex = int.Parse (param);
+ newIndex = int.Parse (param) - 1;
break;
}
ShowPage (newIndex);
public void Sort (string newSortExpression, SortDirection newSortDirection)
{
- SortDirection newDirection;
- if (sortExpression == newSortExpression) {
- if (sortDirection == SortDirection.Ascending)
- newDirection = SortDirection.Descending;
- else
- newDirection = SortDirection.Ascending;
- } else
- newDirection = sortDirection;
-
- GridViewSortEventArgs args = new GridViewSortEventArgs (newSortExpression, newDirection);
+ GridViewSortEventArgs args = new GridViewSortEventArgs (newSortExpression, newSortDirection);
OnSorting (args);
if (args.Cancel) return;
if (rowIndex != EditIndex) throw new NotSupportedException ();
+ currentEditOldValues = oldEditValues.Values;
+
GridViewRow row = Rows [rowIndex];
currentEditRowKeys = DataKeys [rowIndex].Values;
- currentEditNewValues = GetRowValues (row, false, true);
- currentEditOldValues = oldEditValues.Values;
+ currentEditNewValues = GetRowValues (row, false, false);
GridViewUpdateEventArgs args = new GridViewUpdateEventArgs (EditIndex, currentEditRowKeys, currentEditOldValues, currentEditNewValues);
OnRowUpdating (args);
OnRowDeleting (args);
if (!args.Cancel) {
+ RequireBinding ();
DataSourceView view = GetData ();
if (view != null)
view.Delete (currentEditRowKeys, currentEditNewValues, new DataSourceViewOperationCallback (DeleteCallback));
// System.Web.UI.WebControls.ImageField.cs
//
// Authors:
-// Lluis Sanchez Gual (lluis@novell.com)
+// Lluis Sanchez Gual (lluis@novell.com)
//
-// (C) 2005 Novell, Inc. (http://www.novell.com)
+// (C) 2005 Novell, Inc (http://www.novell.com)
//
//
//
#if NET_2_0
+using System.Collections;
+using System.Collections.Specialized;
using System.Web.UI;
+using System.ComponentModel;
+using System.Security.Permissions;
+using System.Reflection;
-namespace System.Web.UI.WebControls
-{
+namespace System.Web.UI.WebControls {
+
+ [AspNetHostingPermissionAttribute (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
+ [AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public class ImageField : DataControlField
{
+ public static readonly string ThisExpression = "!";
+
+ PropertyDescriptor imageProperty;
+ PropertyDescriptor textProperty;
+
+ public override bool Initialize (bool sortingEnabled, Control control)
+ {
+ return base.Initialize (sortingEnabled, control);
+ }
+
+ [DefaultValueAttribute ("")]\r
+ [WebCategoryAttribute ("Appearance")]\r
+ [LocalizableAttribute (true)]\r
+ public virtual string AlternateText {
+ get {
+ object ob = ViewState ["AlternateText"];
+ if (ob != null) return (string) ob;
+ return string.Empty;
+ }
+ set {
+ ViewState ["AlternateText"] = value;
+ OnFieldChanged ();
+ }
+ }
+
+ [DefaultValueAttribute (true)]
+ [WebCategoryAttribute ("Behavior")]
+ public virtual bool ConvertEmptyStringToNull {
+ get {
+ object ob = ViewState ["ConvertEmptyStringToNull"];
+ if (ob != null) return (bool) ob;
+ return true;
+ }
+ set {
+ ViewState ["ConvertEmptyStringToNull"] = value;
+ OnFieldChanged ();
+ }
+ }
+
+ [TypeConverterAttribute ("System.Web.UI.Design.DataSourceViewSchemaConverter, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
+ [WebCategoryAttribute ("Data")]
+ [DefaultValueAttribute ("")]
+ public virtual string DataAlternateTextField {
+ get {
+ object ob = ViewState ["DataAlternateTextField"];
+ if (ob != null) return (string) ob;
+ return "";
+ }
+ set {
+ ViewState ["DataAlternateTextField"] = value;
+ OnFieldChanged ();
+ }
+ }
+
+ [WebCategoryAttribute ("Data")]
+ [DefaultValueAttribute ("")]
+ public virtual string DataAlternateTextFormatString {
+ get {
+ object ob = ViewState ["DataAlternateTextFormatString"];
+ if (ob != null) return (string) ob;
+ return "";
+ }
+ set {
+ ViewState ["DataAlternateTextFormatString"] = value;
+ OnFieldChanged ();
+ }
+ }
+
+ [TypeConverterAttribute ("System.Web.UI.Design.DataSourceViewSchemaConverter, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
+ [WebCategoryAttribute ("Data")]
+ [DefaultValueAttribute ("")]
+ public virtual string DataImageUrlField {
+ get {
+ object ob = ViewState ["DataImageUrlField"];
+ if (ob != null) return (string) ob;
+ return "";
+ }
+ set {
+ ViewState ["DataImageUrlField"] = value;
+ OnFieldChanged ();
+ }
+ }
+
+ [WebCategoryAttribute ("Data")]
+ [DefaultValueAttribute ("")]
+ public virtual string DataImageUrlFormatString {
+ get {
+ object ob = ViewState ["DataImageUrlFormatString"];
+ if (ob != null) return (string) ob;
+ return "";
+ }
+ set {
+ ViewState ["DataImageUrlFormatString"] = value;
+ OnFieldChanged ();
+ }
+ }
+
+ [DefaultValueAttribute ("")]
+ [WebCategoryAttribute ("Behavior")]
+ [LocalizableAttribute (true)]\r
+ public virtual string NullDisplayText {
+ get {
+ object ob = ViewState ["NullDisplayText"];
+ if (ob != null) return (string) ob;
+ return "";
+ }
+ set {
+ ViewState ["NullDisplayText"] = value;
+ OnFieldChanged ();
+ }
+ }
+
+ [DefaultValueAttribute ("")]\r
+ [EditorAttribute ("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]\r
+ [UrlPropertyAttribute]\r
+ [WebCategoryAttribute ("Behavior")]\r
+ public virtual string NullImageUrl {
+ get {
+ object ob = ViewState ["NullImageUrl"];
+ if (ob != null) return (string) ob;
+ return "";
+ }
+ set {
+ ViewState ["NullImageUrl"] = value;
+ OnFieldChanged ();
+ }
+ }
+
+ [WebCategoryAttribute ("Behavior")]
+ [DefaultValueAttribute (false)]
+ public bool ReadOnly {
+ get {
+ object val = ViewState ["ReadOnly"];
+ return val != null ? (bool) val : false;
+ }
+ set {
+ ViewState ["ReadOnly"] = value;
+ OnFieldChanged ();
+ }
+ }
+
+ public override void ExtractValuesFromCell (IOrderedDictionary dictionary,
+ DataControlFieldCell cell, DataControlRowState rowState, bool includeReadOnly)
+ {
+ if ((ReadOnly && !includeReadOnly) || cell.Controls.Count == 0) return;
+
+ if ((rowState & DataControlRowState.Edit) != 0 && !ReadOnly) {
+ TextBox box = cell.Controls [0] as TextBox;
+ dictionary [DataImageUrlField] = box.Text;
+ } else if (includeReadOnly) {
+ Image img = cell.Controls [0] as Image;
+ dictionary [DataImageUrlField] = img.ImageUrl;
+ }
+ }
+
+ public override void InitializeCell (DataControlFieldCell cell,
+ DataControlCellType cellType, DataControlRowState rowState, int rowIndex)
+ {
+ base.InitializeCell (cell, cellType, rowState, rowIndex);
+ if (cellType == DataControlCellType.DataCell)
+ InitializeDataCell (cell, rowState);
+ cell.DataBinding += new EventHandler (OnDataBindField);
+ }
+
+ public virtual void InitializeDataCell (DataControlFieldCell cell, DataControlRowState rowState)
+ {
+ if ((rowState & DataControlRowState.Edit) != 0 && !ReadOnly) {
+ TextBox box = new TextBox ();
+ cell.Controls.Add (box);
+ } else {
+ Image img = new Image ();
+ cell.Controls.Add (img);
+ }
+ }
+
+ protected virtual string FormatImageUrlValue (object value)
+ {
+ if (value == null || (value.ToString().Length == 0 && ConvertEmptyStringToNull))
+ return NullImageUrl;
+ else if (DataImageUrlFormatString.Length > 0)
+ return string.Format (DataImageUrlFormatString, value);
+ else
+ return value.ToString ();
+ }
+
+ protected virtual string GetFormattedAlternateText (Control controlContainer)
+ {
+ if (DataAlternateTextField.Length > 0)
+ {
+ if (textProperty == null)
+ textProperty = GetProperty (controlContainer, DataAlternateTextField);
+
+ object value = GetValue (controlContainer, DataAlternateTextField, textProperty);
+
+ if (value == null || (value.ToString().Length == 0 && ConvertEmptyStringToNull))
+ return NullDisplayText;
+ else if (DataAlternateTextFormatString.Length > 0)
+ return string.Format (DataAlternateTextFormatString, value);
+ else
+ return value.ToString ();
+ }
+ else
+ return AlternateText;
+
+ }
+
+ protected virtual object GetValue (Control controlContainer, string fieldName, PropertyDescriptor cachedDescriptor)
+ {
+ if (DesignMode)
+ return GetDesignTimeValue ();
+ else {
+ if (fieldName == ThisExpression)
+ return controlContainer.ToString ();
+ else {
+ IDataItemContainer dic = (IDataItemContainer) controlContainer;
+ if (cachedDescriptor != null) return cachedDescriptor.GetValue (dic.DataItem);
+ PropertyDescriptor prop = GetProperty (controlContainer, fieldName);
+ return prop.GetValue (dic.DataItem);
+ }
+ }
+ }
+
+ PropertyDescriptor GetProperty (Control controlContainer, string fieldName)
+ {
+ IDataItemContainer dic = (IDataItemContainer) controlContainer;
+ PropertyDescriptor prop = TypeDescriptor.GetProperties (dic.DataItem) [fieldName];
+ if (prop == null)
+ new InvalidOperationException ("Property '" + fieldName + "' not found in object of type " + dic.DataItem.GetType());
+ return prop;
+ }
+
+ protected virtual string GetDesignTimeValue ()
+ {
+ return "Databound";
+ }
+
+ protected virtual void OnDataBindField (object sender, EventArgs e)
+ {
+ DataControlFieldCell cell = (DataControlFieldCell) sender;
+
+ if (imageProperty == null)
+ imageProperty = GetProperty (cell.BindingContainer, DataImageUrlField);
+
+ Control c = cell.Controls [0];
+ if (c is TextBox) {
+ object val = GetValue (cell.BindingContainer, DataImageUrlField, imageProperty);
+ ((TextBox)c).Text = val != null ? val.ToString() : "";
+ }
+ else if (c is Image) {
+ Image img = (Image)c;
+ img.ImageUrl = FormatImageUrlValue (GetValue (cell.BindingContainer, DataImageUrlField, imageProperty));
+ img.AlternateText = GetFormattedAlternateText (cell.BindingContainer);
+ }
+ }
+
+ public override void ValidateSupportsCallback ()
+ {
+ }
}
}
#endif
object GetBoundPropertyValue (string name)
{
- if (boundProperties == null) {
- ICustomTypeDescriptor desc = hierarchyData as ICustomTypeDescriptor;
- if (desc == null)
- throw new InvalidOperationException ("Property '" + name + "' not found in data bound item");
- boundProperties = desc.GetProperties ();
- }
+ if (boundProperties == null)
+ boundProperties = TypeDescriptor.GetProperties (hierarchyData);
PropertyDescriptor prop = boundProperties.Find (name, true);
if (prop == null)
}
}
+ public event ObjectDataSourceStatusEventHandler Deleted {
+ add { DefaultView.Deleted += value; }
+ remove { DefaultView.Deleted -= value; }
+ }
+
+ public event ObjectDataSourceMethodEventHandler Deleting {
+ add { DefaultView.Deleting += value; }
+ remove { DefaultView.Deleting -= value; }
+ }
+
+ public event ObjectDataSourceFilteringEventHandler Filtering {
+ add { DefaultView.Filtering += value; }
+ remove { DefaultView.Filtering -= value; }
+ }
+
+ public event ObjectDataSourceStatusEventHandler Inserted {
+ add { DefaultView.Inserted += value; }
+ remove { DefaultView.Inserted -= value; }
+ }
+
+ public event ObjectDataSourceMethodEventHandler Inserting {
+ add { DefaultView.Inserting += value; }
+ remove { DefaultView.Inserting -= value; }
+ }
+
public event ObjectDataSourceObjectEventHandler ObjectCreated {
add { DefaultView.ObjectCreated += value; }
remove { DefaultView.ObjectCreated -= value; }
remove { DefaultView.Updating -= value; }
}
+ [WebCategoryAttribute ("Data")]\r
+ [DefaultValueAttribute (ConflictOptions.OverwriteChanges)]\r
+ public ConflictOptions ConflictDetection {
+ get { return DefaultView.ConflictDetection; }
+ set { DefaultView.ConflictDetection = value; }
+ }
+
+ [WebCategoryAttribute ("Data")]\r
+ [DefaultValueAttribute ("")]\r
+ public string DataObjectTypeName {
+ get { return DefaultView.DataObjectTypeName; }
+ set { DefaultView.DataObjectTypeName = value; }
+ }
+
+ [WebCategoryAttribute ("Data")]\r
+ [DefaultValueAttribute ("")]\r
+ public string DeleteMethod {
+ get { return DefaultView.DeleteMethod; }
+ set { DefaultView.DeleteMethod = value; }
+ }
+
+ [WebCategoryAttribute ("Data")]\r
+ [MergablePropertyAttribute (false)]\r
+ [EditorAttribute ("System.Web.UI.Design.WebControls.ParameterCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]\r
+ [DefaultValueAttribute (null)]\r
+ [PersistenceModeAttribute (PersistenceMode.InnerProperty)]\r
+ public ParameterCollection DeleteParameters {
+ get { return DefaultView.DeleteParameters; }
+ }
+
[WebCategoryAttribute ("Paging")]\r
[DefaultValueAttribute (false)]\r
public virtual bool EnablePaging {
set { DefaultView.EnablePaging = value; }
}
+ [WebCategoryAttribute ("Data")]\r
+ [DefaultValueAttribute ("")]\r
+ public string FilterExpression {
+ get { return DefaultView.FilterExpression; }
+ set { DefaultView.FilterExpression = value; }
+ }
+
+ [WebCategoryAttribute ("Data")]\r
+ [MergablePropertyAttribute (false)]\r
+ [EditorAttribute ("System.Web.UI.Design.WebControls.ParameterCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]\r
+ [DefaultValueAttribute (null)]\r
+ [PersistenceModeAttribute (PersistenceMode.InnerProperty)]\r
+ public ParameterCollection FilterParameters {
+ get { return DefaultView.FilterParameters; }
+ }
+
+ [DefaultValueAttribute ("")]\r
+ [WebCategoryAttribute ("Data")]\r
+ public virtual string InsertMethod {
+ get { return DefaultView.InsertMethod; }
+ set { DefaultView.InsertMethod = value; }
+ }
+
+ [WebCategoryAttribute ("Data")]\r
+ [MergablePropertyAttribute (false)]\r
+ [EditorAttribute ("System.Web.UI.Design.WebControls.ParameterCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]\r
+ [DefaultValueAttribute (null)]\r
+ [PersistenceModeAttribute (PersistenceMode.InnerProperty)]\r
+ public ParameterCollection InsertParameters {
+ get { return DefaultView.InsertParameters; }
+ }
+
[WebCategoryAttribute ("Paging")]\r
[DefaultValueAttribute ("maximumRows")]\r
public string MaximumRowsParameterName {
get { return DefaultView.MaximumRowsParameterName; }
set { DefaultView.MaximumRowsParameterName = value; }
}
+
+ [WebCategoryAttribute ("Data")]\r
+ [DefaultValueAttribute ("original_{0}")]\r
+ public string OldValuesParameterFormatString {
+ get { return DefaultView.OldValuesParameterFormatString; }
+ set { DefaultView.OldValuesParameterFormatString = value; }
+ }
[WebCategoryAttribute ("Paging")]\r
[DefaultValueAttribute ("")]\r
get { return DefaultView.SelectParameters; }
}
+ [DefaultValueAttribute ("")]\r
+ [WebCategoryAttribute ("Data")]\r
+ public string SortParameterName {
+ get { return DefaultView.SortParameterName; }
+ set { DefaultView.SortParameterName = value; }
+ }
+
[WebCategoryAttribute ("Paging")]\r
[DefaultValueAttribute ("startRowIndex")]\r
public string StartRowIndexParameterName {
return DefaultView.Select (DataSourceSelectArguments.Empty);
}
+ public int Update ()
+ {
+ Hashtable empty = new Hashtable ();
+ return DefaultView.Update (empty, empty, null);
+ }
+
+ public int Delete ()
+ {
+ Hashtable empty = new Hashtable ();
+ return DefaultView.Delete (empty, null);
+ }
+
+ public int Insert ()
+ {
+ Hashtable empty = new Hashtable ();
+ return DefaultView.Insert (empty);
+ }
+
protected override void LoadViewState (object savedState)
{
if (savedState == null) {
--- /dev/null
+//
+// System.Web.UI.WebControls.ObjectDataSourceFilteringEventArgs.cs
+//
+// Authors:
+// Lluis Sanchez Gual (lluis@novell.com)
+//
+// (C) 2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+
+using System.Collections;
+using System.Collections.Specialized;
+
+namespace System.Web.UI.WebControls
+{
+ public class ObjectDataSourceFilteringEventArgs : System.ComponentModel.CancelEventArgs
+ {
+ private IOrderedDictionary parameters;
+
+ public ObjectDataSourceFilteringEventArgs (IOrderedDictionary parameterValues)
+ {
+ this.parameters = parameterValues;
+ }
+
+ public IOrderedDictionary ParameterValues {
+ get { return parameters; }
+ }
+ }
+}
+
+#endif
--- /dev/null
+//
+// System.Web.UI.WebControls.ObjectDataSourceFilteringEventHandler.cs
+//
+// Authors:
+// Lluis Sanchez Gual (lluis@novell.com)
+//
+// (C) 2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+
+#if NET_2_0
+
+namespace System.Web.UI.WebControls
+{
+ public delegate void ObjectDataSourceFilteringEventHandler (object sender, ObjectDataSourceFilteringEventArgs e);
+}
+
+#endif
ObjectDataSource owner;
HttpContext context;
Type objectType;
+ Type dataObjectType;
StateBag viewState = new StateBag ();
ParameterCollection selectParameters;
ParameterCollection updateParameters;
-
+ ParameterCollection deleteParameters;
+ ParameterCollection insertParameters;
+ ParameterCollection filterParameters;
+
+ private static readonly object DeletedEvent = new object();
+ private static readonly object DeletingEvent = new object();
+ private static readonly object FilteringEvent = new object();
+ private static readonly object InsertedEvent = new object();
+ private static readonly object InsertingEvent = new object();
private static readonly object ObjectCreatedEvent = new object();
private static readonly object ObjectCreatingEvent = new object();
private static readonly object ObjectDisposingEvent = new object();
this.context = context;
}
+ public event ObjectDataSourceStatusEventHandler Deleted {
+ add { Events.AddHandler (DeletedEvent, value); }
+ remove { Events.RemoveHandler (DeletedEvent, value); }
+ }
+
+ public event ObjectDataSourceMethodEventHandler Deleting {
+ add { Events.AddHandler (DeletingEvent, value); }
+ remove { Events.RemoveHandler (DeletingEvent, value); }
+ }
+
+ public event ObjectDataSourceFilteringEventHandler Filtering {
+ add { Events.AddHandler (FilteringEvent, value); }
+ remove { Events.RemoveHandler (FilteringEvent, value); }
+ }
+
+ public event ObjectDataSourceStatusEventHandler Inserted {
+ add { Events.AddHandler (InsertedEvent, value); }
+ remove { Events.RemoveHandler (InsertedEvent, value); }
+ }
+
+ public event ObjectDataSourceMethodEventHandler Inserting {
+ add { Events.AddHandler (InsertingEvent, value); }
+ remove { Events.RemoveHandler (InsertingEvent, value); }
+ }
+
public event ObjectDataSourceObjectEventHandler ObjectCreated {
add { Events.AddHandler (ObjectCreatedEvent, value); }
remove { Events.RemoveHandler (ObjectCreatedEvent, value); }
remove { Events.RemoveHandler (UpdatingEvent, value); }
}
+ protected virtual void OnDeleted (ObjectDataSourceStatusEventArgs e)
+ {
+ if (Events != null) {
+ ObjectDataSourceStatusEventHandler eh = (ObjectDataSourceStatusEventHandler) Events [DeletedEvent];
+ if (eh != null) eh (this, e);
+ }
+ }
+
+ protected virtual void OnDeleting (ObjectDataSourceMethodEventArgs e)
+ {
+ if (Events != null) {
+ ObjectDataSourceMethodEventHandler eh = (ObjectDataSourceMethodEventHandler) Events [DeletingEvent];
+ if (eh != null) eh (this, e);
+ }
+ }
+
+ protected virtual void OnFiltering (ObjectDataSourceFilteringEventArgs e)
+ {
+ if (Events != null) {
+ ObjectDataSourceFilteringEventHandler eh = (ObjectDataSourceFilteringEventHandler) Events [FilteringEvent];
+ if (eh != null) eh (this, e);
+ }
+ }
+
+ protected virtual void OnInserted (ObjectDataSourceStatusEventArgs e)
+ {
+ if (Events != null) {
+ ObjectDataSourceStatusEventHandler eh = (ObjectDataSourceStatusEventHandler) Events [InsertedEvent];
+ if (eh != null) eh (this, e);
+ }
+ }
+
+ protected virtual void OnInserting (ObjectDataSourceMethodEventArgs e)
+ {
+ if (Events != null) {
+ ObjectDataSourceMethodEventHandler eh = (ObjectDataSourceMethodEventHandler) Events [InsertingEvent];
+ if (eh != null) eh (this, e);
+ }
+ }
+
protected virtual void OnObjectCreated (ObjectDataSourceEventArgs e)
{
if (Events != null) {
get { return viewState; }
}
+ public override bool CanDelete {
+ get { return DeleteMethod.Length > 0; }
+ }
+
+ public override bool CanInsert {
+ get { return InsertMethod.Length > 0; }
+ }
+
public override bool CanPage {
get { return EnablePaging; }
}
get { return SelectCountMethod.Length > 0; }
}
+ public override bool CanSort {
+ get { return true; }
+ }
+
public override bool CanUpdate {
get { return UpdateMethod.Length > 0; }
}
- public virtual bool EnablePaging {
+ public ConflictOptions ConflictDetection {
+ get {
+ object ret = ViewState ["ConflictDetection"];
+ return ret != null ? (ConflictOptions)ret : ConflictOptions.OverwriteChanges;
+ }
+ set {
+ ViewState ["ConflictDetection"] = value;
+ }
+ }
+
+ public bool ConvertNullToDBNull {
+ get {
+ object ret = ViewState ["ConvertNullToDBNull"];
+ return ret != null ? (bool)ret : false;
+ }
+ set {
+ ViewState ["ConvertNullToDBNull"] = value;
+ }
+ }
+
+ public string DataObjectTypeName {
+ get {
+ object ret = ViewState ["DataObjectTypeName"];
+ return ret != null ? (string)ret : string.Empty;
+ }
+ set {
+ ViewState ["DataObjectTypeName"] = value;
+ }
+ }
+
+ public string DeleteMethod {
+ get {
+ object ret = ViewState ["DeleteMethod"];
+ return ret != null ? (string)ret : string.Empty;
+ }
+ set {
+ ViewState ["DeleteMethod"] = value;
+ }
+ }
+
+ public ParameterCollection DeleteParameters {
+ get {
+ if (deleteParameters == null) {
+ deleteParameters = new ParameterCollection ();
+ if (((IStateManager)this).IsTrackingViewState)
+ ((IStateManager)deleteParameters).TrackViewState ();
+ }
+ return deleteParameters;
+ }
+ }
+
+ public bool EnablePaging {
get {
object ret = ViewState ["EnablePaging"];
return ret != null ? (bool)ret : false;
}
}
+ public string FilterExpression {
+ get {
+ object ret = ViewState ["FilterExpression"];
+ return ret != null ? (string)ret : string.Empty;
+ }
+ set {
+ ViewState ["FilterExpression"] = value;
+ }
+ }
+
+ public ParameterCollection FilterParameters {
+ get {
+ if (filterParameters == null) {
+ filterParameters = new ParameterCollection ();
+ if (IsTrackingViewState)
+ ((IStateManager)filterParameters).TrackViewState ();
+ }
+ return filterParameters;
+ }
+ }
+
+ public string InsertMethod {
+ get {
+ object ret = ViewState ["InsertMethod"];
+ return ret != null ? (string)ret : string.Empty;
+ }
+ set {
+ ViewState ["InsertMethod"] = value;
+ }
+ }
+
+ public ParameterCollection InsertParameters {
+ get {
+ if (insertParameters == null) {
+ insertParameters = new ParameterCollection ();
+ if (IsTrackingViewState)
+ ((IStateManager)insertParameters).TrackViewState ();
+ }
+ return insertParameters;
+ }
+ }
+
public string MaximumRowsParameterName {
get {
object ret = ViewState ["MaximumRowsParameterName"];
}
}
- public virtual string SelectCountMethod {
+ [DefaultValueAttribute ("original_{0}")]\r
+ public string OldValuesParameterFormatString {
+ get {
+ object ret = ViewState ["OldValuesParameterFormatString"];
+ return ret != null ? (string)ret : "original_{0}";
+ }
+ set {
+ ViewState ["OldValuesParameterFormatString"] = value;
+ }
+ }
+
+ public string SelectCountMethod {
get {
object ret = ViewState ["SelectCountMethod"];
return ret != null ? (string)ret : string.Empty;
}
}
- public virtual string SelectMethod {
+ public string SelectMethod {
get {
object ret = ViewState ["SelectMethod"];
return ret != null ? (string)ret : string.Empty;
}
}
+ public string SortParameterName {
+ get {
+ object ret = ViewState ["SortParameterName"];
+ return ret != null ? (string)ret : string.Empty;
+ }
+ set {
+ ViewState ["SortParameterName"] = value;
+ }
+ }
+
public string StartRowIndexParameterName {
get {
object ret = ViewState ["StartRowIndexParameterName"];
}
}
- public virtual string TypeName {
+ public string TypeName {
get {
object ret = ViewState ["TypeName"];
return ret != null ? (string)ret : string.Empty;
}
}
- public virtual string UpdateMethod {
+ public string UpdateMethod {
get {
object ret = ViewState ["UpdateMethod"];
return ret != null ? (string)ret : string.Empty;
}
}
+ Type DataObjectType {
+ get {
+ if (dataObjectType == null) {
+ dataObjectType = Type.GetType (DataObjectTypeName);
+ if (objectType == null)
+ throw new InvalidOperationException ("Type not found: " + DataObjectTypeName);
+ }
+ return dataObjectType;
+ }
+ }
+
public IEnumerable Select (DataSourceSelectArguments arguments)
{
return ExecuteSelect (arguments);
}
- protected override int ExecuteUpdate (IDictionary keys, IDictionary values, IDictionary oldValues)
+ public int Update (IDictionary keys, IDictionary values, IDictionary oldValues)
{
- Hashtable allValues = new Hashtable ();
- foreach (DictionaryEntry de in keys)
- allValues [de.Key] = de.Value;
- foreach (DictionaryEntry de in values)
- allValues [de.Key] = de.Value;
+ return ExecuteUpdate (keys, values, oldValues);
+ }
+
+ public int Delete (IDictionary keys, IDictionary oldValues)
+ {
+ return ExecuteDelete (keys, oldValues);
+ }
+
+ public int Insert (IDictionary values)
+ {
+ return ExecuteInsert (values);
+ }
+
+ protected override int ExecuteInsert (IDictionary values)
+ {
+ if (!CanInsert)
+ throw new NotSupportedException ("Insert operation not supported.");
+
+ IOrderedDictionary paramValues;
+ MethodInfo method;
+
+ if (DataObjectTypeName.Length == 0) {
+ paramValues = MergeParameterValues (InsertParameters, values, null, true);
+ method = GetObjectMethod (InsertMethod, paramValues);
+ } else {
+ method = ResolveDataObjectMethod (InsertMethod, values, null, out paramValues);
+ }
+
+ ObjectDataSourceMethodEventArgs args = new ObjectDataSourceMethodEventArgs (paramValues);
+ OnInserting (args);
+ if (args.Cancel)
+ return -1;
+
+ ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
+ OnInserted (rargs);
+
+ if (rargs.Exception != null && !rargs.ExceptionHandled)
+ throw rargs.Exception;
+
+ return -1;
+ }
- IOrderedDictionary paramValues = MergeParameterValues (UpdateParameters, allValues);
+ protected override int ExecuteDelete (IDictionary keys, IDictionary oldValues)
+ {
+ if (!CanDelete)
+ throw new NotSupportedException ("Delete operation not supported.");
+
+ if (ConflictDetection == ConflictOptions.CompareAllValues && (oldValues == null || oldValues.Count == 0))
+ throw new InvalidOperationException ("ConflictDetection is set to CompareAllValues and oldValues collection is null or empty.");
+
+ IDictionary oldDataValues;
+ if (ConflictDetection == ConflictOptions.CompareAllValues) {
+ oldDataValues = new Hashtable ();
+ foreach (DictionaryEntry de in keys)
+ oldDataValues [de.Key] = de.Value;
+ foreach (DictionaryEntry de in oldValues)
+ oldDataValues [de.Key] = de.Value;
+ } else
+ oldDataValues = keys;
+
+ IOrderedDictionary paramValues;
+ MethodInfo method;
+
+ if (DataObjectTypeName.Length == 0) {
+ paramValues = MergeParameterValues (DeleteParameters, null, oldDataValues, true);
+ method = GetObjectMethod (DeleteMethod, paramValues);
+ } else {
+ method = ResolveDataObjectMethod (DeleteMethod, oldDataValues, null, out paramValues);
+ }
+ ObjectDataSourceMethodEventArgs args = new ObjectDataSourceMethodEventArgs (paramValues);
+ OnDeleting (args);
+ if (args.Cancel)
+ return -1;
+
+ ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
+
+ OnDeleted (rargs);
+
+ if (rargs.Exception != null && !rargs.ExceptionHandled)
+ throw rargs.Exception;
+
+ return -1;
+ }
+
+ protected override int ExecuteUpdate (IDictionary keys, IDictionary values, IDictionary oldValues)
+ {
+ IOrderedDictionary paramValues;
+ MethodInfo method;
+
+ if (DataObjectTypeName.Length == 0)
+ {
+ IDictionary dataValues;
+ IDictionary oldDataValues;
+ if (ConflictDetection == ConflictOptions.CompareAllValues) {
+ oldDataValues = new Hashtable ();
+ dataValues = values;
+ foreach (DictionaryEntry de in keys)
+ oldDataValues [de.Key] = de.Value;
+ foreach (DictionaryEntry de in oldValues)
+ oldDataValues [de.Key] = de.Value;
+ } else {
+ oldDataValues = keys;
+ dataValues = values;
+ }
+ paramValues = MergeParameterValues (UpdateParameters, dataValues, oldDataValues, false);
+ method = GetObjectMethod (UpdateMethod, paramValues);
+ }
+ else
+ {
+ IDictionary dataValues = new Hashtable ();
+ IDictionary oldDataValues;
+
+ foreach (DictionaryEntry de in values)
+ dataValues [de.Key] = de.Value;
+
+ if (ConflictDetection == ConflictOptions.CompareAllValues) {
+ oldDataValues = new Hashtable ();
+ foreach (DictionaryEntry de in keys) {
+ oldDataValues [de.Key] = de.Value;
+ dataValues [de.Key] = de.Value;
+ }
+ foreach (DictionaryEntry de in oldValues)
+ oldDataValues [de.Key] = de.Value;
+ } else {
+ oldDataValues = null;
+ foreach (DictionaryEntry de in keys)
+ dataValues [de.Key] = de.Value;
+ }
+ method = ResolveDataObjectMethod (UpdateMethod, dataValues, oldDataValues, out paramValues);
+ }
+
ObjectDataSourceMethodEventArgs args = new ObjectDataSourceMethodEventArgs (paramValues);
OnUpdating (args);
if (args.Cancel)
return -1;
- ObjectDataSourceStatusEventArgs rargs = InvokeMethod (UpdateMethod, paramValues);
+ ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
OnUpdated (rargs);
if (rargs.Exception != null && !rargs.ExceptionHandled)
{
arguments.RaiseUnsupportedCapabilitiesError (this);
- IOrderedDictionary paramValues = MergeParameterValues (SelectParameters, null);
-
+ IOrderedDictionary paramValues = MergeParameterValues (SelectParameters, null, null, true);
ObjectDataSourceSelectingEventArgs args = new ObjectDataSourceSelectingEventArgs (paramValues, arguments, false);
OnSelecting (args);
if (args.Cancel)
paramValues [MaximumRowsParameterName] = arguments.MaximumRows;
}
+ if (SortParameterName.Length > 0)
+ paramValues [SortParameterName] = arguments.SortExpression;
+
object result = InvokeSelect (SelectMethod, paramValues);
if (result is DataSet) {
if (result is DataTable) {
DataView dview = new DataView ((DataTable)result);
+ if (arguments.SortExpression != null && arguments.SortExpression.Length > 0) {
+ dview.Sort = arguments.SortExpression;
+ }
+ if (FilterExpression.Length > 0) {
+ OrderedDictionary fparams = new OrderedDictionary ();
+ foreach (Parameter p in FilterParameters)
+ fparams.Add (p.Name, p.GetValue (context, owner));
+
+ ObjectDataSourceFilteringEventArgs fargs = new ObjectDataSourceFilteringEventArgs (fparams);
+ OnFiltering (fargs);
+ if (!fargs.Cancel) {
+ object[] formatValues = new object[fargs.ParameterValues.Count];
+ for (int n=0; n<formatValues.Length; n++)
+ formatValues [n] = fargs.ParameterValues [n];
+ dview.RowFilter = string.Format (FilterExpression, formatValues);
+ }
+ }
return dview;
}
object InvokeSelect (string methodName, IOrderedDictionary paramValues)
{
- ObjectDataSourceStatusEventArgs rargs = InvokeMethod (methodName, paramValues);
+ MethodInfo method = GetObjectMethod (methodName, paramValues);
+ ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
OnSelected (rargs);
if (rargs.Exception != null && !rargs.ExceptionHandled)
return rargs.ReturnValue;
}
- ObjectDataSourceStatusEventArgs InvokeMethod (string methodName, IOrderedDictionary paramValues)
+ ObjectDataSourceStatusEventArgs InvokeMethod (MethodInfo method, IOrderedDictionary paramValues)
{
object instance = null;
- MethodInfo method = GetObjectMethod (methodName, paramValues);
+
if (!method.IsStatic)
instance = CreateObjectInstance ();
object[] methodArgs = GetParameterArray (pars, paramValues, out outParamInfos);
if (methodArgs == null)
- throw CreateMethodException (methodName, paramValues);
+ throw CreateMethodException (method.Name, paramValues);
object result = null;
Hashtable outParams = null;
throw CreateMethodException (methodName, parameters);
}
+ MethodInfo ResolveDataObjectMethod (string methodName, IDictionary values, IDictionary oldValues, out IOrderedDictionary paramValues)
+ {
+ MethodInfo method;
+ if (oldValues != null)
+ method = ObjectType.GetMethod (methodName, new Type[] { DataObjectType, DataObjectType });
+ else
+ method = ObjectType.GetMethod (methodName, new Type[] { DataObjectType });
+
+ if (method == null)
+ throw new InvalidOperationException ("ObjectDataSource " + owner.ID + " could not find a method named '" + methodName + "' with parameters of type '" + DataObjectType + "' in '" + ObjectType + "'.");
+
+ paramValues = new OrderedDictionary ();
+ ParameterInfo[] ps = method.GetParameters ();
+
+ if (oldValues != null) {
+ if (FormatOldParameter (ps[0].Name) == ps[1].Name) {
+ paramValues [ps[0].Name] = CreateDataObject (values);
+ paramValues [ps[1].Name] = CreateDataObject (oldValues);
+ } else if (FormatOldParameter (ps[1].Name) == ps[0].Name) {
+ paramValues [ps[0].Name] = CreateDataObject (oldValues);
+ paramValues [ps[1].Name] = CreateDataObject (values);
+ } else
+ throw new InvalidOperationException ("Method '" + methodName + "' does not have any parameter that fits the value of OldValuesParameterFormatString.");
+ } else {
+ paramValues [ps[0].Name] = CreateDataObject (values);
+ }
+ return method;
+ }
+
Exception CreateMethodException (string methodName, IOrderedDictionary parameters)
{
string s = "";
return new InvalidOperationException ("ObjectDataSource " + owner.ID + " could not find a method named '" + methodName + "' with parameters " + s + "in type '" + ObjectType + "'.");
}
+ object CreateDataObject (IDictionary values)
+ {
+ object ob = Activator.CreateInstance (DataObjectType);
+ foreach (DictionaryEntry de in values) {
+ PropertyInfo p = DataObjectType.GetProperty ((string)de.Key);
+ if (p == null) throw new InvalidOperationException ("Property " + de.Key + " not found in type '" +DataObjectType + "'.");
+ p.SetValue (ob, ConvertParameter (p.PropertyType, de.Value), null);
+ }
+ return ob;
+ }
+
object CreateObjectInstance ()
{
ObjectDataSourceEventArgs args = new ObjectDataSourceEventArgs (null);
}
}
- IOrderedDictionary MergeParameterValues (ParameterCollection viewParams, IDictionary values)
+ IOrderedDictionary MergeParameterValues (ParameterCollection viewParams, IDictionary values, IDictionary oldValues, bool allwaysAddNewValues)
{
OrderedDictionary mergedValues = new OrderedDictionary ();
foreach (Parameter p in viewParams) {
- object val = values != null ? values [p.Name] : null;
- if (val != null)
- val = Convert.ChangeType (val, p.Type);
- else
- val = p.GetValue (context, owner);
+ bool oldAdded = false;
+ if (oldValues != null && oldValues.Contains (p.Name)) {
+ object val = Convert.ChangeType (oldValues [p.Name], p.Type);
+ mergedValues [FormatOldParameter (p.Name)] = val;
+ oldAdded = true;
+ }
- mergedValues [p.Name] = val;
+ if (values != null && values.Contains (p.Name)) {
+ object val = Convert.ChangeType (values [p.Name], p.Type);
+ mergedValues [p.Name] = val;
+ } else if (!oldAdded || allwaysAddNewValues) {
+ object val = p.GetValue (context, owner);
+ mergedValues [p.Name] = val;
+ }
}
if (values != null) {
mergedValues [de.Key] = de.Value;
}
+ if (oldValues != null) {
+ foreach (DictionaryEntry de in oldValues)
+ if (!mergedValues.Contains (FormatOldParameter ((string)de.Key)))
+ mergedValues [FormatOldParameter ((string)de.Key)] = de.Value;
+ }
+
return mergedValues;
}
object ConvertParameter (Type targetType, object value)
{
+ if (value == null) {
+ if (targetType.IsPrimitive)
+ value = 0;
+ else if (targetType == typeof(object) && ConvertNullToDBNull)
+ return DBNull.Value;
+ }
return Convert.ChangeType (value, targetType);
}
+ string FormatOldParameter (string name)
+ {
+ string f = OldValuesParameterFormatString;
+ if (f.Length > 0)
+ return String.Format (f, name);
+ else
+ return name;
+ }
+
protected virtual void LoadViewState (object savedState)
{
- object[] state = (savedState == null) ? new object [3] : (object[]) savedState;
+ object[] state = (savedState == null) ? new object [6] : (object[]) savedState;
viewState.LoadViewState (state[0]);
((IStateManager)SelectParameters).LoadViewState (state[1]);
- ((IStateManager)UpdateParameters).LoadViewState (state[1]);
+ ((IStateManager)UpdateParameters).LoadViewState (state[2]);
+ ((IStateManager)DeleteParameters).LoadViewState (state[3]);
+ ((IStateManager)InsertParameters).LoadViewState (state[4]);
+ ((IStateManager)FilterParameters).LoadViewState (state[5]);
}
protected virtual object SaveViewState()
{
- object[] state = new object [3];
+ object[] state = new object [6];
state [0] = viewState.SaveViewState ();
if (selectParameters != null)
state [1] = ((IStateManager)selectParameters).SaveViewState ();
if (updateParameters != null)
state [2] = ((IStateManager)updateParameters).SaveViewState ();
+ if (deleteParameters != null)
+ state [3] = ((IStateManager)deleteParameters).SaveViewState ();
+ if (insertParameters != null)
+ state [4] = ((IStateManager)insertParameters).SaveViewState ();
+ if (filterParameters != null)
+ state [5] = ((IStateManager)filterParameters).SaveViewState ();
foreach (object ob in state)
if (ob != null) return state;
viewState.TrackViewState ();
if (selectParameters != null) ((IStateManager)selectParameters).TrackViewState ();
if (updateParameters != null) ((IStateManager)updateParameters).TrackViewState ();
+ if (deleteParameters != null) ((IStateManager)deleteParameters).TrackViewState ();
+ if (insertParameters != null) ((IStateManager)insertParameters).TrackViewState ();
+ if (filterParameters != null) ((IStateManager)filterParameters).TrackViewState ();
}
- bool IStateManager.IsTrackingViewState
+ protected virtual bool IsTrackingViewState
{
get { return viewState.IsTrackingViewState; }
}
+
+ bool IStateManager.IsTrackingViewState
+ {
+ get { return IsTrackingViewState; }
+ }
+
void IStateManager.TrackViewState()
{
TrackViewState ();
{\r
int first = currentPage / PageButtonCount;\r
int last = first + PageButtonCount;\r
- if (last >= pageCount) last = pageCount - 1;\r
+ if (last >= pageCount) last = pageCount;\r
\r
if (first > 0) {\r
if (Mode == PagerButtons.NumericFirstLast)\r
}\r
\r
for (int n = first; n < last; n++)\r
- row.Cells.Add (CreateCell (n.ToString(), string.Empty, (n != currentPage) ? "Page" : "", n.ToString()));\r
+ row.Cells.Add (CreateCell ((n+1).ToString(), string.Empty, (n != currentPage) ? "Page" : "", (n+1).ToString()));\r
\r
if (last < pageCount - 1) {\r
row.Cells.Add (CreateCell (NextPageText, NextPageImageUrl, "Page", "Next"));\r
//
#if NET_2_0
+using System.Collections.Specialized;
using System.Web.UI;
+using System.Security.Permissions;
+using System.ComponentModel;
namespace System.Web.UI.WebControls
{
+ [AspNetHostingPermissionAttribute (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
+ [AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public class TemplateField : DataControlField
{
+ ITemplate alternatingItemTemplate;
+ ITemplate editItemTemplate;
+ ITemplate footerTemplate;
+ ITemplate headerTemplate;
+ ITemplate insertItemTemplate;
+ ITemplate itemTemplate;
+
+ [DefaultValue (null)]
+ [TemplateContainer (typeof(IDataItemContainer), BindingDirection.TwoWay)]
+ [PersistenceMode (PersistenceMode.InnerProperty)]
+ [Browsable (false)]
+ public ITemplate AlternatingItemTemplate {
+ get { return alternatingItemTemplate; }
+ set { alternatingItemTemplate = value; OnFieldChanged (); }
+ }
+
+ [DefaultValueAttribute (true)]
+ [WebCategoryAttribute ("Behavior")]
+ public virtual bool ConvertEmptyStringToNull {
+ get {
+ object ob = ViewState ["ConvertEmptyStringToNull"];
+ if (ob != null) return (bool) ob;
+ return true;
+ }
+ set {
+ ViewState ["ConvertEmptyStringToNull"] = value;
+ OnFieldChanged ();
+ }
+ }
+
+ [DefaultValue (null)]
+ [TemplateContainer (typeof(IDataItemContainer), BindingDirection.TwoWay)]
+ [PersistenceMode (PersistenceMode.InnerProperty)]
+ [Browsable (false)]
+ public ITemplate EditItemTemplate {
+ get { return editItemTemplate; }
+ set { editItemTemplate = value; OnFieldChanged (); }
+ }
+
+ [DefaultValue (null)]
+ [TemplateContainer (typeof(IDataItemContainer), BindingDirection.OneWay)]
+ [PersistenceMode (PersistenceMode.InnerProperty)]
+ [Browsable (false)]
+ public ITemplate FooterTemplate {
+ get { return footerTemplate; }
+ set { footerTemplate = value; OnFieldChanged (); }
+ }
+
+ [DefaultValue (null)]
+ [TemplateContainer (typeof(IDataItemContainer), BindingDirection.OneWay)]
+ [PersistenceMode (PersistenceMode.InnerProperty)]
+ [Browsable (false)]
+ public ITemplate HeaderTemplate {
+ get { return headerTemplate; }
+ set { headerTemplate = value; OnFieldChanged (); }
+ }
+
+ [DefaultValue (null)]
+ [TemplateContainer (typeof(IDataItemContainer), BindingDirection.TwoWay)]
+ [PersistenceMode (PersistenceMode.InnerProperty)]
+ [Browsable (false)]
+ public ITemplate InsertItemTemplate {
+ get { return insertItemTemplate; }
+ set { insertItemTemplate = value; OnFieldChanged (); }
+ }
+
+ [DefaultValue (null)]
+ [TemplateContainer (typeof(IDataItemContainer), BindingDirection.TwoWay)]
+ [PersistenceMode (PersistenceMode.InnerProperty)]
+ [Browsable (false)]
+ public ITemplate ItemTemplate {
+ get { return itemTemplate; }
+ set { itemTemplate = value; OnFieldChanged (); }
+ }
+
+ public override void InitializeCell (DataControlFieldCell cell,
+ DataControlCellType cellType, DataControlRowState rowState, int rowIndex)
+ {
+ if (cellType == DataControlCellType.Header) {
+ if (headerTemplate != null && ShowHeader) {
+ headerTemplate.InstantiateIn (cell);
+ return;
+ }
+ } else if (cellType == DataControlCellType.Footer) {
+ if (footerTemplate != null) {
+ footerTemplate.InstantiateIn (cell);
+ return;
+ }
+ } else {
+ if ((rowState & DataControlRowState.Insert) != 0) {
+ if (headerTemplate != null) {
+ insertItemTemplate.InstantiateIn (cell);
+ return;
+ }
+ }
+ else if ((rowState & DataControlRowState.Edit) != 0) {
+ if (editItemTemplate != null) {
+ editItemTemplate.InstantiateIn (cell);
+ return;
+ }
+ }
+ else if ((rowState & DataControlRowState.Alternate) != 0 && alternatingItemTemplate != null) {
+ alternatingItemTemplate.InstantiateIn (cell);
+ return;
+ }
+ else if (itemTemplate != null) {
+ itemTemplate.InstantiateIn (cell);
+ return;
+ }
+ }
+
+ base.InitializeCell (cell, cellType, rowState, rowIndex);
+ }
+
+ [MonoTODO]
+ public override void ExtractValuesFromCell (IOrderedDictionary dictionary,
+ DataControlFieldCell cell, DataControlRowState rowState, bool includeReadOnly)
+ {
+ }
+
+ public override void ValidateSupportsCallback ()
+ {
+ throw new NotSupportedException ("Callback not supported on TemplateField. Turn disable callbacks on '" + Control.ID + "'.");
+ }
+
}
}
#endif
object GetBoundPropertyValue (string name)
{
- if (boundProperties == null) {
- ICustomTypeDescriptor desc = hierarchyData as ICustomTypeDescriptor;
- if (desc == null)
- throw new InvalidOperationException ("Property '" + name + "' not found in data bound item");
- boundProperties = desc.GetProperties ();
- }
+ if (boundProperties == null)
+ boundProperties = TypeDescriptor.GetProperties (hierarchyData);
PropertyDescriptor prop = boundProperties.Find (name, true);
if (prop == null)
+2005-04-07 Lluis Sanchez Gual <lluis@novell.com>
+
+ * TemplateControl.cs:
+ * Page.cs: Moved Eval and XPath from Page
+ to TemplateControl.
+ * StateManagedCollection.cs: Avoid saving null state.
+
2005-04-01 Lluis Sanchez Gual <lluis@novell.com>
* DataSourceView.cs: Rethrow exceptions not handled by operation
_form = form;
}
- Stack dataItemCtx;
-
- internal void PushDataItemContext (object o)
- {
- if (dataItemCtx == null)
- dataItemCtx = new Stack ();
-
- dataItemCtx.Push (o);
- }
-
- internal void PopDataItemContext ()
- {
- if (dataItemCtx == null)
- throw new InvalidOperationException ();
-
- dataItemCtx.Pop ();
- }
-
- internal object CurrentDataItem {
- get {
- if (dataItemCtx == null)
- throw new InvalidOperationException ("No data item");
-
- return dataItemCtx.Peek ();
- }
- }
-
- protected object Eval (string expression)
- {
- return DataBinder.Eval (CurrentDataItem, expression);
- }
-
- protected object Eval (string expression, string format)
- {
- return DataBinder.Eval (CurrentDataItem, expression, format);
- }
-
- protected object XPath (string xpathexpression)
- {
- return XPathBinder.Eval (CurrentDataItem, xpathexpression);
- }
-
- protected object XPath (string xpathexpression, string format)
- {
- return XPathBinder.Eval (CurrentDataItem, xpathexpression, format);
- }
-
- protected IEnumerable XPathSelect (string xpathexpression)
- {
- return XPathBinder.Select (CurrentDataItem, xpathexpression);
- }
-
[BrowsableAttribute (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public Page PreviousPage {
#region IStateManager
void IStateManager.LoadViewState (object savedState)
{
+ if (savedState == null) return;
+
int pos = -1;
foreach (Pair p in (ArrayList)savedState) {
pos ++;
{
ArrayList saved = new ArrayList ();
Type [] knownTypes = GetKnownTypes ();
+ bool allNull = true;
foreach (IStateManager itm in items) {
object state = itm.SaveViewState ();
p.Second = t;
saved.Add (p);
+ allNull = false;
}
- return saved;
+ if (allNull) return null;
+ else return saved;
}
void IStateManager.TrackViewState ()
}
}
+#if NET_2_0
+
+ Stack dataItemCtx;
+
+ internal void PushDataItemContext (object o)
+ {
+ if (dataItemCtx == null)
+ dataItemCtx = new Stack ();
+
+ dataItemCtx.Push (o);
+ }
+
+ internal void PopDataItemContext ()
+ {
+ if (dataItemCtx == null)
+ throw new InvalidOperationException ();
+
+ dataItemCtx.Pop ();
+ }
+
+ internal object CurrentDataItem {
+ get {
+ if (dataItemCtx == null)
+ throw new InvalidOperationException ("No data item");
+
+ return dataItemCtx.Peek ();
+ }
+ }
+
+ protected object Eval (string expression)
+ {
+ return DataBinder.Eval (CurrentDataItem, expression);
+ }
+
+ protected object Eval (string expression, string format)
+ {
+ return DataBinder.Eval (CurrentDataItem, expression, format);
+ }
+
+ protected object XPath (string xpathexpression)
+ {
+ return XPathBinder.Eval (CurrentDataItem, xpathexpression);
+ }
+
+ protected object XPath (string xpathexpression, string format)
+ {
+ return XPathBinder.Eval (CurrentDataItem, xpathexpression, format);
+ }
+
+ protected IEnumerable XPathSelect (string xpathexpression)
+ {
+ return XPathBinder.Select (CurrentDataItem, xpathexpression);
+ }
+#endif
+
}
}
System.Web.UI.WebControls/ObjectDataSourceDisposingEventHandler.cs
System.Web.UI.WebControls/ObjectDataSourceEventArgs.cs
System.Web.UI.WebControls/ObjectDataSourceEventHandler.cs
+System.Web.UI.WebControls/ObjectDataSourceFilteringEventArgs.cs
+System.Web.UI.WebControls/ObjectDataSourceFilteringEventHandler.cs
System.Web.UI.WebControls/ObjectDataSourceMethodEventArgs.cs
System.Web.UI.WebControls/ObjectDataSourceMethodEventHandler.cs
System.Web.UI.WebControls/ObjectDataSourceSelectingEventArgs.cs
+2005-04-07 Andrew Skiba <andrews@mainsoft.com>
+
+ * XslDecimalFormat.jvm.cs : added
+
2005-03-31 Atsushi Enomoto <atsushi@ximian.com>
* MSXslScriptManager.cs : added TARGET_JVM switch (that does not
--- /dev/null
+//
+// XslDecimalFormat.jvm.cs
+//
+// Authors:
+// Andrew Skiba <andrews@mainsoft.com>
+//
+// (C) 2005 Mainsoft Corporation (http://www.mainsoft.com)
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Xml;
+using System.Xml.XPath;
+using System.Xml.Xsl;
+
+using QName = System.Xml.XmlQualifiedName;
+
+namespace Mono.Xml.Xsl {
+ internal class XslDecimalFormat {
+
+ java.text.DecimalFormatSymbols javaFormat;
+ string baseUri;
+ int lineNumber;
+ int linePosition;
+
+ public static readonly XslDecimalFormat Default = new XslDecimalFormat ();
+
+ XslDecimalFormat ()
+ {
+ javaFormat = new java.text.DecimalFormatSymbols ();
+ }
+
+ public XslDecimalFormat (Compiler c)
+ :this ()
+ {
+ Initialize(c);
+ }
+
+ private void Initialize(Compiler c)
+ {
+ XPathNavigator n = c.Input;
+
+ IXmlLineInfo li = n as IXmlLineInfo;
+ if (li != null) {
+ lineNumber = li.LineNumber;
+ linePosition = li.LinePosition;
+ }
+ baseUri = n.BaseURI;
+
+ if (n.MoveToFirstAttribute ()) {
+ do {
+ if (n.NamespaceURI != String.Empty)
+ continue;
+
+ switch (n.LocalName) {
+ case "name": break; // already handled
+ case "decimal-separator":
+ if (n.Value.Length != 1)
+ throw new XsltCompileException ("XSLT decimal-separator value must be exact one character.", null, n);
+ javaFormat.setDecimalSeparator (n.Value[0]);
+ break;
+
+ case "grouping-separator":
+ if (n.Value.Length != 1)
+ throw new XsltCompileException ("XSLT grouping-separator value must be exact one character.", null, n);
+ javaFormat.setGroupingSeparator (n.Value[0]);
+ break;
+
+ case "infinity":
+ javaFormat.setInfinity (n.Value);
+ break;
+ case "minus-sign":
+ if (n.Value.Length != 1)
+ throw new XsltCompileException ("XSLT minus-sign value must be exact one character.", null, n);
+ javaFormat.setMinusSign (n.Value[0]);
+ break;
+ case "NaN":
+ javaFormat.setNaN (n.Value);
+ break;
+ case "percent":
+ if (n.Value.Length != 1)
+ throw new XsltCompileException ("XSLT percent value must be exact one character.", null, n);
+ javaFormat.setPercent (n.Value[0]);
+ break;
+ case "per-mille":
+ if (n.Value.Length != 1)
+ throw new XsltCompileException ("XSLT per-mille value must be exact one character.", null, n);
+ javaFormat.setPerMill (n.Value[0]);
+ break;
+ case "digit":
+ if (n.Value.Length != 1)
+ throw new XsltCompileException ("XSLT digit value must be exact one character.", null, n);
+ javaFormat.setDigit (n.Value[0]);
+ break;
+ case "zero-digit":
+ if (n.Value.Length != 1)
+ throw new XsltCompileException ("XSLT zero-digit value must be exact one character.", null, n);
+ javaFormat.setZeroDigit (n.Value [0]);
+ break;
+ case "pattern-separator":
+ if (n.Value.Length != 1)
+ throw new XsltCompileException ("XSLT pattern-separator value must be exact one character.", null, n);
+ javaFormat.setPatternSeparator (n.Value [0]);
+ break;
+ }
+ } while (n.MoveToNextAttribute ());
+ n.MoveToParent ();
+ }
+ }
+
+ public void CheckSameAs (XslDecimalFormat other)
+ {
+ if (! this.javaFormat.equals (other.javaFormat))
+ throw new XsltCompileException (null, other.baseUri, other.lineNumber, other.linePosition);
+ }
+
+ public string FormatNumber (double number, string pattern)
+ {
+ java.text.DecimalFormat frm = new java.text.DecimalFormat("", javaFormat);
+
+ frm.applyLocalizedPattern (pattern);
+ java.lang.StringBuffer buffer= new java.lang.StringBuffer ();
+ java.text.FieldPosition fld = new java.text.FieldPosition (0);
+
+ frm.format (number, buffer, fld);
+ return buffer.ToString();
+ }
+ }
+}
+2004-04-03 Andrew Skiba <andrews@mainsoft.com>
+
+ * XmlSerializer.cs: added TARGET_JVM that does not support on-the-fly
+ code generation.
+
2005-03-30 Lluis Sanchez Gual <lluis@novell.com>
* SerializationCodeGenerator.cs:
using System.Xml;
using System.Xml.Schema;
using System.Text;
+#if !TARGET_JVM
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
+#endif
using System.Configuration;
using System.Security.Policy;
static XmlSerializer ()
{
- string db = Environment.GetEnvironmentVariable ("MONO_XMLSERIALIZER_DEBUG");
- deleteTempFiles = (db == null || db == "no");
-
- IDictionary table = (IDictionary) ConfigurationSettings.GetConfig("system.diagnostics");
- if (table != null) {
- table = (IDictionary) table["switches"];
- if (table != null) {
- string val = (string) table ["XmlSerialization.Compilation"];
- if (val == "1") deleteTempFiles = false;
- }
- }
+#if !TARGET_JVM
+ string db = null;
+ string th = null;
+ generationThreshold = -1;
+ backgroundGeneration = false;
+#else
+ string db = Environment.GetEnvironmentVariable ("MONO_XMLSERIALIZER_DEBUG");
string th = Environment.GetEnvironmentVariable ("MONO_XMLSERIALIZER_THS");
if (th == null) {
backgroundGeneration = (generationThreshold != 0);
if (generationThreshold < 1) generationThreshold = 1;
}
+#endif
+ deleteTempFiles = (db == null || db == "no");
+
+ IDictionary table = (IDictionary) ConfigurationSettings.GetConfig("system.diagnostics");
+ if (table != null)
+ {
+ table = (IDictionary) table["switches"];
+ if (table != null)
+ {
+ string val = (string) table ["XmlSerialization.Compilation"];
+ if (val == "1") deleteTempFiles = false;
+ }
+ }
}
#region Constructors
return new XmlSerializationReaderInterpreter (typeMapping);
}
+#if TARGET_JVM
+ void CheckGeneratedTypes (XmlMapping typeMapping)
+ {
+ throw new NotImplementedException();
+ }
+ void GenerateSerializersAsync (GenerationBatch batch)
+ {
+ throw new NotImplementedException();
+ }
+ void RunSerializerGeneration (object obj)
+ {
+ throw new NotImplementedException();
+ }
+#else
void CheckGeneratedTypes (XmlMapping typeMapping)
{
lock (this)
return res.CompiledAssembly;
}
+#endif
#if NET_2_0
GenerationBatch LoadFromSatelliteAssembly (GenerationBatch batch)
+2005-04-07 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * Socket.cs: added SocketOperation enum and 2 new fields to
+ SocketAsyncResult that are used by the runtime. Asynchronous read/write
+ are serialized so that only 1 of each kind is really 'active'.
+ Handle non-blocking connects in BeginConnect instead of doing 2 Poll()
+ in the threadpool.
+
+ * NetworkStream.cs: better message for the exception.
+
2005-04-04 Gonzalo Paniagua Javier <gonzalo@ximian.com>
* Socket.cs: remove unused async IO code.
if (socket.SocketType != SocketType.Stream)
throw new ArgumentException ("Socket is not of type Stream", "socket");
if (!socket.Blocking)
- throw new IOException ();
+ throw new IOException ("Operation not allowed on a non-blocking socket.");
this.socket = socket;
this.owns_socket = owns_socket;
{
public class Socket : IDisposable
{
+ enum SocketOperation {
+ Accept,
+ Connect,
+ Receive,
+ ReceiveFrom,
+ Send,
+ SendTo
+ }
+
[StructLayout (LayoutKind.Sequential)]
private sealed class SocketAsyncResult: IAsyncResult
{
bool completed;
AsyncCallback real_callback;
int error;
+ SocketOperation operation;
+ object ares;
- public SocketAsyncResult (Socket sock, object state, AsyncCallback callback)
+ public SocketAsyncResult (Socket sock, object state, AsyncCallback callback, SocketOperation operation)
{
this.Sock = sock;
this.handle = sock.socket;
this.state = state;
this.real_callback = callback;
+ this.operation = operation;
SockFlags = SocketFlags.None;
}
- public void CreateAsyncDelegate ()
- {
- if (real_callback != null)
- this.callback = new AsyncCallback (FakeCB);
- }
-
- static void FakeCB (IAsyncResult result)
- {
- SocketAsyncResult ares = (SocketAsyncResult) result;
- ares.real_callback.BeginInvoke (ares, null, null);
- }
-
public void CheckIfThrowDelayedException ()
{
if (delayedException != null)
IsCompleted = true;
if (real_callback != null)
real_callback (this);
+
+ Queue queue = null;
+ if (operation == SocketOperation.Receive || operation == SocketOperation.ReceiveFrom) {
+ queue = Sock.readQ;
+ } else if (operation == SocketOperation.Send || operation == SocketOperation.SendTo) {
+ queue = Sock.writeQ;
+ }
+
+ if (queue == null)
+ return;
+
+ SocketAsyncCall sac = null;
+ SocketAsyncResult req = null;
+ lock (queue) {
+ queue.Dequeue (); // remove ourselves
+ if (queue.Count > 0) {
+ req = (SocketAsyncResult) queue.Peek ();
+ Worker worker = new Worker (req);
+ sac = GetDelegate (worker, req.operation);
+ }
+ }
+
+ if (sac != null)
+ sac.BeginInvoke (null, req);
+ }
+
+ SocketAsyncCall GetDelegate (Worker worker, SocketOperation op)
+ {
+ switch (op) {
+ case SocketOperation.Receive:
+ return new SocketAsyncCall (worker.Receive);
+ case SocketOperation.ReceiveFrom:
+ return new SocketAsyncCall (worker.ReceiveFrom);
+ case SocketOperation.Send:
+ return new SocketAsyncCall (worker.Send);
+ case SocketOperation.SendTo:
+ return new SocketAsyncCall (worker.SendTo);
+ default:
+ return null; // never happens
+ }
+ }
+
+ public void Complete (bool synch)
+ {
+ completed_sync = synch;
+ Complete ();
}
public void Complete (int total)
this.total = total;
Complete ();
}
-
+
+ public void Complete (Exception e, bool synch)
+ {
+ completed_sync = synch;
+ delayedException = e;
+ Complete ();
+ }
+
public void Complete (Exception e)
{
delayedException = e;
lock (result) {
Socket acc_socket = null;
try {
- if (!result.Sock.blocking)
- result.Sock.Poll (-1, SelectMode.SelectRead);
-
acc_socket = result.Sock.Accept ();
} catch (Exception e) {
result.Complete (e);
lock (result) {
try {
result.Sock.Connect (result.EndPoint);
- } catch (SocketException se) {
- if (result.Sock.blocking || se.ErrorCode != 10036) {
- result.Complete (se);
- return;
- }
-
- try {
- result.Sock.Poll (-1, SelectMode.SelectWrite);
- result.Sock.Connect (result.EndPoint);
- } catch (Exception k) {
- result.Complete (k);
- return;
- }
} catch (Exception e) {
result.Complete (e);
return;
lock (result) {
int total = 0;
try {
- if (!result.Sock.blocking)
- result.Sock.Poll (-1, SelectMode.SelectRead);
-
total = result.Sock.Receive_nochecks (result.Buffer,
result.Offset,
result.Size,
lock (result) {
int total = 0;
try {
- if (!result.Sock.blocking)
- result.Sock.Poll (-1, SelectMode.SelectRead);
-
total = result.Sock.ReceiveFrom_nochecks (result.Buffer,
result.Offset,
result.Size,
lock (result) {
int total = 0;
try {
- if (!result.Sock.blocking)
- result.Sock.Poll (-1, SelectMode.SelectWrite);
-
total = result.Sock.Send_nochecks (result.Buffer,
result.Offset,
result.Size,
lock (result) {
int total = 0;
try {
- if (!result.Sock.blocking)
- result.Sock.Poll (-1, SelectMode.SelectWrite);
-
total = result.Sock.SendTo_nochecks (result.Buffer,
result.Offset,
result.Size,
internal bool blocking=true;
private int pendingEnds;
private int closeDelayed;
+ private Queue readQ = new Queue (2);
+ private Queue writeQ = new Queue (2);
delegate void SocketAsyncCall ();
/*
throw new ObjectDisposedException (GetType ().ToString ());
Interlocked.Increment (ref pendingEnds);
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
+ SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Accept);
Worker worker = new Worker (req);
SocketAsyncCall sac = new SocketAsyncCall (worker.Accept);
- sac.BeginInvoke (null, null);
+ sac.BeginInvoke (null, req);
return(req);
}
throw new ArgumentNullException ("end_point");
Interlocked.Increment (ref pendingEnds);
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
+ SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
req.EndPoint = end_point;
- Worker worker = new Worker (req);
- SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
- sac.BeginInvoke (null, null);
+ int error = 0;
+ if (!blocking) {
+ SocketAddress serial = end_point.Serialize ();
+ Connect_internal (socket, serial, out error);
+ if (error == 0) {
+ // succeeded synch
+ req.Complete (true);
+ } else if (error != 10036 && error != 10035) {
+ // error synch
+ req.Complete (new SocketException (error), true);
+ }
+ }
+
+ if (blocking || error == 10036 || error == 10035) {
+ // continue asynch
+ Worker worker = new Worker (req);
+ SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
+ sac.BeginInvoke (null, req);
+ }
+
return(req);
}
throw new ArgumentOutOfRangeException ("size");
Interlocked.Increment (ref pendingEnds);
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
- req.Buffer = buffer;
- req.Offset = offset;
- req.Size = size;
- req.SockFlags = socket_flags;
- Worker worker = new Worker (req);
- SocketAsyncCall sac = new SocketAsyncCall (worker.Receive);
- sac.BeginInvoke (null, null);
+ SocketAsyncResult req;
+ lock (readQ) {
+ req = new SocketAsyncResult (this, state, callback, SocketOperation.Receive);
+ req.Buffer = buffer;
+ req.Offset = offset;
+ req.Size = size;
+ req.SockFlags = socket_flags;
+ readQ.Enqueue (req);
+ if (readQ.Count == 1) {
+ Worker worker = new Worker (req);
+ SocketAsyncCall sac = new SocketAsyncCall (worker.Receive);
+ sac.BeginInvoke (null, req);
+ }
+ }
return req;
}
throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
Interlocked.Increment (ref pendingEnds);
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
- req.Buffer = buffer;
- req.Offset = offset;
- req.Size = size;
- req.SockFlags = socket_flags;
- req.EndPoint = remote_end;
- Worker worker = new Worker (req);
- SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveFrom);
- sac.BeginInvoke (null, null);
+ SocketAsyncResult req;
+ lock (readQ) {
+ req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveFrom);
+ req.Buffer = buffer;
+ req.Offset = offset;
+ req.Size = size;
+ req.SockFlags = socket_flags;
+ req.EndPoint = remote_end;
+ readQ.Enqueue (req);
+ if (readQ.Count == 1) {
+ Worker worker = new Worker (req);
+ SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveFrom);
+ sac.BeginInvoke (null, req);
+ }
+ }
return req;
}
throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
Interlocked.Increment (ref pendingEnds);
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
- req.Buffer = buffer;
- req.Offset = offset;
- req.Size = size;
- req.SockFlags = socket_flags;
- Worker worker = new Worker (req);
- SocketAsyncCall sac = new SocketAsyncCall (worker.Send);
- sac.BeginInvoke (null, null);
+ SocketAsyncResult req;
+ lock (writeQ) {
+ req = new SocketAsyncResult (this, state, callback, SocketOperation.Send);
+ req.Buffer = buffer;
+ req.Offset = offset;
+ req.Size = size;
+ req.SockFlags = socket_flags;
+ writeQ.Enqueue (req);
+ if (writeQ.Count == 1) {
+ Worker worker = new Worker (req);
+ SocketAsyncCall sac = new SocketAsyncCall (worker.Send);
+ sac.BeginInvoke (null, req);
+ }
+ }
return req;
}
throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
Interlocked.Increment (ref pendingEnds);
- SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
- req.Buffer = buffer;
- req.Offset = offset;
- req.Size = size;
- req.SockFlags = socket_flags;
- req.EndPoint = remote_end;
- Worker worker = new Worker(req);
- SocketAsyncCall sac = new SocketAsyncCall (worker.SendTo);
- sac.BeginInvoke (null, null);
+ SocketAsyncResult req;
+ lock (writeQ) {
+ req = new SocketAsyncResult (this, state, callback, SocketOperation.SendTo);
+ req.Buffer = buffer;
+ req.Offset = offset;
+ req.Size = size;
+ req.SockFlags = socket_flags;
+ req.EndPoint = remote_end;
+ writeQ.Enqueue (req);
+ if (writeQ.Count == 1) {
+ Worker worker = new Worker (req);
+ SocketAsyncCall sac = new SocketAsyncCall (worker.SendTo);
+ sac.BeginInvoke (null, req);
+ }
+ }
return req;
}
SocketAddress serial = remote_end.Serialize ();
Connect_internal(socket, serial, out error);
- if (error != 0)
+ if (error != 0) {
throw new SocketException (error);
+ }
connected=true;
}
throw new SocketException (error);
}
-
+
connected = true;
return ret;
+2005-04-07 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * WebHeaderCollection.cs: added if-modified-since to the list of
+ restricted headers.
+
+ * ServicePoint.cs: use a field object when locking.
+
+2005-04-07 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * WebConnectionStream.cs: ForceCompletion actually calls NextRead. No
+ need to wait for a Close/ReadAll when we have no content.
+
2005-04-04 Gonzalo Paniagua Javier <gonzalo@ximian.com>
* NtlmClient.cs: fix typo in assembly name.
Hashtable groups;
bool sendContinue = true;
bool useConnect;
+ object locker = new object ();
#if NET_1_1
bool useNagle;
#endif
public int CurrentConnections {
get {
- lock (this) {
+ lock (locker) {
return currentConnections;
}
}
public DateTime IdleSince {
get {
- lock (this) {
+ lock (locker) {
return idleSince;
}
}
{
WebConnection cnc;
- lock (this) {
+ lock (locker) {
WebConnectionGroup cncGroup = GetConnectionGroup (groupName);
cnc = cncGroup.GetConnection ();
}
internal void IncrementConnection ()
{
- lock (this) {
+ lock (locker) {
currentConnections++;
idleSince = DateTime.Now.AddMilliseconds (1000000);
}
internal void DecrementConnection ()
{
- lock (this) {
+ lock (locker) {
currentConnections--;
if (currentConnections == 0)
idleSince = DateTime.Now;
byte [] headers;
bool disposed;
bool headersSent;
- bool forceCompletion;
public WebConnectionStream (WebConnection cnc)
{
internal void ForceCompletion ()
{
- forceCompletion = true;
+ nextReadCalled = true;
+ cnc.NextRead ();
}
internal void CheckComplete ()
{
bool nrc = nextReadCalled;
- if (forceCompletion || (!nrc && readBufferSize - readBufferOffset == contentLength)) {
+ if (!nrc && readBufferSize - readBufferOffset == contentLength) {
nextReadCalled = true;
cnc.NextRead ();
}
restricted.Add ("date", true);\r
restricted.Add ("expect", true);\r
restricted.Add ("host", true);\r
+ restricted.Add ("if-modified-since", true);\r
restricted.Add ("range", true);\r
restricted.Add ("referer", true);\r
restricted.Add ("transfer-encoding", true);\r
if (name == null)\r
throw new ArgumentNullException ("name");\r
if (internallyCreated && IsRestricted (name))\r
- throw new ArgumentException ("restricted header");\r
+ throw new ArgumentException ("This header must be modified with the appropiate property.");
this.AddWithoutValidate (name, value);\r
}\r
\r
+2005-04-07 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * FileStream.cs:
+ * MonoIO.cs: remove dead code related to async IO.
+
2005-03-24 Sebastien Pouliot <sebastien@ximian.com>
* Directory.cs: Added a Demand for Read/Write when creating a new
this.canseek = true;
} else {
this.canseek = false;
+ noBuffering = true;
+ bufferSize = 0;
}
this.handle = handle;
this.async = isAsync;
this.anonymous = false;
- if (isAsync && MonoIO.SupportsAsync)
- ThreadPool.BindHandle (handle);
-
InitBuffer (bufferSize, noBuffering);
/* Can't set append mode */
MonoIOError error;
- bool openAsync = (isAsync && MonoIO.SupportsAsync);
- this.handle = MonoIO.Open (name, mode, access, share, openAsync, out error);
+ this.handle = MonoIO.Open (name, mode, access, share, false, out error);
if (handle == MonoIO.InvalidHandle) {
// don't leak the path information for isolated storage
string fname = (anonymous) ? Path.GetFileName (name) : name;
if (MonoIO.GetFileType (handle, out error) == MonoFileType.Disk) {
this.canseek = true;
this.async = isAsync;
- if (openAsync)
- ThreadPool.BindHandle (handle);
} else {
this.canseek = false;
this.async = false;
if (handle == MonoIO.InvalidHandle)
throw new ObjectDisposedException ("Stream has been closed");
- if (!canseek)
+ if (!CanSeek)
throw new NotSupportedException ("The stream does not support seeking");
// Buffered data might change the length of the stream
if (!async)
return base.BeginRead (buffer, offset, count, cback, state);
- if (!MonoIO.SupportsAsync) {
- ReadDelegate r = new ReadDelegate (ReadInternal);
- return r.BeginInvoke (buffer, offset, count, cback, state);
- }
-
- FileStreamAsyncResult result = new FileStreamAsyncResult (cback, state);
- result.Count = count;
- result.OriginalCount = count;
- int buffered = ReadSegment (buffer, offset, count);
- if (buffered >= count) {
- result.SetComplete (null, buffered, true);
- return result;
- }
-
- result.Buffer = buffer;
- result.Offset = offset + buffered;
- result.Count -= buffered;
-
- KeepReference (result);
- MonoIO.BeginRead (handle, result);
-
- return result;
+ ReadDelegate r = new ReadDelegate (ReadInternal);
+ return r.BeginInvoke (buffer, offset, count, cback, state);
}
public override int EndRead (IAsyncResult async_result)
if (!async)
return base.EndRead (async_result);
- if (!MonoIO.SupportsAsync) {
- AsyncResult ares = async_result as AsyncResult;
- if (ares == null)
- throw new ArgumentException ("Invalid IAsyncResult", "async_result");
-
- ReadDelegate r = ares.AsyncDelegate as ReadDelegate;
- if (r == null)
- throw new ArgumentException ("Invalid IAsyncResult", "async_result");
-
- return r.EndInvoke (async_result);
- }
-
- FileStreamAsyncResult result = async_result as FileStreamAsyncResult;
- if (result == null || result.BytesRead == -1)
+ AsyncResult ares = async_result as AsyncResult;
+ if (ares == null)
throw new ArgumentException ("Invalid IAsyncResult", "async_result");
- RemoveReference (result);
- if (result.Done)
- throw new InvalidOperationException ("EndRead already called.");
-
- result.Done = true;
- if (!result.IsCompleted)
- result.AsyncWaitHandle.WaitOne ();
-
- if (result.Exception != null)
- throw result.Exception;
+ ReadDelegate r = ares.AsyncDelegate as ReadDelegate;
+ if (r == null)
+ throw new ArgumentException ("Invalid IAsyncResult", "async_result");
- buf_start += result.BytesRead;
- return result.OriginalCount - result.Count + result.BytesRead;
+ return r.EndInvoke (async_result);
}
public override void Write (byte[] src, int src_offset, int count)
bytes = buffer;
}
- if (!MonoIO.SupportsAsync) {
- WriteDelegate w = new WriteDelegate (WriteInternal);
- return w.BeginInvoke (buffer, offset, count, cback, state);
- }
-
- if (buffered >= count) {
- result.SetComplete (null, buffered, true);
- return result;
- }
-
- result.Buffer = buffer;
- result.Offset = offset;
- result.Count = count;
-
- KeepReference (result);
- MonoIO.BeginWrite (handle, result);
-
- return result;
+ WriteDelegate w = new WriteDelegate (WriteInternal);
+ return w.BeginInvoke (buffer, offset, count, cback, state);
}
public override void EndWrite (IAsyncResult async_result)
return;
}
- if (!MonoIO.SupportsAsync) {
- AsyncResult ares = async_result as AsyncResult;
- if (ares == null)
- throw new ArgumentException ("Invalid IAsyncResult", "async_result");
-
- WriteDelegate w = ares.AsyncDelegate as WriteDelegate;
- if (w == null)
- throw new ArgumentException ("Invalid IAsyncResult", "async_result");
-
- w.EndInvoke (async_result);
- return;
- }
-
- FileStreamAsyncResult result = async_result as FileStreamAsyncResult;
- if (result == null || result.BytesRead != -1)
+ AsyncResult ares = async_result as AsyncResult;
+ if (ares == null)
throw new ArgumentException ("Invalid IAsyncResult", "async_result");
- RemoveReference (result);
- if (result.Done)
- throw new InvalidOperationException ("EndWrite already called.");
-
- result.Done = true;
- if (!result.IsCompleted)
- result.AsyncWaitHandle.WaitOne ();
-
- if (result.Exception != null)
- throw result.Exception;
+ WriteDelegate w = ares.AsyncDelegate as WriteDelegate;
+ if (w == null)
+ throw new ArgumentException ("Invalid IAsyncResult", "async_result");
- buf_start += result.Count;
- buf_offset = buf_length = 0;
+ w.EndInvoke (async_result);
+ return;
}
public override long Seek (long offset, SeekOrigin origin)
buf_dirty = false;
}
- static void KeepReference (object o)
- {
- lock (typeof (FileStream)) {
- if (asyncObjects == null)
- asyncObjects = new Hashtable ();
-
- asyncObjects [o] = o;
- }
- }
-
- static void RemoveReference (object o)
- {
- lock (typeof (FileStream)) {
- if (asyncObjects == null)
- return;
-
- asyncObjects.Remove (o);
- }
- }
-
// fields
internal const int DefaultBufferSize = 8192;
- private static Hashtable asyncObjects;
private FileAccess access;
private bool owner;
-//
// System.IO.MonoIO.cs: static interface to native filesystem.
//
// Author:
public static readonly IntPtr
InvalidHandle = (IntPtr)(-1L);
- public static readonly bool SupportsAsync = GetSupportsAsync ();
-
// error methods
-
public static Exception GetException (MonoIOError error)
{
return GetException (String.Empty, error);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
public extern static MonoFileType GetFileType (IntPtr handle, out MonoIOError error);
- // aio_* methods
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- extern static bool GetSupportsAsync ();
-
public static bool Exists (string path, out MonoIOError error)
{
FileAttributes attrs = GetFileAttributes (path,
[MethodImplAttribute (MethodImplOptions.InternalCall)]
public extern static int GetTempPath(out string path);
-
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- public extern static void BeginWrite (IntPtr handle,FileStreamAsyncResult ares);
-
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- public extern static void BeginRead (IntPtr handle, FileStreamAsyncResult ares);
-
}
}
+2005-04-07 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * ThreadPool.cs: BindHandle does nothing now.
+
+2005-04-07 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * Thread.cs: clear the Unstarted bit before calling Start_internal.
+ Fixes bug #72738.
+
2005-04-04 Ben Maurer <bmaurer@ximian.com>
* Thread.cs: Do argument checking for Current[UI]Culture to make
throw new SystemException ("Thread creation failed");
}
- // Launch this thread
- Start_internal(system_thread_handle);
-
// Mark the thread state as Running
// (which is all bits
// cleared). Therefore just remove the
// Unstarted bit
clr_state(ThreadState.Unstarted);
+
+ // Launch this thread
+ Start_internal(system_thread_handle);
}
}
/* nothing to do */
}
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- static extern bool BindHandleInternal (IntPtr osHandle);
-
- [SecurityPermission (SecurityAction.Demand, UnmanagedCode=true)]
public static bool BindHandle (IntPtr osHandle)
{
- return BindHandleInternal (osHandle);
+ return true;
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
Assembly corlib2 = Assembly.LoadWithPartialName ("corlib_plattest");
Assert.IsTrue (corlib != null || corlib2 != null);
}
+
+#if NET_2_0
+ [Test]
+ public void ReflectionOnlyLoad ()
+ {
+ Assembly assembly = Assembly.ReflectionOnlyLoad (typeof (AssemblyTest).Assembly.FullName);
+
+ Assert.IsNotNull (assembly);
+ Assert.IsTrue (assembly.ReflectionOnly);
+ }
+
+ [Test]
+ public void ReflectionOnlyLoadFrom ()
+ {
+ string loc = typeof (AssemblyTest).Assembly.Location;
+ string filename = Path.GetFileName (loc);
+ Assembly assembly = Assembly.ReflectionOnlyLoadFrom (filename);
+
+ Assert.IsNotNull (assembly);
+ Assert.IsTrue (assembly.ReflectionOnly);
+ }
+
+ [Test]
+ [ExpectedException (typeof (ArgumentException))]
+ public void CreateInstanceOnRefOnly ()
+ {
+ Assembly assembly = Assembly.ReflectionOnlyLoad (typeof (AssemblyTest).Assembly.FullName);
+ assembly.CreateInstance ("MonoTests.System.Reflection.AssemblyTest");
+ }
+#endif
}
}
+2005-04-08 Raja R Harinath <rharinath@novell.com>
+
+ * FieldInfoTest.cs (RefOnlyFieldClass): Rename from RefOnlyClass.
+ * MethodInfoTest.cs (RefOnlyMethodClass): Rename from RefOnlyClass.
+
+2005-04-08 Carlos Alberto Cortez <calberto.cortez@gmail.com>
+
+ * AssemblyTest.cs: Added tests for ReflectionOnly support.
+ * MethodInfoTest.cs: Added test for Reflection Only support.
+ * FieldInfoTest.cs: Added tests for ReflectionOnly support.
+
2005-04-04 Sebastien Pouliot <sebastien@ximian.com>
* AssemblyNameTest.cs: Added tests for Clone and serialization without
AssertEquals (typeof (Marshal1), Type.GetType (attr.MarshalType));
*/
}
+
+ [Test]
+ [ExpectedException (typeof (InvalidOperationException))]
+ public void GetValueOnRefOnlyAssembly ()
+ {
+ Assembly assembly = Assembly.ReflectionOnlyLoad (typeof (FieldInfoTest).Assembly.FullName);
+ Type t = assembly.GetType (typeof (RefOnlyFieldClass).FullName);
+ FieldInfo f = t.GetField ("RefOnlyField", BindingFlags.Static | BindingFlags.NonPublic);
+
+ f.GetValue (null);
+ }
+
+ [Test]
+ [ExpectedException (typeof (InvalidOperationException))]
+ public void SetValueOnRefOnlyAssembly ()
+ {
+ Assembly assembly = Assembly.ReflectionOnlyLoad (typeof (FieldInfoTest).Assembly.FullName);
+ Type t = assembly.GetType (typeof (RefOnlyFieldClass).FullName);
+ FieldInfo f = t.GetField ("RefOnlyField", BindingFlags.Static | BindingFlags.NonPublic);
+
+ f.SetValue (null, 8);
+ }
+
#endif
}
+#if NET_2_0
+// Helper class
+class RefOnlyFieldClass
+{
+ // Helper property
+ static int RefOnlyField;
+}
+#endif
}
else
AssertEquals (false, locals [1].IsPinned);
}
+
+ [Test]
+ [ExpectedException (typeof (InvalidOperationException))]
+ public void InvokeOnRefOnlyAssembly ()
+ {
+ Assembly a = Assembly.ReflectionOnlyLoad (typeof (MethodInfoTest).Assembly.FullName);
+ Type t = a.GetType (typeof (RefOnlyMethodClass).FullName);
+ MethodInfo m = t.GetMethod ("RefOnlyMethod", BindingFlags.Static | BindingFlags.NonPublic);
+
+ m.Invoke (null, new object [0]);
+ }
+
#endif
}
+
+#if NET_2_0
+ // Helper class
+ class RefOnlyMethodClass
+ {
+ // Helper static method
+ static void RefOnlyMethod ()
+ {
+ }
+ }
+#endif
}
+2005-04-08 Raja R Harinath <rharinath@novell.com>
+
+ * cs0535-3.cs: New test from #58413.
+
2005-04-05 Raja R Harinath <rharinath@novell.com>
* cs0208-5.cs, cs0208-6.cs: New tests from #62232.
+++ /dev/null
-// cs0422.cs: 'C.Prop.get': abstract properties cannot have private accessors
-// Line: 7
-
-abstract class C {
- protected abstract int Prop
- {
- private get;
- set;
- }
-}
-
--- /dev/null
+// cs0442.cs: 'C.Prop.get': abstract properties cannot have private accessors
+// Line: 7
+
+abstract class C {
+ protected abstract int Prop
+ {
+ private get;
+ set;
+ }
+}
+
--- /dev/null
+// cs0535.cs: 'Test' does not implement interface member 'X.Hola(ref string)'
+// Line: 9
+
+using System;
+interface X {
+ void Hola (ref string name);
+}
+
+class Test : X {
+ static void Main ()
+ {
+ }
+
+ public void Hola (out string name)
+ {
+ name = null;
+ }
+}
--- /dev/null
+// cs0655.cs: 'd' is not a valid named attribute argument because its type is not valid attribute type
+// Line: 11
+
+using System;
+
+class TestAttribute : Attribute
+{
+ public int[][] a;
+}
+
+[Test (a = null)]
+class C
+{
+}
\ No newline at end of file
--- /dev/null
+// cs0655.cs: 'd' is not a valid named attribute argument because its type is not valid attribute type
+// Line: 11
+
+using System;
+
+class TestAttribute : Attribute
+{
+ public decimal d;
+}
+
+[Test (d = 44444)]
+class C
+{
+}
\ No newline at end of file
--- /dev/null
+// CS1636: __arglist is not allowed in parameter list of iterators
+// Line: 6
+
+class C
+{
+ public System.Collections.IEnumerator GetEnumerator (__arglist)
+ {
+ yield return 1;
+ }
+
+}
--- /dev/null
+// CS1637: Iterators cannot have unsafe parameters or yield types
+// Line: 6
+// Compiler options: /unsafe
+
+unsafe class C
+{
+ public System.Collections.IEnumerator GetEnumerator (int* p)
+ {
+ yield return 1;
+ }
+
+}
--- /dev/null
+// cs1674.cs: 'int': type used in a using statement must be implicitly convertible to 'System.IDisposable'
+// Line: 8
+
+class C
+{
+ void Method (int arg)
+ {
+ using (arg)
+ {
+ }
+ }
+}
\ No newline at end of file
cs0266-2.cs
cs0534-3.cs
cs0534-4.cs
+cs0535-3.cs
cs0576.cs
cs0611-2.cs
cs0611.cs
cs0271.cs
cs0272.cs
cs0407.cs
-cs0422.cs
+cs0442.cs
cs0428.cs
cs0525-2.cs
cs0525.cs
cs0647-15.cs
cs0650.cs
cs0654.cs
+cs0655.cs
+cs0655-2.cs
cs0681.cs
cs0683.cs
cs0686.cs
cs1629.cs
cs1633.cs
cs1634.cs
+cs1636.cs
+cs1637.cs
cs1638.cs
cs1641.cs
cs1642.cs
cs1670.cs
cs1671-2.cs
cs1671.cs
+cs1674.cs
cs1677-2.cs
cs1677.cs
cs1708.cs
using System.Reflection;
using System.Runtime.CompilerServices;
-[assembly: AssemblyVersion("1.1.3")]
+[assembly: AssemblyVersion("1.1.4")]
[assembly: AssemblyTitle ("Mono C# Compiler")]
[assembly: AssemblyDescription ("Mono C# Compiler with Generics")]
[assembly: AssemblyCopyright ("2001, 2002, 2003 Ximian, Inc.")]
+2005-02-09 Raja R Harinath <rharinath@novell.com>
+
+ Combine two near-redundant caches.
+ * typemanager.cs (method_params): Rename from method_internal_params.
+ (TypeManager.GetParameterData): New. Replace
+ Invocation.GetParameterData.
+ (TypeManager.LookupParametersByBuilder): Remove.
+ * expression.cs (Invocation.method_parameter_cache): Remove.
+ (Invocation.GetParameterData): Remove.
+ Update to changes.
+ * anonymous.cs, attribute.cs, convert.cs, delegate.cs:
+ Update to changes.
+
+2005-02-08 Raja R Harinath <rharinath@novell.com>
+
+ Fix #72015.
+ * delegate.cs (Delegate.DefineType): When bootstrapping corlib, if
+ TypeManager.multicast_delegate_type is null, resolve it by looking
+ up "System.MulticastDelegate".
+ * rootcontext.cs (RootContext.ResolveCore): Simplify.
+
+2005-02-07 Abin Thomas (NOSIP) <projectmonokochi@rediffmail.com>
+ Anoob V.E (NOSIP) <projectmonokochi@rediffmail.com>
+ Harilal P.R (NOSIP) <projectmonokochi@rediffmail.com>
+
+ Fix cs0164.cs.
+ * statement.cs (LabeledStatement.Resolve): Don't set 'referenced'.
+ (LabeledStatement.AddReference): New. Set 'referenced'.
+ (Goto.Resolve): Use it.
+
+2005-02-05 John Luke <john.luke@gmail.com>
+
+ * driver.cs: remove duplicate -doc line in Usage ()
+
+2005-02-04 Raja R Harinath <rharinath@novell.com>
+
+ * location.cs (Location.AddFile): Fix CS2002 error report.
+
+2005-02-02 Martin Baulig <martin@ximian.com>
+
+ * delegate.cs (Delegate.DefineType): Report an internal error if
+ TypeManager.multicast_delegate_type is null. See bug #72015 for
+ details.
+
+2005-02-02 Raja R Harinath <rharinath@novell.com>
+
+ Fix a crasher in a variant of #31984.
+ * const.cs (Constant.CheckBase): New override that defers the
+ new-or-override check in case the base type hasn't been populated
+ yet.
+ (Constant.Define): Ensure the new-or-override check is performed.
+
+2005-02-01 Duncan Mak <duncan@ximian.com>
+
+ * const.cs (LookupConstantValue): Check that `ce' is not null
+ before calling GetValue ().
+
+2005-02-01 Raja R Harinath <rharinath@novell.com>
+
+ Fix test-334.cs (#69519).
+ * cs-parser.jay (using_alias_directive): Pass in an expression to
+ NamespaceEntry.UsingAlias.
+ (using_namespace_directive): Pass in an expression to
+ NamespaceEntry.Using.
+ (namespace_name): Don't flatten to a string.
+ * namespace.cs (NamespaceEntry.AliasEntry): Store an expression.
+ (NamespaceEntry.AliasEntry.Resolve): Lookup using
+ ResolveAsTypeStep.
+ (NamespaceEntry.UsingEntry): Likewise.
+ (NamespaceEntry.Using,NamespaceEntry.UsingAlias): Update to
+ changes.
+ (NamespaceEntry.LookupForUsing): Remove.
+ (NamespaceEntry.LookupNamespaceOrType): Add support for dotted
+ names.
+ (NamespaceEntry.Lookup): Remove support for dotted names.
+
+2005-02-01 Raja R Harinath <rharinath@novell.com>
+
+ * namespace.cs (NamespaceEntry.NamespaceEntry): Simplify, and
+ split into two.
+ (NamespaceEntry.ImplicitParent): Compute on demand.
+ (NamespaceEntry.Doppelganger): New implicit namespace-entry that
+ parallels the current.
+ (NamespaceEntry.LookupForUsing): Use it.
+ (NamespaceEntry.Lookup): If the current namespace-entry is
+ implicit, don't search aliases and using tables.
+
+2005-02-01 Raja R Harinath <rharinath@novell.com>
+
+ Fix #31984.
+ * class.cs (TypeContainer.DoDefineMembers): Don't initialize
+ BaseCache here.
+ (TypeContainer.BaseCache): Compute on demand.
+ (TypeContainer.FindMembers): Define constants and types if they're
+ not already created.
+ (FieldMember.Define): Move resetting of ec.InUnsafe before error
+ check.
+ * const.cs (Constant.Define): Make idempotent.
+
+2005-01-29 Miguel de Icaza <miguel@novell.com>
+
+ * pending.cs: Produce better code (no nops produced by using Ldarg
+ + value).
+
+ * pending.cs (PendingImplementation.DefineProxy): It was not `arg
+ i - 1' it should be arg + 1.
+
+ Fixes bug #71819.
+
+2005-01-28 Raja R Harinath <rharinath@novell.com>
+
+ * attribute.cs (Attribute.CheckAttributeType): Make private
+ non-virtual.
+ (Attribute.ResolveType): Make virtual.
+ (GlobalAttribute.ResolveType,GlobalAttribute.Resolve): Simplify
+ handling of RootContext.Tree.Types.
+
+2005-01-27 Raja R Harinath <rharinath@novell.com>
+
+ Update attribute-handling to use the SimpleName/MemberAccess
+ mechanisms.
+ * cs-parser.jay (attribute): Pass in an expression to the
+ constructors of Attribute and GlobalAttribute.
+ * attribute.cs (Attribute): Take an expression for the name.
+ (Attribute.ResolvePossibleAttributeTypes): New. Resolves the
+ passed in attribute name expression.
+ (Attribute.CheckAttributeType): Use it.
+ * ecore.cs (FullNamedExpression.ResolveAsTypeStep): New.
+ * expression.cs (MemberAccess.ResolveAsTypeStep): Move body to ...
+ (MemberAccess.ResolveNamespaceOrType): ... here. Add 'silent'
+ argument to prevent error messages if the lookup fails.
+
+2005-01-27 Marek Safar <marek.safar@seznam.cz>
+
+ * expression.cs (Indirection): Implemented IVariable interface
+ to support indirection in AddressOf operator.
+ (PointerArithmetic.Emit): Add optimalization for case where
+ result can be precomputed.
+
+2005-01-26 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.AttributeTargets): Return the correct
+ AttributeTargets depending on our `Kind' instead of throwing an
+ exception; fixes #71632.
+
+2005-01-26 Marek Safar <marek.safar@seznam.cz>
+
+ Fix #71257
+ * expression.cs (MemberAccess.ResolveMemberAccess): Add CS0176 test for
+ constant members.
+
2005-03-17 Martin Baulig <martin@ximian.com>
* anonymous.cs (AnonymousMethod.method_modifiers): Change default
MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (ec, delegate_type, loc);
invoke_mb = (MethodInfo) invoke_mg.Methods [0];
- ParameterData invoke_pd = Invocation.GetParameterData (invoke_mb);
+ ParameterData invoke_pd = TypeManager.GetParameterData (invoke_mb);
//
// If implicit parameters are set, then we must check for out in the parameters
public AttributeTargets Target;
public readonly string Name;
+ public readonly Expression LeftExpr;
+ public readonly string Identifier;
+
public readonly ArrayList Arguments;
public readonly Location Location;
static PtrHashtable usage_attr_cache = new PtrHashtable ();
- public Attribute (string target, string name, ArrayList args, Location loc)
+ public Attribute (string target, Expression left_expr, string identifier, ArrayList args, Location loc)
{
- Name = name;
+ LeftExpr = left_expr;
+ Identifier = identifier;
+ Name = LeftExpr == null ? identifier : LeftExpr + "." + identifier;
Arguments = args;
Location = loc;
ExplicitTarget = target;
{
Report.Error (617, Location, "Invalid attribute argument: '{0}'. Argument must be fields " +
"fields which are not readonly, static or const; or read-write instance properties.",
- Name);
+ name);
}
static void Error_AttributeArgumentNotValid (string extra, Location loc)
"Could not find a constructor for this argument list.");
}
+ void ResolvePossibleAttributeTypes (EmitContext ec, out Type t1, out Type t2)
+ {
+ t1 = null;
+ t2 = null;
+
+ FullNamedExpression n1 = null;
+ FullNamedExpression n2 = null;
+ string IdentifierAttribute = Identifier + "Attribute";
+ if (LeftExpr == null) {
+ n1 = new SimpleName (Identifier, Location).ResolveAsTypeStep (ec);
+
+ // FIXME: Shouldn't do this for quoted attributes: [@A]
+ n2 = new SimpleName (IdentifierAttribute, Location).ResolveAsTypeStep (ec);
+ } else {
+ FullNamedExpression l = LeftExpr.ResolveAsTypeStep (ec);
+ if (l == null) {
+ Report.Error (246, Location, "Couldn't find namespace or type '{0}'", LeftExpr);
+ return;
+ }
+ n1 = new MemberAccess (l, Identifier, Location).ResolveNamespaceOrType (ec, true);
+
+ // FIXME: Shouldn't do this for quoted attributes: [X.@A]
+ n2 = new MemberAccess (l, IdentifierAttribute, Location).ResolveNamespaceOrType (ec, true);
+ }
+
+ TypeExpr te1 = n1 == null ? null : n1 as TypeExpr;
+ TypeExpr te2 = n2 == null ? null : n2 as TypeExpr;
+
+ if (te1 != null)
+ t1 = te1.ResolveType (ec);
+ if (te2 != null)
+ t2 = te2.ResolveType (ec);
+ }
+
/// <summary>
/// Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
/// </summary>
- protected virtual Type CheckAttributeType (EmitContext ec)
+ Type CheckAttributeType (EmitContext ec)
{
- string NameAttribute = Name + "Attribute";
- FullNamedExpression n1 = ec.ResolvingTypeTree
- ? ec.DeclSpace.FindType (Location, Name)
- : ec.DeclSpace.LookupType (Name, true, Location);
+ Type t1, t2;
+ ResolvePossibleAttributeTypes (ec, out t1, out t2);
- // FIXME: Shouldn't do this for quoted attributes: [@A]
- FullNamedExpression n2 = ec.ResolvingTypeTree
- ? ec.DeclSpace.FindType (Location, NameAttribute)
- : ec.DeclSpace.LookupType (NameAttribute, true, Location);
-
- TypeExpr e1 = n1 == null ? null : n1 as TypeExpr;
- TypeExpr e2 = n2 == null ? null : n2 as TypeExpr;
-
- Type t1 = e1 == null ? null : e1.ResolveType (ec);
- Type t2 = e2 == null ? null : e2.ResolveType (ec);
+ string NameAttribute = Name + "Attribute";
String err0616 = null;
if (t1 != null && ! t1.IsSubclassOf (TypeManager.attribute_type)) {
return null;
}
- public Type ResolveType (EmitContext ec)
+ public virtual Type ResolveType (EmitContext ec)
{
if (Type == null)
Type = CheckAttributeType (ec);
// of type object
//
- ParameterData pd = Invocation.GetParameterData (constructor);
+ ParameterData pd = TypeManager.GetParameterData (constructor);
int last_real_param = pd.Count;
if (pd.HasParams) {
{
public readonly NamespaceEntry ns;
- public GlobalAttribute (TypeContainer container, string target, string name, ArrayList args, Location loc):
- base (target, name, args, loc)
+ public GlobalAttribute (TypeContainer container, string target,
+ Expression left_expr, string identifier, ArrayList args, Location loc):
+ base (target, left_expr, identifier, args, loc)
{
ns = container.NamespaceEntry;
}
- protected override Type CheckAttributeType (EmitContext ec)
+ void Enter ()
{
// RootContext.Tree.Types has a single NamespaceEntry which gets overwritten
// each time a new file is parsed. However, we need to use the NamespaceEntry
// in effect where the attribute was used. Since code elsewhere cannot assume
// that the NamespaceEntry is right, just overwrite it.
//
- // Precondition: RootContext.Tree.Types == null || RootContext.Tree.Types == ns.
- // The second case happens when we are recursively invoked from inside Emit.
-
- NamespaceEntry old = null;
- if (ec.DeclSpace == RootContext.Tree.Types) {
- old = ec.DeclSpace.NamespaceEntry;
- ec.DeclSpace.NamespaceEntry = ns;
- if (old != null && old != ns)
- throw new InternalErrorException (Location + " non-null NamespaceEntry " + old);
- }
+ // Precondition: RootContext.Tree.Types == null
- Type retval = base.CheckAttributeType (ec);
+ if (RootContext.Tree.Types.NamespaceEntry != null)
+ throw new InternalErrorException (Location + " non-null NamespaceEntry");
- if (ec.DeclSpace == RootContext.Tree.Types)
- ec.DeclSpace.NamespaceEntry = old;
+ RootContext.Tree.Types.NamespaceEntry = ns;
+ }
+ void Leave ()
+ {
+ RootContext.Tree.Types.NamespaceEntry = null;
+ }
+
+ public override Type ResolveType (EmitContext ec)
+ {
+ Enter ();
+ Type retval = base.ResolveType (ec);
+ Leave ();
return retval;
}
public override CustomAttributeBuilder Resolve (EmitContext ec)
{
- if (ec.DeclSpace == RootContext.Tree.Types) {
- NamespaceEntry old = ec.DeclSpace.NamespaceEntry;
- ec.DeclSpace.NamespaceEntry = ns;
- if (old != null)
- throw new InternalErrorException (Location + " non-null NamespaceEntry " + old);
- }
-
+ Enter ();
CustomAttributeBuilder retval = base.Resolve (ec);
-
- if (ec.DeclSpace == RootContext.Tree.Types)
- ec.DeclSpace.NamespaceEntry = null;
-
+ Leave ();
return retval;
}
}
protected virtual bool DoDefineMembers ()
{
- //
- // We need to be able to use the member cache while we are checking/defining
- //
- if (TypeBuilder.BaseType != null)
- base_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
-
- if (TypeBuilder.IsInterface)
- base_cache = TypeManager.LookupBaseInterfacesCache (TypeBuilder);
-
if (IsTopLevel) {
if ((ModFlags & Modifiers.NEW) != 0)
Error_KeywordNotAllowed (Location);
continue;
FieldBuilder fb = con.FieldBuilder;
+ if (fb == null) {
+ if (con.Define ())
+ fb = con.FieldBuilder;
+ }
if (fb != null && filter (fb, criteria) == true) {
if (members == null)
members = new ArrayList ();
continue;
TypeBuilder tb = t.TypeBuilder;
+ if (tb == null)
+ tb = t.DefineType ();
+
if (tb != null && (filter (tb, criteria) == true)) {
if (members == null)
members = new ArrayList ();
public virtual MemberCache BaseCache {
get {
+ if (base_cache != null)
+ return base_cache;
+ if (TypeBuilder.BaseType != null)
+ base_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
+ if (TypeBuilder.IsInterface)
+ base_cache = TypeManager.LookupBaseInterfacesCache (TypeBuilder);
return base_cache;
}
}
protected override bool CheckGenericOverride (MethodInfo method, string name)
{
- ParameterData pd = Invocation.GetParameterData (method);
+ ParameterData pd = TypeManager.GetParameterData (method);
for (int i = 0; i < ParameterTypes.Length; i++) {
GenericConstraints ogc = pd.GenericConstraints (i);
}
if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0) {
- Report.SymbolRelatedToPreviousError (conflict_symbol);
- Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
- }
+ Report.SymbolRelatedToPreviousError (conflict_symbol);
+ Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
+ }
return true;
}
MemberType = texpr.Type;
+ ec.InUnsafe = old_unsafe;
+
if (MemberType == TypeManager.void_type) {
Report.Error (1547, Location, "Keyword 'void' cannot be used in this context");
return false;
}
- ec.InUnsafe = old_unsafe;
-
if (!CheckBase ())
return false;
}
#endif
+ protected override bool CheckBase ()
+ {
+ // Constant.Define can be called when the parent type hasn't yet been populated
+ // and it's base types need not have been populated. So, we defer this check
+ // to the second time Define () is called on this member.
+ if (Parent.BaseCache == null)
+ return true;
+ return base.CheckBase ();
+ }
+
/// <summary>
/// Defines the constant in the @parent
/// </summary>
public override bool Define ()
{
+ // Make Define () idempotent, but ensure that the error check happens.
+ if (FieldBuilder != null)
+ return base.CheckBase ();
+
if (!base.Define ())
return false;
}
Expr = ce;
}
- ConstantValue = ce.GetValue ();
+
+ if (ce != null)
+ ConstantValue = ce.GetValue ();
if (MemberType.IsEnum){
//
//
Type source_type = source.Type;
foreach (MethodBase mb in me.Methods){
- ParameterData pd = Invocation.GetParameterData (mb);
+ ParameterData pd = TypeManager.GetParameterData (mb);
Type param_type = pd.ParameterType (0);
if (param_type == source_type)
foreach (MethodBase mb in union.Methods){
- ParameterData pd = Invocation.GetParameterData (mb);
+ ParameterData pd = TypeManager.GetParameterData (mb);
MethodInfo mi = (MethodInfo) mb;
if (pd.ParameterType (0) == most_specific_source &&
: USING IDENTIFIER ASSIGN
namespace_or_type_name SEMICOLON
{
- current_namespace.UsingAlias ((string) $2, (MemberName) $4, lexer.Location);
+ MemberName name = (MemberName) $4;
+ current_namespace.UsingAlias ((string) $2, name.GetTypeExpression (lexer.Location), lexer.Location);
}
| USING error {
CheckIdentifierToken (yyToken);
using_namespace_directive
: USING namespace_name SEMICOLON
{
- current_namespace.Using ((string) $2, lexer.Location);
+ MemberName ns_name = (MemberName) $2;
+ current_namespace.Using (ns_name.GetTypeExpression (lexer.Location), lexer.Location);
}
;
if (name.TypeArguments != null)
syntax_error (lexer.Location, "namespace name expected");
- $$ = name.GetName ();
+ $$ = name;
}
;
}
opt_attribute_arguments
{
+ Location loc = (Location) $2;
MemberName mname = (MemberName) $1;
if (mname.IsGeneric) {
Report.Error (404, lexer.Location,
"'<' unexpected: attributes cannot be generic");
}
- string name = mname.GetName ();
+ MemberName left = mname.Left;
+ string identifier = mname.Name;
+
+ Expression left_expr = left == null ? null : left.GetTypeExpression (loc);
+
if (current_attr_target == "assembly" || current_attr_target == "module")
$$ = new GlobalAttribute (current_container, current_attr_target,
- name, (ArrayList) $3, (Location) $2);
+ left_expr, identifier, (ArrayList) $3, loc);
else
- $$ = new Attribute (current_attr_target, name, (ArrayList) $3,
- (Location) $2);
+ $$ = new Attribute (current_attr_target, left_expr, identifier, (ArrayList) $3, loc);
}
;
TypeAttributes attr = Modifiers.TypeAttr (ModFlags, IsTopLevel) |
TypeAttributes.Class | TypeAttributes.Sealed;
+ if (TypeManager.multicast_delegate_type == null && !RootContext.StdLib) {
+ TypeExpr expr = new TypeLookupExpression ("System.MulticastDelegate");
+ TypeManager.multicast_delegate_type = expr.ResolveType (ec);
+ }
+
if (TypeManager.multicast_delegate_type == null)
Report.Error (-100, Location, "Internal error: delegate used before " +
"System.MulticastDelegate is resolved. This can only " +
{
MethodAttributes mattr;
int i;
- ec = new EmitContext (this, this, Location, null, null, ModFlags, false);
if (IsGeneric) {
foreach (TypeParameter type_param in TypeParameters)
type_param.DefineType (ec);
}
+ if (ec == null)
+ throw new InternalErrorException ("Define called before DefineType?");
+
// FIXME: POSSIBLY make this static, as it is always constant
//
Type [] const_arg_types = new Type [2];
return null;
MethodBase invoke_mb = mg.Methods [0];
- ParameterData invoke_pd = Invocation.GetParameterData (invoke_mb);
+ ParameterData invoke_pd = TypeManager.GetParameterData (invoke_mb);
if (!mg.HasTypeArguments &&
!TypeManager.InferTypeArguments (ec, invoke_pd, ref mb))
return null;
- ParameterData pd = Invocation.GetParameterData (mb);
- int pd_count = pd.Count;
+ ParameterData pd = TypeManager.GetParameterData (mb);
- if (invoke_pd.Count != pd_count)
+ if (invoke_pd.Count != pd.Count)
return null;
- for (int i = pd_count; i > 0; ) {
+ for (int i = pd.Count; i > 0; ) {
i--;
Type invoke_pd_type = invoke_pd.ParameterType (i);
}
MethodBase mb = ((MethodGroupExpr) ml).Methods [0];
- ParameterData pd = Invocation.GetParameterData (mb);
+ ParameterData pd = TypeManager.GetParameterData (mb);
int pd_count = pd.Count;
}
MethodBase mb = ((MethodGroupExpr) ml).Methods [0];
- ParameterData pd = Invocation.GetParameterData (mb);
+ ParameterData pd = TypeManager.GetParameterData (mb);
Expression probe_ml = Expression.MemberLookup (
ec, delegate_type, "Invoke", loc);
}
MethodBase probe_mb = ((MethodGroupExpr) probe_ml).Methods [0];
- ParameterData probe_pd = Invocation.GetParameterData (probe_mb);
+ ParameterData probe_pd = TypeManager.GetParameterData (probe_mb);
if (((MethodInfo) mb).ReturnType != ((MethodInfo) probe_mb).ReturnType)
return false;
ec, type, "Invoke", MemberTypes.Method,
Expression.AllBindingFlags, loc);
MethodBase method = ((MethodGroupExpr) invoke_method).Methods [0];
- ParameterData param = Invocation.GetParameterData (method);
+ ParameterData param = TypeManager.GetParameterData (method);
string delegate_desc = Delegate.FullDelegateDesc (type, method, param);
if (!mg.HasTypeArguments &&
protected Expression ResolveMethodGroupExpr (EmitContext ec, MethodGroupExpr mg)
{
- foreach (MethodInfo mi in mg.Methods){
- delegate_method = Delegate.VerifyMethod (
- ec, type, mi, loc);
-
- if (delegate_method != null)
- break;
- }
-
- if (delegate_method == null) {
- Error_NoMatchingMethodForDelegate (ec, mg, type, loc);
- return null;
- }
-
- //
- // Check safe/unsafe of the delegate
- //
- if (!ec.InUnsafe){
- ParameterData param = Invocation.GetParameterData (delegate_method);
- int count = param.Count;
-
- for (int i = 0; i < count; i++){
- if (param.ParameterType (i).IsPointer){
- Expression.UnsafeError (loc);
- return null;
- }
+ foreach (MethodInfo mi in mg.Methods){
+ delegate_method = Delegate.VerifyMethod (ec, type, mi, loc);
+
+ if (delegate_method != null)
+ break;
+ }
+
+ if (delegate_method == null) {
+ Error_NoMatchingMethodForDelegate (ec, mg, type, loc);
+ return null;
+ }
+
+ //
+ // Check safe/unsafe of the delegate
+ //
+ if (!ec.InUnsafe){
+ ParameterData param = TypeManager.GetParameterData (delegate_method);
+ int count = param.Count;
+
+ for (int i = 0; i < count; i++){
+ if (param.ParameterType (i).IsPointer){
+ Expression.UnsafeError (loc);
+ return null;
}
}
+ }
//TODO: implement caching when performance will be low
IMethodData md = TypeManager.GetMethod (delegate_method);
" -nostdlib[+|-] Does not load core libraries\n" +
" -nowarn:W1[,W2] Disables one or more warnings\n" +
" -out:FNAME Specifies output file\n" +
- " -doc:XMLFILE Generates xml documentation into specified file\n" +
" -pkg:P1[,Pn] References packages P1..Pn\n" +
" --expect-error X Expect that error X will be encountered\n" +
" -recurse:SPEC Recursively compiles the files in SPEC ([dir]/file)\n" +
sb.Append (valid [i]);
}
- Error (119, "Expression denotes a `" + ExprClassName () + "' where " +
+ Report.Error (119, loc, "Expression denotes a `" + ExprClassName () + "' where " +
"a `" + sb.ToString () + "' was expected");
}
/// section 10.8.1 (Fully Qualified Names).
/// </summary>
public abstract class FullNamedExpression : Expression {
+ public override FullNamedExpression ResolveAsTypeStep (EmitContext ec)
+ {
+ return this;
+ }
+
public abstract string FullName {
get;
}
}
IVariable variable = Expr as IVariable;
- if (!ec.InFixedInitializer && ((variable == null) || !variable.VerifyFixed (false))) {
+ bool is_fixed = variable != null && variable.VerifyFixed (false);
+
+ if (!ec.InFixedInitializer && !is_fixed) {
Error (212, "You can only take the address of an unfixed expression inside " +
"of a fixed statement initializer");
return null;
}
- if (ec.InFixedInitializer && ((variable != null) && variable.VerifyFixed (false))) {
+ if (ec.InFixedInitializer && is_fixed) {
Error (213, "You can not fix an already fixed expression");
return null;
}
// after semantic analysis (this is so we can take the address
// of an indirection).
//
- public class Indirection : Expression, IMemoryLocation, IAssignMethod {
+ public class Indirection : Expression, IMemoryLocation, IAssignMethod, IVariable {
Expression expr;
LocalTemporary temporary;
bool prepared;
{
return "*(" + expr + ")";
}
+
+ #region IVariable Members
+
+ public VariableInfo VariableInfo {
+ get {
+ return null;
+ }
+ }
+
+ public bool VerifyFixed (bool is_expression)
+ {
+ return true;
+ }
+
+ #endregion
}
/// <summary>
//
left.Emit (ec);
ig.Emit (OpCodes.Conv_I);
- right.Emit (ec);
- if (size != 1){
- if (size == 0)
- ig.Emit (OpCodes.Sizeof, element);
- else
- IntLiteral.EmitInt (ig, size);
- if (rtype == TypeManager.int64_type)
- ig.Emit (OpCodes.Conv_I8);
- else if (rtype == TypeManager.uint64_type)
- ig.Emit (OpCodes.Conv_U8);
- ig.Emit (OpCodes.Mul);
+
+ Constant right_const = right as Constant;
+ if (right_const != null && size != 0) {
+ Expression ex = ConstantFold.BinaryFold (ec, Binary.Operator.Multiply, new IntConstant (size), right_const, loc);
+ if (ex == null)
+ return;
+ ex.Emit (ec);
+ } else {
+ right.Emit (ec);
+ if (size != 1){
+ if (size == 0)
+ ig.Emit (OpCodes.Sizeof, element);
+ else
+ IntLiteral.EmitInt (ig, size);
+ if (rtype == TypeManager.int64_type)
+ ig.Emit (OpCodes.Conv_I8);
+ else if (rtype == TypeManager.uint64_type)
+ ig.Emit (OpCodes.Conv_U8);
+ ig.Emit (OpCodes.Mul);
+ }
}
if (rtype == TypeManager.int64_type || rtype == TypeManager.uint64_type)
Expression expr;
MethodBase method = null;
- static Hashtable method_parameter_cache;
-
- static Invocation ()
- {
- method_parameter_cache = new PtrHashtable ();
- }
-
//
// arguments is an ArrayList, but we do not want to typecast,
// as it might be null.
}
}
- /// <summary>
- /// Returns the Parameters (a ParameterData interface) for the
- /// Method `mb'
- /// </summary>
- public static ParameterData GetParameterData (MethodBase mb)
- {
- object pd = method_parameter_cache [mb];
- object ip;
-
- if (pd != null)
- return (ParameterData) pd;
-
- ip = TypeManager.LookupParametersByBuilder (mb);
- if (ip != null){
- method_parameter_cache [mb] = ip;
-
- return (ParameterData) ip;
- } else {
- ReflectionParameters rp = new ReflectionParameters (mb);
- method_parameter_cache [mb] = rp;
-
- return (ParameterData) rp;
- }
- }
-
/// <summary>
/// Determines "better conversion" as specified in 7.4.2.3
///
MethodBase candidate, bool candidate_params,
MethodBase best, bool best_params, Location loc)
{
- ParameterData candidate_pd = GetParameterData (candidate);
- ParameterData best_pd = GetParameterData (best);
+ ParameterData candidate_pd = TypeManager.GetParameterData (candidate);
+ ParameterData best_pd = TypeManager.GetParameterData (best);
int cand_count = candidate_pd.Count;
sb.Append (".");
sb.Append (mb.Name);
- ParameterData pd = GetParameterData (mb);
+ ParameterData pd = TypeManager.GetParameterData (mb);
int count = pd.Count;
sb.Append (" (");
int arg_count, MethodBase candidate,
bool do_varargs)
{
- ParameterData pd = GetParameterData (candidate);
+ ParameterData pd = TypeManager.GetParameterData (candidate);
int pd_count = pd.Count;
static bool IsApplicable (EmitContext ec, ArrayList arguments, int arg_count,
MethodBase candidate)
{
- ParameterData pd = GetParameterData (candidate);
+ ParameterData pd = TypeManager.GetParameterData (candidate);
if (arg_count != pd.Count)
return false;
//
for (int i = 0; i < methods.Length; ++i) {
MethodBase c = (MethodBase) methods [i];
- ParameterData pd = GetParameterData (c);
+ ParameterData pd = TypeManager.GetParameterData (c);
if (pd.Count != arg_count)
continue;
for (int i = 0; i < methods.Length; ++i) {
MethodBase c = methods [i];
- ParameterData pd = GetParameterData (c);
+ ParameterData pd = TypeManager.GetParameterData (c);
if (pd.Count != arg_count)
continue;
Type delegate_type, bool may_fail,
Location loc)
{
- ParameterData pd = GetParameterData (method);
+ ParameterData pd = TypeManager.GetParameterData (method);
int pd_count = pd.Count;
for (int j = 0; j < arg_count; j++) {
{
ParameterData pd;
if (mb != null)
- pd = GetParameterData (mb);
+ pd = TypeManager.GetParameterData (mb);
else
pd = null;
static Type[] GetVarargsTypes (EmitContext ec, MethodBase mb,
ArrayList arguments)
{
- ParameterData pd = GetParameterData (mb);
+ ParameterData pd = TypeManager.GetParameterData (mb);
if (arguments == null)
return new Type [0];
object real_value = ((Constant) c.Expr).GetValue ();
- return Constantify (real_value, t);
+ Expression exp = Constantify (real_value, t);
+
+ if (left_is_explicit && !left_is_type && !IdenticalNameAndTypeName (ec, left_original, left, loc)) {
+ Report.SymbolRelatedToPreviousError (c);
+ error176 (loc, c.GetSignatureForError ());
+ return null;
+ }
+
+ return exp;
}
}
}
public override FullNamedExpression ResolveAsTypeStep (EmitContext ec)
+ {
+ return ResolveNamespaceOrType (ec, false);
+ }
+
+ public FullNamedExpression ResolveNamespaceOrType (EmitContext ec, bool silent)
{
FullNamedExpression new_expr = expr.ResolveAsTypeStep (ec);
FullNamedExpression retval = ns.Lookup (ec.DeclSpace, lookup_id, loc);
if ((retval != null) && (args != null))
retval = new ConstructedType (retval, args, loc).ResolveAsTypeStep (ec);
- if (retval == null)
+ if (!silent && retval == null)
Report.Error (234, loc, "The type or namespace name `{0}' could not be found in namespace `{1}'", Identifier, ns.FullName);
return retval;
}
Expression member_lookup;
member_lookup = MemberLookupFinal (ec, expr_type, expr_type, lookup_id, loc);
- if (member_lookup == null) {
+ if (!silent && member_lookup == null) {
Report.Error (234, loc, "The type name `{0}' could not be found in type `{1}'",
Identifier, new_expr.FullName);
return null;
mb = mb.GetGenericMethodDefinition ();
int pos = type.GenericParameterPosition;
- ParameterData pd = Invocation.GetParameterData (mb);
+ ParameterData pd = TypeManager.GetParameterData (mb);
GenericConstraints temp_gc = pd.GenericConstraints (pos);
Type mparam = mb.GetGenericArguments () [pos];
else
arg_count = arguments.Count;
- ParameterData pd = Invocation.GetParameterData (method);
+ ParameterData pd = TypeManager.GetParameterData (method);
int pd_count = pd.Count;
else
arg_count = 0;
- ParameterData pd = Invocation.GetParameterData (method);
+ ParameterData pd = TypeManager.GetParameterData (method);
if (arg_count != pd.Count)
return false;
if (!TypeManager.IsGenericMethod (method))
return true;
- ParameterData pd = Invocation.GetParameterData (method);
+ ParameterData pd = TypeManager.GetParameterData (method);
if (apd.Count != pd.Count)
return false;
/// in 8 bits (and say, map anything after char 255 to be `255+').
/// </remarks>
public struct Location {
- public int token;
+ int token;
static ArrayList source_list;
static Hashtable source_files;
string path = Path.GetFullPath (name);
if (source_files.Contains (path)){
- Report.Warning (2002, name, "Source file '{0}' specified multiple times", path);
+ int id = (int) source_files [path];
+ string other_name = ((SourceFile) source_list [id - 1]).Name;
+ if (name.Equals (other_name))
+ Report.Warning (2002, "Source file '{0}' specified multiple times", name);
+ else
+ Report.Warning (2002, "Source filenames '{0}' and '{1}' both refer to the same file: {2}", name, other_name, path);
return;
}
// exist.
//
public class UsingEntry {
- public readonly string Name;
+ public Expression Name;
public readonly NamespaceEntry NamespaceEntry;
public readonly Location Location;
- public UsingEntry (NamespaceEntry entry, string name, Location loc)
+ public UsingEntry (NamespaceEntry entry, Expression name, Location loc)
{
Name = name;
NamespaceEntry = entry;
Location = loc;
}
- Namespace resolved_ns;
+ internal FullNamedExpression resolved;
public Namespace Resolve ()
{
- if (resolved_ns != null)
- return resolved_ns;
+ if (resolved != null)
+ return resolved as Namespace;
+
+ DeclSpace root = RootContext.Tree.Types;
+ root.NamespaceEntry = NamespaceEntry;
+ resolved = Name.ResolveAsTypeStep (root.EmitContext);
+ root.NamespaceEntry = null;
- FullNamedExpression resolved = NamespaceEntry.LookupForUsing (Name, Location);
- resolved_ns = resolved as Namespace;
- return resolved_ns;
+ return resolved as Namespace;
}
}
public class AliasEntry {
public readonly string Name;
- public readonly MemberName Alias;
+ public readonly Expression Alias;
public readonly NamespaceEntry NamespaceEntry;
public readonly Location Location;
- public AliasEntry (NamespaceEntry entry, string name, MemberName alias, Location loc)
+ public AliasEntry (NamespaceEntry entry, string name, Expression alias, Location loc)
{
Name = name;
Alias = alias;
if (resolved != null)
return resolved;
- //
- // GENERICS: Cope with the expression and not with the string
- // this will fail with `using A = Stack<int>'
- //
-
- string alias = Alias.GetTypeName ();
-
- resolved = NamespaceEntry.LookupForUsing (alias, Location);
- if (resolved == null)
- return null;
-
- if (Alias.TypeArguments == null)
- return resolved;
-
- EmitContext ec = RootContext.Tree.Types.EmitContext;
- resolved = new TypeAliasExpression (resolved, Alias.TypeArguments, Location);
- resolved = resolved.ResolveAsTypeStep (ec);
+ DeclSpace root = RootContext.Tree.Types;
+ root.NamespaceEntry = NamespaceEntry;
+ resolved = Alias.ResolveAsTypeStep (root.EmitContext);
+ root.NamespaceEntry = null;
return resolved;
}
}
public NamespaceEntry (NamespaceEntry parent, SourceFile file, string name, Location loc)
- : this (parent, file, name, false, loc)
- { }
-
- protected NamespaceEntry (NamespaceEntry parent, SourceFile file, string name, bool is_implicit, Location loc)
{
this.parent = parent;
this.file = file;
- this.IsImplicit = is_implicit;
+ this.IsImplicit = false;
this.ID = ++next_id;
- if (!is_implicit && (parent != null))
+ if (parent != null)
ns = parent.NS.GetNamespace (name, true);
else if (name != null)
ns = Namespace.LookupNamespace (name, true);
else
ns = Namespace.Root;
ns.AddNamespaceEntry (this);
+ this.FullName = ns.Name;
+ }
- if ((parent != null) && (parent.NS != ns.Parent))
- implicit_parent = new NamespaceEntry (parent, file, ns.Parent.Name, true, loc);
- else
- implicit_parent = parent;
+ private NamespaceEntry (NamespaceEntry parent, SourceFile file, Namespace ns)
+ {
+ this.parent = parent;
+ this.file = file;
+ this.IsImplicit = true;
+ this.ID = ++next_id;
+ this.ns = ns;
this.FullName = ns.Name;
}
+ //
+ // According to section 16.3.1 (using-alias-directive), the namespace-or-type-name is
+ // resolved as if the immediately containing namespace body has no using-directives.
+ //
+ // Section 16.3.2 says that the same rule is applied when resolving the namespace-name
+ // in the using-namespace-directive.
+ //
+ // To implement these rules, the expressions in the using directives are resolved using
+ // the "doppelganger" (ghostly bodiless duplicate).
+ //
+ NamespaceEntry doppelganger;
+ NamespaceEntry Doppelganger {
+ get {
+ if (!IsImplicit && doppelganger == null)
+ doppelganger = new NamespaceEntry (ImplicitParent, file, ns);
+ return doppelganger;
+ }
+ }
+
static int next_id = 0;
public readonly string FullName;
public readonly int ID;
public NamespaceEntry ImplicitParent {
get {
+ if (parent == null)
+ return null;
+ if (implicit_parent == null) {
+ implicit_parent = (parent.NS == ns.Parent)
+ ? parent
+ : new NamespaceEntry (parent, file, ns.Parent);
+ }
return implicit_parent;
}
}
/// <summary>
/// Records a new namespace for resolving name references
/// </summary>
- public void Using (string ns, Location loc)
+ public void Using (Expression ns, Location loc)
{
+ string name = ns.ToString ();
if (DeclarationFound){
Report.Error (1529, loc, "A using clause must precede all other namespace elements");
return;
}
- if (ns == FullName)
+ if (name == FullName)
return;
if (using_clauses == null)
using_clauses = new ArrayList ();
foreach (UsingEntry old_entry in using_clauses) {
- if (old_entry.Name == ns) {
+ if (old_entry.Name.ToString () == name) {
if (RootContext.WarningLevel >= 3)
- Report.Warning (105, loc, "The using directive for '{0}' appeared previously in this namespace", ns);
+ Report.Warning (105, loc, "The using directive for '{0}' appeared previously in this namespace", name);
return;
}
}
-
- UsingEntry ue = new UsingEntry (this, ns, loc);
+
+
+ UsingEntry ue = new UsingEntry (Doppelganger, ns, loc);
using_clauses.Add (ue);
}
- public void UsingAlias (string name, MemberName alias, Location loc)
+ public void UsingAlias (string name, Expression alias, Location loc)
{
if (DeclarationFound){
Report.Error (1529, loc, "A using clause must precede all other namespace elements");
return;
}
- aliases [name] = new AliasEntry (this, name, alias, loc);
+ aliases [name] = new AliasEntry (Doppelganger, name, alias, loc);
}
public FullNamedExpression LookupAlias (string alias)
return entry == null ? null : entry.Resolve ();
}
- //
- // According to section 16.3.1 (using-alias-directive), the namespace-or-type-name is
- // resolved as if the immediately containing namespace body has no using-directives.
- //
- // Section 16.3.2 says that the same rule is applied when resolving the namespace-name
- // in the using-namespace-directive.
- //
- public FullNamedExpression LookupForUsing (string dotted_name, Location loc)
+ public FullNamedExpression LookupNamespaceOrType (DeclSpace ds, string name, Location loc)
{
- int pos = dotted_name.IndexOf ('.');
- string simple_name = dotted_name;
+ FullNamedExpression resolved = null;
string rest = null;
+
+ // If name is of the form `N.I', first lookup `N', then search a member `I' in it.
+ int pos = name.IndexOf ('.');
if (pos >= 0) {
- simple_name = dotted_name.Substring (0, pos);
- rest = dotted_name.Substring (pos + 1);
+ rest = name.Substring (pos + 1);
+ name = name.Substring (0, pos);
}
- FullNamedExpression o = NS.Lookup (null, simple_name, loc);
- if (o == null && ImplicitParent != null)
- o = ImplicitParent.LookupNamespaceOrType (null, simple_name, loc);
+ for (NamespaceEntry curr_ns = this; curr_ns != null; curr_ns = curr_ns.ImplicitParent) {
+ if ((resolved = curr_ns.Lookup (ds, name, loc)) != null)
+ break;
+ }
- if (o == null || rest == null)
- return o;
+ if (resolved == null || rest == null)
+ return resolved;
- Namespace ns = o as Namespace;
+ Namespace ns = resolved as Namespace;
if (ns != null)
- return ns.Lookup (null, rest, loc);
-
- Type nested = TypeManager.LookupType (o.FullName + "." + rest);
- if (nested == null)
+ return ns.Lookup (ds, rest, loc);
+
+ Type nested = TypeManager.LookupType (resolved.FullName + "." + rest);
+ if ((nested == null) || ((ds != null) && !ds.CheckAccessLevel (nested)))
return null;
return new TypeExpression (nested, Location.Null);
}
- public FullNamedExpression LookupNamespaceOrType (DeclSpace ds, string name, Location loc)
- {
- FullNamedExpression resolved = null;
- for (NamespaceEntry curr_ns = this; curr_ns != null; curr_ns = curr_ns.ImplicitParent) {
- if ((resolved = curr_ns.Lookup (ds, name, loc)) != null)
- break;
- }
- return resolved;
- }
-
private FullNamedExpression Lookup (DeclSpace ds, string name, Location loc)
{
- FullNamedExpression o;
- Namespace ns;
-
- //
- // If name is of the form `N.I', first lookup `N', then search a member `I' in it.
- //
- // FIXME: Remove this block. Only simple names should come here.
- // The bug: The loop in LookupNamespaceOrType continues if
- // the lookup for N succeeds but the nested lookup for I fails.
- // This is one part of #52697.
- //
- int pos = name.IndexOf ('.');
- if (pos >= 0) {
- string first = name.Substring (0, pos);
- string last = name.Substring (pos + 1);
-
- o = Lookup (ds, first, loc);
- if (o == null)
- return null;
-
- ns = o as Namespace;
- if (ns != null) {
- o = ns.Lookup (ds, last, loc);
- return o;
- }
-
- Type nested = TypeManager.LookupType (o.FullName + "." + last);
- if ((nested == null) || ((ds != null) && !ds.CheckAccessLevel (nested)))
- return null;
-
- return new TypeExpression (nested, Location.Null);
- }
+ // Precondition: Only simple names (no dots) will be looked up with this function.
//
// Check whether it's in the namespace.
//
- o = NS.Lookup (ds, name, loc);
+ FullNamedExpression o = NS.Lookup (ds, name, loc);
if (o != null)
return o;
+ if (IsImplicit)
+ return null;
+
//
// Check aliases.
//
if (o != null)
return o;
- if (name.IndexOf ('.') > 0)
- return null;
-
//
// Check using entries.
//
if (using_clauses != null) {
using_list = new string [using_clauses.Count];
for (int i = 0; i < using_clauses.Count; i++)
- using_list [i] = ((UsingEntry) using_clauses [i]).Name;
+ using_list [i] = ((UsingEntry) using_clauses [i]).Name.ToString ();
} else {
using_list = new string [0];
}
if (ue.Resolve () != null)
continue;
- if (LookupForUsing (ue.Name, ue.Location) == null)
- error246 (ue.Location, ue.Name);
+ if (ue.resolved == null)
+ error246 (ue.Location, ue.Name.ToString ());
else
Report.Error (138, ue.Location, "The using keyword only lets you specify a namespace, " +
"`" + ue.Name + "' is a class not a namespace.");
if (alias.Resolve () != null)
continue;
- error246 (alias.Location, alias.Alias.GetTypeName ());
+ error246 (alias.Location, alias.Alias.ToString ());
}
}
}
CallingConventions.Standard | CallingConventions.HasThis,
base_method.ReturnType, args);
- ParameterData pd = Invocation.GetParameterData (iface_method);
+ ParameterData pd = TypeManager.GetParameterData (iface_method);
proxy.DefineParameter (0, ParameterAttributes.None, "");
for (int i = 0; i < pd.Count; i++) {
string name = pd.ParameterName (i);
// These are classes that depends on the core interfaces
//
string [] classes_second_stage = {
+ "System.Enum",
+ "System.String",
+ "System.Array",
"System.Reflection.MemberInfo",
"System.Type",
"System.Exception",
"System.Security.CodeAccessPermission"
};
- // We must store them here before calling BootstrapCorlib_ResolveDelegate.
- TypeManager.string_type = BootstrapCorlib_ResolveClass (root, "System.String");
- TypeManager.enum_type = BootstrapCorlib_ResolveClass (root, "System.Enum");
- TypeManager.array_type = BootstrapCorlib_ResolveClass (root, "System.Array");
- TypeManager.multicast_delegate_type = BootstrapCorlib_ResolveClass (root, "System.MulticastDelegate");
- TypeManager.delegate_type = BootstrapCorlib_ResolveClass (root, "System.Delegate");
-
foreach (string cname in classes_second_stage)
BootstrapCorlib_ResolveClass (root, cname);
BootstrapCorlib_ResolveStruct (root, "System.Nullable`1");
BootstrapCorlib_ResolveDelegate (root, "System.AsyncCallback");
+
+ // These will be defined indirectly during the previous ResolveDelegate.
+ // However make sure the rest of the checks happen.
+ string [] delegate_types = { "System.Delegate", "System.MulticastDelegate" };
+ foreach (string cname in delegate_types)
+ BootstrapCorlib_ResolveClass (root, cname);
}
// <summary>
label.AddUsageVector (ec.CurrentBranching.CurrentUsageVector);
ec.CurrentBranching.CurrentUsageVector.Goto ();
+ label.AddReference ();
return true;
}
{
ec.CurrentBranching.Label (vectors);
- referenced = true;
-
return true;
}
LabelTarget (ec);
ec.ig.MarkLabel (label);
}
+
+ public void AddReference ()
+ {
+ referenced = true;
+ }
}
if (mb.Mono_IsInflatedMethod) {
MethodInfo generic = mb.GetGenericMethodDefinition ();
- gpd = Invocation.GetParameterData (generic);
+ gpd = TypeManager.GetParameterData (generic);
last_arg_is_params = gpd.HasParams;
return;
static Hashtable indexer_arguments;
// <remarks>
- // Maybe `method_arguments' should be replaced and only
- // method_internal_params should be kept?
+ // Maps a MethodBase to its ParameterData (either InternalParameters or ReflectionParameters)
// <remarks>
- static Hashtable method_internal_params;
+ static Hashtable method_params;
// <remarks>
// Keeps track of methods
builder_to_ifaces = null;
method_arguments = null;
indexer_arguments = null;
- method_internal_params = null;
+ method_params = null;
builder_to_method = null;
fields = null;
builder_to_member_cache = new PtrHashtable ();
builder_to_method = new PtrHashtable ();
method_arguments = new PtrHashtable ();
- method_internal_params = new PtrHashtable ();
+ method_params = new PtrHashtable ();
indexer_arguments = new PtrHashtable ();
builder_to_ifaces = new PtrHashtable ();
MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true);
string signature = GetFullNameSignature (mb);
- string arg = TypeManager.LookupParametersByBuilder (mb).ParameterDesc (0);
+ string arg = GetParameterData (mb).ParameterDesc (0);
return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg);
}
{
StringBuilder sig = new StringBuilder ("(");
- //
- // FIXME: We should really have a single function to do
- // everything instead of the following 5 line pattern
- //
- ParameterData iparams = LookupParametersByBuilder (mb);
+ ParameterData iparams = GetParameterData (mb);
- if (iparams == null)
- iparams = new ReflectionParameters (mb);
-
// Is property
if (mb.IsSpecialName && iparams.Count == 0 && !mb.IsConstructor)
return GetFullNameSignature (mb);
args = NoTypes;
method_arguments.Add (mb, args);
- method_internal_params.Add (mb, ip);
+ method_params.Add (mb, ip);
}
- static public InternalParameters LookupParametersByBuilder (MethodBase mb)
+ static public ParameterData GetParameterData (MethodBase mb)
{
- if (! (mb is ConstructorBuilder || mb is MethodBuilder))
- return null;
-
- if (method_internal_params.Contains (mb))
- return (InternalParameters) method_internal_params [mb];
- else
- throw new Exception ("Argument for Method not registered" + mb);
+ object pd = method_params [mb];
+ if (pd == null) {
+ if (mb is MethodBuilder || mb is ConstructorBuilder)
+ throw new InternalErrorException ("Argument for Method not registered" + mb);
+
+ method_params [mb] = pd = new ReflectionParameters (mb);
+ }
+
+ return (ParameterData) pd;
}
/// <summary>
+2005-04-08 Marek Safar <marek.safar@seznam.cz>
+
+ * attribute.cs (Attribute.IsValidArgumentType): Test valid named
+ argument types.
+ (Attribute.Resolve): Add named argument type checking.
+
+ * class.cs (FixedField.Define): Use IsPrimitiveType
+
+ * expression.cs (Binary.ResolveOperator): Reflect IsCLRType renaming.
+
+ * iterators.cs (Iterator.DefineIterator): Add check for arglist and
+ unsafe parameter types.
+
+ * statement.cs (Using.ResolveExpression): Add better error description.
+
+ * typemanager.cs (IsCLRType): Renamed to IsPrimitiveType.
+
+2005-04-08 Raja R Harinath <rharinath@novell.com>
+
+ Fix #74484.
+ * attribute.cs (Attribute.GetAttributeUsage): Resolve
+ AttributeUsageAttribute in the emitcontext of the attribute class,
+ not in the emitcontext of the attributable entity it was attached to.
+ * cs-parser.jay: Use 'current_class', not 'current_container',
+ when creating a GlobalAttribute.
+
+2005-04-08 Alp Toker <alp@atoker.com>
+
+ * pending.cs: The fix to #58413 failed to compile methods implementing
+ interfaces with/without params modifiers and vice versa, even though
+ params modifiers aren't part of the signature. Make the modifier check
+ less strict as in csc.
+
+2005-04-07 Abin Thomas <projectmonokochi@rediffmail.com>
+ Anoob V E <projectmonokochi@rediffmail.com>
+ Harilal P R <projectmonokochi@rediffmail.com>
+
+ Fix #58413.
+ * pending.cs (TypeAndMethods.mods): New. Store the parameter
+ modifiers of pending methods.
+ (PendingImplementation.PendingImplementation): Initialize it.
+ Add Parameter.Modifier [][] mods and initialize it with ParameterData.
+ (PendingImplementation.InterFaceMethod): Repalce Type[] argument
+ with ParameterData. Add check for modifiers.
+ * class.cs (MethodData.Define): Update to changes.
+
+2005-04-07 Raja R Harinath <rharinath@novell.com>
+
+ * ecore.cs (Expression.IsAccessorAccessible): Clarify code somewhat.
+
2005-04-07 Marek Safar <marek.safar@seznam.cz>
* class.cs (PropertyMethod.Define): Check private accessor in abstract
name);
}
+ void Error_InvalidNamedAgrumentType (string name)
+ {
+ Report.Error (655, Location, "'{0}' is not a valid named attribute argument because its type is not valid attribute type", name);
+ }
+
static void Error_AttributeArgumentNotValid (string extra, Location loc)
{
Report.Error (182, loc,
Error_AttributeArgumentNotValid (loc);
return false;
}
-
+
+ bool IsValidArgumentType (Type t)
+ {
+ return TypeManager.IsPrimitiveType (t) ||
+ (t.IsArray && TypeManager.IsPrimitiveType (t.GetElementType ())) ||
+ TypeManager.IsEnumType (t) ||
+ t == TypeManager.string_type ||
+ t == TypeManager.object_type ||
+ t == TypeManager.type_type;
+ }
+
// Cache for parameter-less attributes
static PtrHashtable att_cache = new PtrHashtable ();
return null;
}
+ if (!IsValidArgumentType (pi.PropertyType)) {
+ Report.SymbolRelatedToPreviousError (pi);
+ Error_InvalidNamedAgrumentType (member_name);
+ return null;
+ }
+
object value;
if (!GetAttributeArgumentExpression (e, Location, pi.PropertyType, out value))
return null;
return null;
}
+ if (!IsValidArgumentType (fi.FieldType)) {
+ Report.SymbolRelatedToPreviousError (fi);
+ Error_InvalidNamedAgrumentType (member_name);
+ return null;
+ }
+
object value;
if (!GetAttributeArgumentExpression (e, Location, fi.FieldType, out value))
return null;
}
object value = pos_values [j];
- if (value != null && a.Type != value.GetType () && a.Type.IsPrimitive) {
+ if (value != null && a.Type != value.GetType () && TypeManager.IsPrimitiveType (a.Type)) {
bool fail;
pos_values [j] = TypeManager.ChangeType (value, a.Type, out fail);
if (fail) {
return ua;
}
- if (attr_class.OptAttributes == null) {
- usage_attr_cache.Add (Type, DefaultUsageAttribute);
- return DefaultUsageAttribute;
- }
+ Attribute a = attr_class.OptAttributes == null
+ ? null
+ : attr_class.OptAttributes.Search (TypeManager.attribute_usage_type, attr_class.EmitContext);
- Attribute a = attr_class.OptAttributes.Search (TypeManager.attribute_usage_type, ec);
- if (a == null) {
- usage_attr_cache.Add (Type, DefaultUsageAttribute);
- return DefaultUsageAttribute;
- }
+ ua = a == null
+ ? DefaultUsageAttribute
+ : a.GetAttributeUsageAttribute (attr_class.EmitContext);
- ua = a.GetAttributeUsageAttribute (ec);
usage_attr_cache.Add (Type, ua);
return ua;
}
if (container.Pending != null){
if (member is Indexer) // TODO: test it, but it should work without this IF
implementing = container.Pending.IsInterfaceIndexer (
- member.InterfaceType, method.ReturnType, ParameterTypes);
+ member.InterfaceType, method.ReturnType, ParameterInfo);
else
implementing = container.Pending.IsInterfaceMethod (
- member.InterfaceType, name, method.ReturnType, ParameterTypes);
+ member.InterfaceType, name, method.ReturnType, ParameterInfo);
if (member.InterfaceType != null){
if (implementing == null){
if (member is Indexer) {
container.Pending.ImplementIndexer (
member.InterfaceType, builder, method.ReturnType,
- ParameterTypes, member.IsExplicitImpl);
+ ParameterInfo, member.IsExplicitImpl);
} else
container.Pending.ImplementMethod (
member.InterfaceType, name, method.ReturnType,
- ParameterTypes, member.IsExplicitImpl);
+ ParameterInfo, member.IsExplicitImpl);
if (member.IsExplicitImpl)
container.TypeBuilder.DefineMethodOverride (
if (!base.Define ())
return false;
- if (!MemberType.IsPrimitive) {
+ if (!TypeManager.IsPrimitiveType (MemberType)) {
Report.Error (1663, Location, "Fixed sized buffer type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double");
return false;
}
flags = method.flags;
} else {
if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
- Report.Error (422, Location, "{0}': abstract properties cannot have private accessors", GetSignatureForError (container));
+ Report.Error (442, Location, "{0}': abstract properties cannot have private accessors", GetSignatureForError (container));
}
CheckModifiers (container, ModFlags);
Expression left_expr = left == null ? null : left.GetTypeExpression (loc);
if (current_attr_target == "assembly" || current_attr_target == "module")
- $$ = new GlobalAttribute (current_container, current_attr_target,
+ $$ = new GlobalAttribute (current_class, current_attr_target,
left_expr, identifier, (ArrayList) $3, loc);
else
$$ = new Attribute (current_attr_target, left_expr, identifier, (ArrayList) $3, loc);
else
yyparse (lexer);
Tokenizer tokenizer = lexer as Tokenizer;
- tokenizer.cleanup ();
+ tokenizer.cleanup ();
} catch (Exception e){
//
// Removed for production use, use parser verbose to get the output.
if (yacc_verbose_flag > 0)
Console.WriteLine (e);
}
+
+ RootContext.Tree.Types.NamespaceEntry = null;
}
void CheckToken (int error, int yyToken, string msg)
//
// If only accessible to the current class or children
//
- if (ma == MethodAttributes.Private) {
- Type declaring_type = mi.DeclaringType;
+ if (ma == MethodAttributes.Private)
+ return invocation_type == mi.DeclaringType ||
+ TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType);
- if (invocation_type != declaring_type)
- return TypeManager.IsNestedChildOf (invocation_type, declaring_type);
-
- return true;
- }
- //
- // FamAndAssem requires that we not only derivate, but we are on the
- // same assembly.
- //
- if (ma == MethodAttributes.FamANDAssem){
- return (mi.DeclaringType.Assembly != invocation_type.Assembly);
- }
-
- // Assembly and FamORAssem succeed if we're in the same assembly.
- if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
- if (mi.DeclaringType.Assembly == invocation_type.Assembly)
+ if (mi.DeclaringType.Assembly == invocation_type.Assembly) {
+ if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
return true;
+ } else {
+ if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
+ return false;
}
- // We already know that we aren't in the same assembly.
- if (ma == MethodAttributes.Assembly)
- return false;
-
// Family and FamANDAssem require that we derive.
- if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem) || (ma == MethodAttributes.FamORAssem)){
+ // FamORAssem requires that we derive if in different assemblies.
+ if (ma == MethodAttributes.Family ||
+ ma == MethodAttributes.FamANDAssem ||
+ ma == MethodAttributes.FamORAssem) {
if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType))
return false;
}
bool must_do_cs1540_check;
- if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check)
- && IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) {
+ if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check) &&
+ IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) {
Report.Error (122, loc, "'{0}' is inaccessible due to its protection level",
DeclaringType.Name + "." + EventInfo.Name);
// Do not perform operator overload resolution when both sides are
// built-in types
//
- if (!(TypeManager.IsCLRType (l) && TypeManager.IsCLRType (r))){
+ if (!(TypeManager.IsPrimitiveType (l) && TypeManager.IsPrimitiveType (r))){
//
// Step 1: Perform Operator Overload location
//
"Iterators cannot have ref or out parameters");
return false;
}
+
+ if ((mod & Parameter.Modifier.ARGLIST) != 0) {
+ Report.Error (1636, Location, "__arglist is not allowed in parameter list of iterators");
+ return false;
+ }
+
+ if (parameters.ParameterType (i).IsPointer) {
+ Report.Error (1637, Location, "Iterators cannot have unsafe parameters or yield types");
+ return false;
+ }
}
ArrayList list = new ArrayList ();
// of methods above.
public Type [][] args;
+ //This is used to store the modifiers of arguments
+ public Parameter.Modifier [][] mods;
+
//
// This flag on the method says `We found a match, but
// because it was private, we could not use the match
pending_implementations [i].optional = missing.Optional;
pending_implementations [i].methods = mi;
pending_implementations [i].args = new Type [count][];
+ pending_implementations [i].mods = new Parameter.Modifier [count][];
pending_implementations [i].found = new bool [count];
pending_implementations [i].need_proxy = new MethodInfo [count];
string indexer_name = TypeManager.IndexerPropertyName (t);
int j = 0;
foreach (MethodInfo m in mi){
- Type [] types;
-
+ pending_implementations [i].args [j] = TypeManager.NoTypes;
+ pending_implementations [i].mods [j] = null;
+
// If there is a previous error, just ignore
if (m == null)
- types = TypeManager.NoTypes;
- else
- types = TypeManager.GetArgumentTypes (m);
-
- pending_implementations [i].args [j] = types;
+ continue;
+
+ pending_implementations [i].args [j] = TypeManager.GetArgumentTypes (m);
+
+ ParameterData pd = TypeManager.GetParameterData (m);
+
+ if (pd.Count > 0){
+ Parameter.Modifier [] pm = new Parameter.Modifier [pd.Count];
+ for (int k = 0; k < pd.Count; k++)
+ pm [k] = pd.ParameterModifier (k);
+ pending_implementations [i].mods [j] = pm;
+ }
+
j++;
}
i++;
abstract_methods.CopyTo (pending_implementations [i].methods, 0);
pending_implementations [i].found = new bool [count];
pending_implementations [i].args = new Type [count][];
+ pending_implementations [i].mods = new Parameter.Modifier [count][];
pending_implementations [i].type = type_builder;
string indexer_name = TypeManager.IndexerPropertyName (type_builder);
MethodInfo mi = (MethodInfo) m;
Type [] types = TypeManager.GetArgumentTypes (mi);
+ ParameterData pd = TypeManager.GetParameterData (mi);
pending_implementations [i].args [j] = types;
+ pending_implementations [i].mods [j] = null;
+ if (pd.Count > 0){
+ Parameter.Modifier [] pm = new Parameter.Modifier [pd.Count];
+ for (int k = 0; k < pd.Count; k++)
+ pm [k] = pd.ParameterModifier (k);
+ pending_implementations [i].mods [j] = pm;
+ }
+
j++;
}
}
/// <summary>
/// Whether the specified method is an interface method implementation
/// </summary>
- public MethodInfo IsInterfaceMethod (Type t, string name, Type ret_type, Type [] args)
+ public MethodInfo IsInterfaceMethod (Type t, string name, Type ret_type, ParameterData args)
{
return InterfaceMethod (t, name, ret_type, args, Operation.Lookup, null);
}
- public MethodInfo IsInterfaceIndexer (Type t, Type ret_type, Type [] args)
+ public MethodInfo IsInterfaceIndexer (Type t, Type ret_type, ParameterData args)
{
return InterfaceMethod (t, null, ret_type, args, Operation.Lookup, null);
}
- public void ImplementMethod (Type t, string name, Type ret_type, Type [] args, bool clear_one)
+ public void ImplementMethod (Type t, string name, Type ret_type, ParameterData args, bool clear_one)
{
InterfaceMethod (t, name, ret_type, args,
clear_one ? Operation.ClearOne : Operation.ClearAll, null);
}
- public void ImplementIndexer (Type t, MethodInfo mi, Type ret_type, Type [] args, bool clear_one)
+ public void ImplementIndexer (Type t, MethodInfo mi, Type ret_type, ParameterData args, bool clear_one)
{
InterfaceMethod (t, null, ret_type, args,
clear_one ? Operation.ClearOne : Operation.ClearAll, mi);
/// that was used in the interface, then we always need to create a proxy for it.
///
/// </remarks>
- public MethodInfo InterfaceMethod (Type t, string name, Type ret_type, Type [] args,
+ public MethodInfo InterfaceMethod (Type t, string name, Type ret_type, ParameterData args,
Operation op, MethodInfo need_proxy)
{
- int arg_len = args.Length;
+ int arg_len = args.Count;
if (pending_implementations == null)
return null;
if (tm.args [i].Length != arg_len)
continue;
- int j, top = args.Length;
- bool fail = false;
-
- for (j = 0; j < top; j++){
- if (tm.args [i][j] != args[j]){
- fail = true;
+ int j, top = args.Count;
+
+ for (j = 0; j < top; j++)
+ if (tm.args [i][j] != args.ParameterType (j) ||
+ (tm.mods [i][j] != args.ParameterModifier (j) &&
+ tm.mods [i][j] != Parameter.Modifier.PARAMS &&
+ args.ParameterModifier (j) != Parameter.Modifier.PARAMS)
+ )
break;
- }
- }
- if (fail)
+ if (j != top)
continue;
if (op != Operation.Lookup){
bool ResolveExpression (EmitContext ec)
{
if (!TypeManager.ImplementsInterface (expr_type, TypeManager.idisposable_type)){
- conv = Convert.ImplicitConversionRequired (
- ec, expr, TypeManager.idisposable_type, loc);
-
- if (conv == null)
+ if (Convert.ImplicitConversion (ec, expr, TypeManager.idisposable_type, loc) == null) {
+ Report.Error (1674, loc, "'{0}': type used in a using statement must be implicitly convertible to 'System.IDisposable'",
+ TypeManager.CSharpName (expr_type));
return false;
+ }
}
return true;
// This is like IsBuiltinType, but lacks decimal_type, we should also clean up
// the pieces in the code where we use IsBuiltinType and special case decimal_type.
//
- public static bool IsCLRType (Type t)
+ public static bool IsPrimitiveType (Type t)
{
- if (t == object_type || t == int32_type || t == uint32_type ||
+ return (t == int32_type || t == uint32_type ||
t == int64_type || t == uint64_type || t == float_type || t == double_type ||
t == char_type || t == short_type || t == bool_type ||
- t == sbyte_type || t == byte_type || t == ushort_type)
- return true;
- else
- return false;
+ t == sbyte_type || t == byte_type || t == ushort_type);
}
public static bool IsDelegateType (Type t)
+2005-04-08 Raja R Harinath <rharinath@novell.com>
+
+ * test-361.cs, test-361-2.cs: New test from #74484.
+
2005-04-05 Raja R Harinath <rharinath@novell.com>
* mtest-8-dll.cs, mtest-8-exe.cs: New test from #73820.
include ../build/rules.make
DISTFILES = README.tests harness.mk $(wildcard *.cs) $(wildcard *.il) $(wildcard *.xml) $(wildcard *.inc) \
- test-353-2.cs
+ test-353-2.cs test-361-2.cs
with_mono_path = MONO_PATH="$(topdir)/class/lib/$(PROFILE)$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH"
NEW_TEST_SOURCES_common = xml-033 xml-034 xml-035 xml-036 test-329 2test-16 test-330 a-parameter5 test-331 test-332 \
test-333 test-311 test-335 test-336 test-337 test-287 test-338 test-339 test-341 test-334 test-342 \
test-344 test-345 test-346 test-347 test-348 test-349 test-350 test-351 test-352 test-353 test-354 test-355 \
- test-356 test-357 test-358 test-359 test-360 \
+ test-356 test-357 test-358 test-359 test-360 test-361 \
mtest-7-dll mtest-7-exe \
mtest-8-dll mtest-8-exe
# Some tests may require additional files to be available in the current directory.
# To promote interoperability, we prefer that those files not be referred to with ../ or ..\\
# To that end, we will copy those files to the test-harness directory, so that we can refer to simple filenames.
-TEST_HARNESS_EXTRAS = $(wildcard *.inc) test-74.cs test-353-2.cs
+TEST_HARNESS_EXTRAS = $(wildcard *.inc) test-74.cs test-353-2.cs test-361-2.cs
all-local install-local uninstall-local:
--- /dev/null
+// Subordinate test file for test-361.cs
+
+using System;
+[AttributeUsage (AttributeTargets.Class)]
+class X : Attribute { }
--- /dev/null
+// Compiler options: test-361-2.cs
+
+[X]
+class Test {
+ static void Main () { }
+}
+2004-04-08 James Willcox <james@ximian.com>
+
+ * mkbundle.cs: add a --static flag for statically linking to libmono
Wed Mar 16 18:11:47 CET 2005 Paolo Molaro <lupus@ximian.com>
static bool autodeps = false;
static bool keeptemp = false;
static bool compile_only = false;
+ static bool static_link = false;
static int Main (string [] args)
{
case "--keeptemp":
keeptemp = true;
break;
-
+ case "--static":
+ static_link = true;
+ break;
default:
sources.Add (args [i]);
break;
if (compile_only)
return;
-
- cmd = String.Format ("cc -o {2} -Wall {0} `pkg-config --cflags --libs mono` {1}",
- temp_c, temp_o, output);
+
+ if (static_link)
+ cmd = String.Format ("cc -o {2} -Wall `pkg-config --cflags mono` {0} " +
+ "`pkg-config --libs-only-L mono` -Wl,-Bstatic " +
+ "`pkg-config --libs-only-l mono | sed -e \"s/\\-lm //\" | " +
+ "sed -e \"s/\\-ldl //\" | sed -e \"s/\\-lpthread //\"` " +
+ "-Wl,-Bdynamic -ldl -lm -lrt {1}",
+ temp_c, temp_o, output);
+ else
+ cmd = String.Format ("cc -o {2} -Wall {0} `pkg-config --cflags --libs mono` {1}",
+ temp_c, temp_o, output);
+
+
Console.WriteLine (cmd);
ret = system (cmd);
if (ret != 0){
" -L path Adds `path' to the search path for assemblies\n" +
" --nodeps Turns off automatic dependency embedding (default)\n" +
" --deps Turns on automatic dependency embedding\n" +
- " --keeptemp Keeps the temporary files\n");
+ " --keeptemp Keeps the temporary files\n" +
+ " --static Statically link to mono libs\n");
}
[DllImport ("libc")]
+2005-04-07 Zoltan Varga <vargaz@freemail.hu>
+
+ * mono-service.cs: Fix compilation with csc.
+
2004-04-06 Joerg Rosenkranz <joergr@voelcker.com>
* mono-service.cs:
try {
a = Assembly.LoadFrom (assembly);
- } catch (FileNotFoundException fnf) {
+ } catch (FileNotFoundException) {
error ("Could not find assembly {0}", assembly);
return 1;
} catch (BadImageFormatException){
signal_event.Reset ();
// Hook up
- signal (UnixConvert.FromSignum (Signum.SIGTERM), my_handler);
- signal (UnixConvert.FromSignum (Signum.SIGUSR1), my_handler);
- signal (UnixConvert.FromSignum (Signum.SIGUSR2), my_handler);
+ signal (UnixConvert.FromSignum (Signum.SIGTERM), new sighandler_t (my_handler));
+ signal (UnixConvert.FromSignum (Signum.SIGUSR1), new sighandler_t (my_handler));
+ signal (UnixConvert.FromSignum (Signum.SIGUSR2), new sighandler_t (my_handler));
// Start up the service.
- ServiceBase service;
+ ServiceBase service = null;
if (name != null){
foreach (ServiceBase svc in services){
+2005-04-07 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * io-private.h:
+ * threads.c:
+ * threads.h:
+ * io.c:
+ * sockets.c:
+ * sockets.h: removed dead code that deals with async IO.
+
2005-03-30 Zoltan Varga <vargaz@freemail.hu>
* atomic.c (InterlockedIncrement): Fix fallback implementation of
struct _WapiHandlePrivate_file
{
WapiFDMapped fd_mapped;
- gboolean async;
- WapiOverlappedCB callback;
};
struct _WapiHandle_find
G_BEGIN_DECLS
int _wapi_file_handle_to_fd (gpointer handle);
-gboolean _wapi_io_add_callback (gpointer handle,
- WapiOverlappedCB callback,
- guint64 flags);
G_END_DECLS
#endif /* _WAPI_IO_PRIVATE_H_ */
#include <stdio.h>
#include <utime.h>
-#ifndef PLATFORM_WIN32
-#ifdef HAVE_AIO_H
-#include <aio.h>
-#define USE_AIO 1
-#elif defined(HAVE_SYS_AIO_H)
-#include <sys/aio.h>
-#define USE_AIO 1
-#else
-#undef USE_AIO
-#endif
-#endif
-
#include <mono/io-layer/wapi.h>
#include <mono/io-layer/wapi-private.h>
#include <mono/io-layer/handles-private.h>
return(FILE_TYPE_DISK);
}
-#ifdef USE_AIO
-typedef struct {
- struct aiocb *aio;
- WapiOverlapped *overlapped;
- WapiOverlappedCB callback;
-} notifier_data_t;
-
-#define SIGPTR(a) a.SIGVAL_PTR
-
-static void
-async_notifier (union sigval sig)
-{
- notifier_data_t *ndata = SIGPTR (sig);
- guint32 error;
- guint32 numbytes;
-
- error = aio_return (ndata->aio);
- if (error < 0) {
- error = _wapi_get_win32_file_error (error);
- numbytes = 0;
- } else {
- numbytes = error;
- error = 0;
- }
-
- ndata->callback (error, numbytes, ndata->overlapped);
- g_free (ndata->aio);
- g_free (ndata);
-}
-
-#endif /* USE_AIO */
-
static gboolean file_read(gpointer handle, gpointer buffer,
guint32 numbytes, guint32 *bytesread,
WapiOverlapped *overlapped)
return(FALSE);
}
- if (file_private_handle->async == FALSE) {
- do {
- ret=read(file_private_handle->fd_mapped.fd, buffer,
- numbytes);
- }
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
-
- if(ret==-1) {
- gint err = errno;
-
-#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": read of handle %p fd %d error: %s", handle,
- file_private_handle->fd_mapped.fd,
- strerror(err));
-#endif
- SetLastError (_wapi_get_win32_file_error (err));
- return(FALSE);
- }
-
- if(bytesread!=NULL) {
- *bytesread=ret;
- }
-
- return(TRUE);
- }
-
-#ifndef USE_AIO
- SetLastError (ERROR_NOT_SUPPORTED);
- return FALSE;
-#else
- if (overlapped == NULL || file_private_handle->callback == NULL) {
- SetLastError (ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
- {
- int fd = file_private_handle->fd_mapped.fd;
- struct aiocb *aio;
- int result;
- notifier_data_t *ndata;
-
- ndata = g_new0 (notifier_data_t, 1);
- aio = g_new0 (struct aiocb, 1);
- ndata->overlapped = overlapped;
- ndata->aio = aio;
- ndata->callback = file_private_handle->callback;
-
- aio->aio_fildes = fd;
- aio->aio_lio_opcode = LIO_READ;
- aio->aio_nbytes = numbytes;
- aio->aio_offset = overlapped->Offset + (((gint64) overlapped->OffsetHigh) << 32);
- aio->aio_buf = buffer;
- aio->aio_sigevent.sigev_notify = SIGEV_THREAD;
- aio->aio_sigevent.sigev_notify_function = async_notifier;
- SIGPTR (aio->aio_sigevent.sigev_value) = ndata;
-
- result = aio_read (aio);
- if (result == -1) {
- _wapi_set_last_error_from_errno ();
- return FALSE;
+ do {
+ ret=read(file_private_handle->fd_mapped.fd, buffer,
+ numbytes);
}
+ while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+
+ if(ret==-1) {
+ gint err = errno;
- result = aio_error (aio);
-#ifdef DEBUG
- g_print ("aio_error (read) returned %d for %d\n", result, fd);
-#endif
- if (result == 0) {
- numbytes = aio_return (aio);
#ifdef DEBUG
- g_print ("numbytes %d for %d\n", numbytes, fd);
+ g_message(G_GNUC_PRETTY_FUNCTION
+ ": read of handle %p fd %d error: %s", handle,
+ file_private_handle->fd_mapped.fd,
+ strerror(err));
#endif
- } else {
- errno = result;
- _wapi_set_last_error_from_errno ();
- return FALSE;
+ SetLastError (_wapi_get_win32_file_error (err));
+ return(FALSE);
}
-
- if (bytesread)
- *bytesread = numbytes;
-
- return TRUE;
+
+ if(bytesread!=NULL) {
+ *bytesread=ret;
}
-#endif
+
+ return(TRUE);
}
static gboolean file_write(gpointer handle, gconstpointer buffer,
struct _WapiHandlePrivate_file *file_private_handle;
gboolean ok;
int ret;
+ off_t current_pos;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
(gpointer *)&file_handle,
return(FALSE);
}
- if (file_private_handle->async == FALSE) {
- off_t current_pos;
-
- /* Need to lock the region we're about to write to,
- * because we only do advisory locking on POSIX
- * systems
- */
- current_pos = lseek (file_private_handle->fd_mapped.fd,
- (off_t)0, SEEK_CUR);
- if (current_pos == -1) {
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": handle %p fd %d lseek failed: %s", handle, file_private_handle->fd_mapped.fd, strerror (errno));
-#endif
- _wapi_set_last_error_from_errno ();
- return(FALSE);
- }
-
- if (_wapi_lock_file_region (file_private_handle->fd_mapped.fd,
- current_pos, numbytes) == FALSE) {
- /* The error has already been set */
- return(FALSE);
- }
-
- do {
- ret=write(file_private_handle->fd_mapped.fd, buffer,
- numbytes);
- }
- while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
-
- _wapi_unlock_file_region (file_private_handle->fd_mapped.fd,
- current_pos, numbytes);
-
- if (ret == -1) {
- if (errno == EINTR) {
- ret = 0;
- } else {
- _wapi_set_last_error_from_errno ();
+ /* Need to lock the region we're about to write to,
+ * because we only do advisory locking on POSIX
+ * systems
+ */
+ current_pos = lseek (file_private_handle->fd_mapped.fd,
+ (off_t)0, SEEK_CUR);
+ if (current_pos == -1) {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": write of handle %p fd %d error: %s", handle,
- file_private_handle->fd_mapped.fd,
- strerror(errno));
+ g_message (G_GNUC_PRETTY_FUNCTION ": handle %p fd %d lseek failed: %s", handle, file_private_handle->fd_mapped.fd, strerror (errno));
#endif
-
- return(FALSE);
- }
- }
- if(byteswritten!=NULL) {
- *byteswritten=ret;
- }
- return(TRUE);
+ _wapi_set_last_error_from_errno ();
+ return(FALSE);
}
-
-#ifndef USE_AIO
- SetLastError (ERROR_NOT_SUPPORTED);
- return FALSE;
-#else
- if (overlapped == NULL || file_private_handle->callback == NULL) {
- SetLastError (ERROR_INVALID_PARAMETER);
- return FALSE;
+
+ if (_wapi_lock_file_region (file_private_handle->fd_mapped.fd,
+ current_pos, numbytes) == FALSE) {
+ /* The error has already been set */
+ return(FALSE);
}
-
- {
- int fd = file_private_handle->fd_mapped.fd;
- struct aiocb *aio;
- int result;
- notifier_data_t *ndata;
-
- ndata = g_new0 (notifier_data_t, 1);
- aio = g_new0 (struct aiocb, 1);
- ndata->overlapped = overlapped;
- ndata->aio = aio;
- ndata->callback = file_private_handle->callback;
-
- aio->aio_fildes = fd;
- aio->aio_lio_opcode = LIO_WRITE;
- aio->aio_nbytes = numbytes;
- aio->aio_offset = overlapped->Offset + (((gint64) overlapped->OffsetHigh) << 32);
- aio->aio_buf = (gpointer) buffer;
- aio->aio_sigevent.sigev_notify = SIGEV_THREAD;
- aio->aio_sigevent.sigev_notify_function = async_notifier;
- SIGPTR (aio->aio_sigevent.sigev_value) = ndata;
-
- result = aio_write (aio);
- if (result == -1) {
- _wapi_set_last_error_from_errno ();
- return FALSE;
+
+ do {
+ ret=write(file_private_handle->fd_mapped.fd, buffer,
+ numbytes);
}
+ while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
- result = aio_error (aio);
-#ifdef DEBUG
- g_print ("aio_error (write) returned %d for %d\n", result, fd);
-#endif
- if (result == 0) {
- numbytes = aio_return (aio);
+ _wapi_unlock_file_region (file_private_handle->fd_mapped.fd,
+ current_pos, numbytes);
+
+ if (ret == -1) {
+ if (errno == EINTR) {
+ ret = 0;
+ } else {
+ _wapi_set_last_error_from_errno ();
#ifdef DEBUG
- g_print ("numbytes %d for %d\n", numbytes, fd);
+ g_message(G_GNUC_PRETTY_FUNCTION
+ ": write of handle %p fd %d error: %s", handle,
+ file_private_handle->fd_mapped.fd,
+ strerror(errno));
#endif
- } else {
- errno = result;
- _wapi_set_last_error_from_errno ();
- return FALSE;
- }
- if (byteswritten)
- *byteswritten = numbytes;
-
- return TRUE;
+ return(FALSE);
+ }
}
-#endif
+ if(byteswritten!=NULL) {
+ *byteswritten=ret;
+ }
+ return(TRUE);
}
static gboolean file_flush(gpointer handle)
file_private_handle->fd_mapped.fd=fd;
file_private_handle->fd_mapped.assigned=TRUE;
- file_private_handle->async = ((attrs & FILE_FLAG_OVERLAPPED) != 0);
file_handle->filename=_wapi_handle_scratch_store (filename,
strlen (filename));
if(security!=NULL) {
return(ret);
}
-gboolean
-_wapi_io_add_callback (gpointer fd_handle,
- WapiOverlappedCB callback,
- guint64 flags G_GNUC_UNUSED)
-{
- struct _WapiHandle_file *file_handle;
- struct _WapiHandlePrivate_file *file_private_handle;
- gboolean ok;
- int thr_ret;
- gboolean ret = FALSE;
- gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle);
-
- if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
- (gpointer *) &file_handle,
- (gpointer *) &file_private_handle);
-
- if (ok == FALSE) {
- ok = _wapi_lookup_handle (handle, WAPI_HANDLE_PIPE,
- (gpointer *) &file_handle,
- (gpointer *) &file_private_handle);
-
- }
-
- if (ok == FALSE || file_private_handle->async == FALSE) {
- SetLastError (ERROR_INVALID_HANDLE);
- return FALSE;
- }
-
- pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
- handle);
- thr_ret = _wapi_handle_lock_handle (handle);
- g_assert (thr_ret == 0);
-
- if (file_private_handle->callback != NULL) {
- SetLastError (ERROR_INVALID_PARAMETER);
- goto cleanup;
- }
- ret = TRUE;
-
- file_private_handle->callback = callback;
-
-cleanup:
- thr_ret = _wapi_handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
- pthread_cleanup_pop (0);
-
- return(ret);
-}
-
gint32
GetLogicalDriveStrings (guint32 len, gunichar2 *buf)
{
#include <signal.h>
#endif
-#ifndef PLATFORM_WIN32
-#ifdef HAVE_AIO_H
-#include <aio.h>
-#define USE_AIO 1
-#elif defined(HAVE_SYS_AIO_H)
-#include <sys/aio.h>
-#define USE_AIO 1
-#else
-#undef USE_AIO
-#endif
-#endif
-
#include <mono/io-layer/wapi.h>
#include <mono/io-layer/wapi-private.h>
#include <mono/io-layer/socket-private.h>
FD_SET(fd, set);
}
-#ifdef USE_AIO
-
-typedef struct {
- struct aiocb *aio;
- gpointer ares;
- SocketAsyncCB callback;
-} notifier_data_t;
-
-#define SIGPTR(a) a.SIGVAL_PTR
-
-static void
-async_notifier (union sigval sig)
-{
- notifier_data_t *ndata = SIGPTR (sig);
- guint32 error;
- guint32 numbytes;
-
- error = aio_return (ndata->aio);
- if (error < 0) {
- error = _wapi_get_win32_file_error (error);
- numbytes = 0;
- } else {
- numbytes = error;
- error = 0;
- }
-
- ndata->callback (error, numbytes, ndata->ares);
- g_free (ndata->aio);
- g_free (ndata);
-}
-
-static gboolean
-do_aio_call (gboolean is_read, gpointer fd_handle, gpointer buffer,
- guint32 numbytes, guint32 *out_bytes,
- gpointer ares,
- SocketAsyncCB callback)
-{
- gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle);
- int fd = GPOINTER_TO_UINT (fd_handle);
- struct aiocb *aio;
- int result;
- notifier_data_t *ndata;
-
- if (handle == NULL ||
- _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
- WSASetLastError (WSAENOTSOCK);
- return FALSE;
- }
-
- ndata = g_new0 (notifier_data_t, 1);
- aio = g_new0 (struct aiocb, 1);
- ndata->ares = ares;
- ndata->aio = aio;
- ndata->callback = callback;
-
- aio->aio_fildes = fd;
- aio->aio_lio_opcode = (is_read) ? LIO_READ : LIO_WRITE;
- aio->aio_nbytes = numbytes;
- aio->aio_offset = 0;
- aio->aio_buf = buffer;
- aio->aio_sigevent.sigev_notify = SIGEV_THREAD;
- aio->aio_sigevent.sigev_notify_function = async_notifier;
- SIGPTR (aio->aio_sigevent.sigev_value) = ndata;
-
- if (is_read) {
- result = aio_read (aio);
- } else {
- result = aio_write (aio);
- }
-
- if (result == -1) {
- WSASetLastError (errno_to_WSA (errno, "do_aio_call"));
- return FALSE;
- }
-
- result = aio_error (aio);
- if (result == 0) {
- numbytes = aio_return (aio);
- } else {
- WSASetLastError (errno_to_WSA (result, "do_aio_call"));
- return FALSE;
- }
-
- if (out_bytes)
- *out_bytes = numbytes;
-
- return TRUE;
-}
-
-gboolean _wapi_socket_async_read (gpointer handle, gpointer buffer,
- guint32 numbytes,
- guint32 *bytesread, gpointer ares,
- SocketAsyncCB callback)
-{
- return do_aio_call (TRUE, handle, buffer, numbytes, bytesread, ares, callback);
-}
-
-gboolean _wapi_socket_async_write (gpointer handle, gpointer buffer,
- guint32 numbytes,
- guint32 *byteswritten, gpointer ares,
- SocketAsyncCB callback)
-{
- return do_aio_call (FALSE, handle, buffer, numbytes, byteswritten, ares, callback);
-}
-
-#endif /* USE_AIO */
-
gchar *output, gint o_len, glong *written,
void *unused1, void *unused2);
-#ifndef PLATFORM_WIN32
-typedef void (*SocketAsyncCB) (guint32 error, guint32 numbytes, gpointer ares);
-
-gboolean _wapi_socket_async_read (gpointer handle, gpointer buffer,
- guint32 numbytes,
- guint32 *bytesread, gpointer ares,
- SocketAsyncCB callback);
-
-gboolean _wapi_socket_async_write (gpointer handle, gpointer buffer,
- guint32 numbytes,
- guint32 *bytesread, gpointer ares,
- SocketAsyncCB callback);
-#endif
-
#endif /* _WAPI_SOCKETS_H_ */
SleepEx(ms, FALSE);
}
-gboolean
-BindIoCompletionCallback (gpointer handle,
- WapiOverlappedCB callback,
- guint64 flags)
-{
- WapiHandleType type;
-
- type = _wapi_handle_type (handle);
- if (type == WAPI_HANDLE_FILE || type == WAPI_HANDLE_PIPE)
- return _wapi_io_add_callback (handle, callback, flags);
-
- SetLastError (ERROR_NOT_SUPPORTED);
- return FALSE;
-}
-
guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer handle,
gpointer param)
{
extern gboolean TlsSetValue(guint32 idx, gpointer value);
extern void Sleep(guint32 ms);
extern guint32 SleepEx(guint32 ms, gboolean alertable);
-extern gboolean BindIoCompletionCallback (gpointer handle,
- WapiOverlappedCB callback,
- guint64 flags);
-
extern guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer thread_handle,
gpointer param);
+2005-04-07 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * file-io.c:
+ * file-io.h:
+ * threadpool.c:
+ * threadpool.h:
+ * icall.c:
+ * socket-io.c: removed dead code for async IO.
+
+2005-04-07 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * socket-io.h: 2 more fields in MonoSocketAsyncResult.
+
+ * threadpool.c: intercept socket async. calls and pass them to a thread
+ that is polling and dispatching the job items to the threadpool as
+ socket become ready. Fixes bugs #71217, #71933.
+
+ * icall.c: Removed AsyncReceive and AsyncSend. Speed up for copies
+ between char and short/ushort arrays.
+
+ * socket-io.c: remove dead code.
+
2005-04-06 Atsushi Enomoto <atsushi@ximian.com>
* locales.c,
#include <signal.h>
#include <unistd.h>
-#ifndef PLATFORM_WIN32
-#ifdef HAVE_AIO_H
-#include <aio.h>
-#define USE_AIO 1
-#elif defined(HAVE_SYS_AIO_H)
-#include <sys/aio.h>
-#define USE_AIO 1
-#else
-#undef USE_AIO
-#endif
-#endif
-
#include <mono/metadata/object.h>
#include <mono/io-layer/io-layer.h>
#include <mono/metadata/file-io.h>
return(ret);
}
-/*
- * Asynchronous IO
- */
-MonoBoolean
-ves_icall_System_IO_MonoIO_GetSupportsAsync (void)
-{
- MONO_ARCH_SAVE_REGS;
-
-#ifdef PLATFORM_WIN32
- /* Seems like BindIoCompletionCallback is not found when compiling...
- * Disabling AIO support on win. Any one wants to fix this?
- */
- return FALSE;
- /* return (g_getenv ("MONO_DISABLE_AIO") == NULL && WINVER >= 0x500); */
-#elif defined(USE_AIO)
- return FALSE;
- /* Disabled. See bug 73718. We can enable this again if we have
- * a thread that handles socket/file IO
- *
- if (aio_cancel (-1, NULL) == -1 && errno == ENOSYS)
- return FALSE;
-
- return (g_getenv ("MONO_DISABLE_AIO") == NULL);
- */
-#else
- return FALSE;
-#endif
-}
-
-static WapiOverlapped *
-get_overlapped_from_fsa (MonoFSAsyncResult *ares)
-{
- WapiOverlapped *ovl;
-
- ovl = g_new0 (WapiOverlapped, 1);
- ovl->Offset = ares->offset;
- ovl->hEvent = ares->wait_handle;
-
- return ovl;
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_BeginRead (HANDLE handle, MonoFSAsyncResult *ares)
-{
- guint32 bytesread;
- WapiOverlapped *ovl;
-
- MONO_ARCH_SAVE_REGS;
-
- ovl = get_overlapped_from_fsa (ares);
- ovl->handle1 = ares;
- return ReadFile (handle, mono_array_addr (ares->buffer, gchar, ares->offset), ares->count, &bytesread, ovl);
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_BeginWrite (HANDLE handle, MonoFSAsyncResult *ares)
-{
- guint32 byteswritten;
- WapiOverlapped *ovl;
-
- MONO_ARCH_SAVE_REGS;
-
- ovl = get_overlapped_from_fsa (ares);
- ovl->handle1 = ares;
- return WriteFile (handle, mono_array_addr (ares->buffer, gchar, ares->offset), ares->count, &byteswritten, ovl);
-}
-
void ves_icall_System_IO_MonoIO_Lock (HANDLE handle, gint64 position,
gint64 length, gint32 *error)
{
MonoDelegate *real_cb;
} MonoFSAsyncResult;
-#ifdef PLATFORM_WIN32
-typedef struct _WapiOverlapped WapiOverlapped;
-
-struct _WapiOverlapped
-{
- guint32 Internal;
- guint32 InternalHigh;
- guint32 Offset;
- guint32 OffsetHigh;
- gpointer hEvent;
- gpointer handle1;
- gpointer handle2;
-};
-#endif
-
/* System.IO.MonoIO */
extern MonoBoolean
extern gint32
ves_icall_System_IO_MonoIO_GetTempPath (MonoString **mono_name);
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_GetSupportsAsync (void);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_BeginRead (HANDLE handle, MonoFSAsyncResult *ares);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_BeginWrite (HANDLE handle, MonoFSAsyncResult *ares);
-
extern void ves_icall_System_IO_MonoIO_Lock (HANDLE handle, gint64 position,
gint64 length, gint32 *error);
extern void ves_icall_System_IO_MonoIO_Unlock (HANDLE handle, gint64 position,
MonoClass *src_class;
MonoClass *dest_class;
int i;
+ gboolean char_int16;
MONO_ARCH_SAVE_REGS;
return TRUE;
}
- if (src_class != dest_class) {
+ /* Check if we're copying a char[] <==> (u)short[] */
+ char_int16 = (src_class == mono_defaults.int16_class || src_class == mono_defaults.uint16_class ||
+ src_class == mono_defaults.char_class);
+ char_int16 = (char_int16 && (dest_class == mono_defaults.int16_class || dest_class == mono_defaults.uint16_class ||
+ dest_class == mono_defaults.char_class));
+
+ if (!char_int16 && src_class != dest_class) {
if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
return FALSE;
};
static const IcallEntry monoio_icalls [] = {
- {"BeginRead", ves_icall_System_IO_MonoIO_BeginRead },
- {"BeginWrite", ves_icall_System_IO_MonoIO_BeginWrite },
{"Close(intptr,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Close},
{"CopyFile(string,string,bool,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_CopyFile},
{"CreateDirectory(string,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_CreateDirectory},
{"GetFileStat(string,System.IO.MonoIOStat&,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_GetFileStat},
{"GetFileType(intptr,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_GetFileType},
{"GetLength(intptr,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_GetLength},
- {"GetSupportsAsync", ves_icall_System_IO_MonoIO_GetSupportsAsync},
{"GetTempPath(string&)", ves_icall_System_IO_MonoIO_GetTempPath},
{"Lock(intptr,long,long,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Lock},
{"MoveFile(string,string,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_MoveFile},
static const IcallEntry socket_icalls [] = {
{"Accept_internal(intptr,int&)", ves_icall_System_Net_Sockets_Socket_Accept_internal},
- {"AsyncReceiveInternal", ves_icall_System_Net_Sockets_Socket_AsyncReceive},
- {"AsyncSendInternal", ves_icall_System_Net_Sockets_Socket_AsyncSend},
{"Available_internal(intptr,int&)", ves_icall_System_Net_Sockets_Socket_Available_internal},
{"Bind_internal(intptr,System.Net.SocketAddress,int&)", ves_icall_System_Net_Sockets_Socket_Bind_internal},
{"Blocking_internal(intptr,bool,int&)", ves_icall_System_Net_Sockets_Socket_Blocking_internal},
{"Connect_internal(intptr,System.Net.SocketAddress,int&)", ves_icall_System_Net_Sockets_Socket_Connect_internal},
{"GetSocketOption_arr_internal(intptr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,byte[]&,int&)", ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal},
{"GetSocketOption_obj_internal(intptr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,object&,int&)", ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal},
- {"GetSupportsAsync", ves_icall_System_IO_MonoIO_GetSupportsAsync},
{"Listen_internal(intptr,int,int&)", ves_icall_System_Net_Sockets_Socket_Listen_internal},
{"LocalEndPoint_internal(intptr,int&)", ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal},
{"Poll_internal", ves_icall_System_Net_Sockets_Socket_Poll_internal},
};
static const IcallEntry threadpool_icalls [] = {
- {"BindHandleInternal", ves_icall_System_Threading_ThreadPool_BindHandle},
{"GetAvailableThreads", ves_icall_System_Threading_ThreadPool_GetAvailableThreads},
{"GetMaxThreads", ves_icall_System_Threading_ThreadPool_GetMaxThreads},
{"GetMinThreads", ves_icall_System_Threading_ThreadPool_GetMinThreads},
#include <unistd.h>
#include <errno.h>
-#ifndef PLATFORM_WIN32
-#ifdef HAVE_AIO_H
-#include <aio.h>
-#define USE_AIO 1
-#elif defined(HAVE_SYS_AIO_H)
-#include <sys/aio.h>
-#define USE_AIO 1
-#else
-#undef USE_AIO
-#endif
-#endif
-
#include <mono/metadata/object.h>
#include <mono/io-layer/io-layer.h>
#include <mono/metadata/socket-io.h>
return(TRUE);
}
-
-/* Async interface */
-#ifndef USE_AIO
-void
-ves_icall_System_Net_Sockets_Socket_AsyncReceive (MonoSocketAsyncResult *ares, gint *error)
-{
- MONO_ARCH_SAVE_REGS;
-
- *error = ERROR_NOT_SUPPORTED;
-}
-
-void
-ves_icall_System_Net_Sockets_Socket_AsyncSend (MonoSocketAsyncResult *ares, gint *error)
-{
- MONO_ARCH_SAVE_REGS;
-
- *error = ERROR_NOT_SUPPORTED;
-}
-#else
-static void
-wsa_overlapped_callback (guint32 error, guint32 numbytes, gpointer result)
-{
- MonoSocketAsyncResult *ares = (MonoSocketAsyncResult *) result;
- MonoThread *thread;
-
- ares->completed = TRUE;
- ares->error = error;
- ares->total = numbytes;
-
- if (ares->callback != NULL) {
- gpointer p [1];
-
- *p = ares;
- thread = mono_thread_attach (mono_object_domain (ares));
- mono_runtime_invoke (ares->callback->method_info->method, NULL, p, NULL);
-
- mono_thread_detach (thread);
- }
-
- if (ares->wait_handle != NULL)
- SetEvent (ares->wait_handle->handle);
-}
-
-void
-ves_icall_System_Net_Sockets_Socket_AsyncReceive (MonoSocketAsyncResult *ares, gint *error)
-{
- gint32 bytesread;
-
- MONO_ARCH_SAVE_REGS;
-
- if (_wapi_socket_async_read (ares->handle,
- mono_array_addr (ares->buffer, gchar, ares->offset),
- ares->size,
- &bytesread,
- ares,
- wsa_overlapped_callback) == FALSE) {
- *error = WSAGetLastError ();
- } else {
- *error = 0;
- ares->completed_synch = TRUE;
- wsa_overlapped_callback (0, bytesread, ares);
- }
-}
-
-void
-ves_icall_System_Net_Sockets_Socket_AsyncSend (MonoSocketAsyncResult *ares, gint *error)
-{
- gint32 byteswritten;
-
- MONO_ARCH_SAVE_REGS;
-
- if (_wapi_socket_async_write (ares->handle,
- mono_array_addr (ares->buffer, gchar, ares->offset),
- ares->size,
- &byteswritten,
- ares,
- wsa_overlapped_callback) == FALSE) {
- *error = WSAGetLastError ();
- } else {
- *error = 0;
- ares->completed_synch = TRUE;
- wsa_overlapped_callback (0, byteswritten, ares);
- }
-}
-#endif /* USE_AIO */
-
void mono_network_init(void)
{
WSADATA wsadata;
MonoBoolean completed;
MonoDelegate *real_callback;
gint error;
+ gint operation;
+ MonoAsyncResult *ares;
} MonoSocketAsyncResult;
typedef struct
extern MonoBoolean ves_icall_System_Net_Dns_GetHostName_internal(MonoString **h_name);
extern MonoBoolean ves_icall_System_Net_Sockets_Socket_Poll_internal (SOCKET sock, gint mode, gint timeout, gint32 *error);
-extern void ves_icall_System_Net_Sockets_Socket_AsyncReceive (MonoSocketAsyncResult *ares, gint *error);
-extern void ves_icall_System_Net_Sockets_Socket_AsyncSend (MonoSocketAsyncResult *ares, gint *error);
-
extern void mono_network_init(void);
extern void mono_network_cleanup(void);
* Gonzalo Paniagua Javier (gonzalo@ximian.com)
*
* (C) 2001-2003 Ximian, Inc.
- * (c) 2004 Novell, Inc. (http://www.novell.com)
+ * (c) 2004,2005 Novell, Inc. (http://www.novell.com)
*/
#include <config.h>
#include <mono/metadata/file-io.h>
#include <mono/metadata/monitor.h>
#include <mono/metadata/marshal.h>
+#include <mono/metadata/socket-io.h>
#include <mono/io-layer/io-layer.h>
#include <mono/os/gc_wrapper.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <mono/utils/mono-poll.h>
#include "threadpool.h"
static CRITICAL_SECTION ares_lock;
+typedef struct {
+ CRITICAL_SECTION io_lock; /* access to sock_to_state */
+ int inited;
+ int pipe [2];
+ GHashTable *sock_to_state;
+
+ HANDLE new_sem; /* access to newpfd and write side of the pipe */
+ mono_pollfd *newpfd;
+} SocketIOData;
+
+static SocketIOData socket_io_data;
+
/* we append a job */
static HANDLE job_added;
static void async_invoke_thread (gpointer data);
static void append_job (MonoAsyncResult *ar);
+static void start_thread_or_queue (MonoAsyncResult *ares);
static GList *async_call_queue = NULL;
+static MonoClass *socket_async_call_klass;
+
+#define INIT_POLLFD(a, b, c) {(a)->fd = b; (a)->events = c; (a)->revents = 0;}
+enum {
+ AIO_FIRST,
+ AIO_ACCEPT = 0,
+ AIO_CONNECT,
+ AIO_RECEIVE,
+ AIO_RECEIVEFROM,
+ AIO_SEND,
+ AIO_SENDTO,
+ AIO_LAST
+};
+
+static void
+socket_io_cleanup (SocketIOData *data)
+{
+ if (data->inited == 0)
+ return;
+
+ EnterCriticalSection (&data->io_lock);
+ data->inited = 0;
+ close (data->pipe [0]);
+ data->pipe [0] = -1;
+ close (data->pipe [1]);
+ data->pipe [1] = -1;
+ CloseHandle (data->new_sem);
+ data->new_sem = NULL;
+ g_hash_table_destroy (data->sock_to_state);
+ data->sock_to_state = NULL;
+ LeaveCriticalSection (&data->io_lock);
+}
+
+static int
+get_event_from_state (MonoSocketAsyncResult *state)
+{
+ switch (state->operation) {
+ case AIO_ACCEPT:
+ case AIO_RECEIVE:
+ case AIO_RECEIVEFROM:
+ return MONO_POLLIN;
+ case AIO_SEND:
+ case AIO_SENDTO:
+ case AIO_CONNECT:
+ return MONO_POLLOUT;
+ default: /* Should never happen */
+ g_print ("socket_io_add: unknown value in switch!!!\n");
+ return 0;
+ }
+}
+
+static int
+get_events_from_list (GSList *list)
+{
+ MonoSocketAsyncResult *state;
+ int events = 0;
+
+ while (list && list->data) {
+ state = (MonoSocketAsyncResult *) list->data;
+ events |= get_event_from_state (state);
+ list = list->next;
+ }
+
+ return events;
+}
+
+static GSList *
+process_io_event (GSList *list, int event)
+{
+ MonoSocketAsyncResult *state;
+ GSList *oldlist;
+
+ oldlist = list;
+ state = NULL;
+ while (list) {
+ state = (MonoSocketAsyncResult *) list->data;
+ if (get_event_from_state (state) == event)
+ break;
+ list = list->next;
+ }
+
+ if (list != NULL) {
+ oldlist = g_slist_remove_link (oldlist, list);
+ g_slist_free_1 (list);
+ start_thread_or_queue (state->ares);
+ }
+
+ return oldlist;
+}
+
+static int
+mark_bad_fds (mono_pollfd *pfds, int nfds)
+{
+ int i, ret;
+ mono_pollfd *pfd;
+ int count = 0;
+
+ for (i = 0; i < nfds; i++) {
+ pfd = &pfds [i];
+ if (pfd->fd == -1)
+ continue;
+
+ ret = mono_poll (pfds, 1, 0);
+ if (ret == -1 && errno == EBADF) {
+ pfd->revents |= MONO_POLLNVAL;
+ count++;
+ } else if (ret == 1) {
+ count++;
+ }
+ }
+
+ return count;
+}
+
+static void
+socket_io_main (gpointer p)
+{
+#define INITIAL_POLLFD_SIZE 1024
+#define POLL_ERRORS (MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL)
+ SocketIOData *data = p;
+ mono_pollfd *pfds;
+ gint maxfd = 1;
+ gint allocated;
+ gint i;
+ MonoThread *thread;
+
+
+ thread = mono_thread_current ();
+ thread->threadpool_thread = TRUE;
+ thread->state |= ThreadState_Background;
+
+ allocated = INITIAL_POLLFD_SIZE;
+ pfds = g_new0 (mono_pollfd, allocated);
+ INIT_POLLFD (pfds, data->pipe [0], MONO_POLLIN);
+ for (i = 1; i < allocated; i++)
+ INIT_POLLFD (&pfds [i], -1, 0);
+
+ while (1) {
+ int nsock = 0;
+ mono_pollfd *pfd;
+ char one [1];
+ GSList *list;
+
+ do {
+ if (nsock == -1) {
+ if ((thread->state & ThreadState_StopRequested) != 0)
+ mono_thread_interruption_checkpoint ();
+ }
+
+ nsock = mono_poll (pfds, maxfd, -1);
+ } while (nsock == -1 && errno == EINTR);
+
+ /*
+ * Apart from EINTR, we only check EBADF, for the rest:
+ * EINVAL: mono_poll() 'protects' us from descriptor
+ * numbers above the limit if using select() by marking
+ * then as MONO_POLLERR. If a system poll() is being
+ * used, the number of descriptor we're passing will not
+ * be over sysconf(_SC_OPEN_MAX), as the error would have
+ * happened when opening.
+ *
+ * EFAULT: we own the memory pointed by pfds.
+ * ENOMEM: we're doomed anyway
+ *
+ */
+
+ if (nsock == -1 && errno == EBADF) {
+ pfds->revents = 0; /* Just in case... */
+ nsock = mark_bad_fds (pfds, maxfd);
+ }
+
+ if ((pfds->revents & POLL_ERRORS) != 0) {
+ /* We're supposed to die now, as the pipe has been closed */
+ g_free (pfds);
+ socket_io_cleanup (data);
+ return;
+ }
+
+ /* Got a new socket */
+ if ((pfds->revents & MONO_POLLIN) != 0) {
+ for (i = 1; i < allocated; i++) {
+ pfd = &pfds [i];
+ if (pfd->fd == -1 || pfd->fd == data->newpfd->fd)
+ break;
+ }
+
+ if (i == allocated) {
+ mono_pollfd *oldfd;
+
+ oldfd = pfds;
+ i = allocated;
+ allocated = allocated * 2;
+ pfds = g_renew (mono_pollfd, oldfd, allocated);
+ g_free (oldfd);
+ for (; i < allocated; i++)
+ INIT_POLLFD (&pfds [i], -1, 0);
+ }
+
+ read (data->pipe [0], one, 1);
+ INIT_POLLFD (&pfds [i], data->newpfd->fd, data->newpfd->events);
+ ReleaseSemaphore (data->new_sem, 1, NULL);
+ if (i >= maxfd)
+ maxfd = i + 1;
+ nsock--;
+ }
+
+ if (nsock == 0)
+ continue;
+
+ EnterCriticalSection (&data->io_lock);
+ if (data->inited == 0) {
+ g_free (pfds);
+ return; /* cleanup called */
+ }
+
+ for (i = 1; i < maxfd && nsock > 0; i++) {
+ pfd = &pfds [i];
+ if (pfd->fd == -1 || pfd->revents == 0)
+ continue;
+
+ nsock--;
+ list = g_hash_table_lookup (data->sock_to_state, GINT_TO_POINTER (pfd->fd));
+ if (list != NULL && (pfd->revents & (MONO_POLLIN | POLL_ERRORS)) != 0) {
+ list = process_io_event (list, MONO_POLLIN);
+ }
+
+ if (list != NULL && (pfd->revents & (MONO_POLLOUT | POLL_ERRORS)) != 0) {
+ list = process_io_event (list, MONO_POLLOUT);
+ }
+
+ if (list != NULL) {
+ g_hash_table_replace (data->sock_to_state, GINT_TO_POINTER (pfd->fd), list);
+ pfd->events = get_events_from_list (list);
+ } else {
+ g_hash_table_remove (data->sock_to_state, GINT_TO_POINTER (pfd->fd));
+ pfd->fd = -1;
+ if (i == maxfd - 1)
+ maxfd--;
+ }
+ }
+ LeaveCriticalSection (&data->io_lock);
+ }
+}
+
+static void
+socket_io_init (SocketIOData *data)
+{
+ if (pipe (data->pipe) != 0) {
+ int err = errno;
+ perror ("mono");
+ g_assert (err);
+ }
+
+ data->sock_to_state = g_hash_table_new (g_direct_hash, g_direct_equal);
+ data->new_sem = CreateSemaphore (NULL, 1, 1, NULL);
+ mono_thread_create (mono_get_root_domain (), socket_io_main, data);
+}
+
+static void
+socket_io_add (MonoAsyncResult *ares, MonoSocketAsyncResult *state)
+{
+ int events;
+ char msg [1];
+ GSList *list;
+ SocketIOData *data = &socket_io_data;
+
+ state->ares = ares;
+ if (InterlockedCompareExchange (&data->inited, -1, -1) == 0) {
+ EnterCriticalSection (&data->io_lock);
+ if (0 == data->inited) {
+ socket_io_init (data);
+ data->inited = 1;
+ }
+ LeaveCriticalSection (&data->io_lock);
+ }
+
+ WaitForSingleObject (data->new_sem, INFINITE);
+ if (data->newpfd == NULL)
+ data->newpfd = g_new0 (mono_pollfd, 1);
+
+ EnterCriticalSection (&data->io_lock);
+ list = g_hash_table_lookup (data->sock_to_state, GINT_TO_POINTER (state->handle));
+ if (list == NULL) {
+ list = g_slist_alloc ();
+ list->data = state;
+ } else {
+ list = g_slist_append (list, state);
+ }
+
+ events = get_events_from_list (list);
+ INIT_POLLFD (data->newpfd, GPOINTER_TO_INT (state->handle), events);
+ g_hash_table_replace (data->sock_to_state, GINT_TO_POINTER (state->handle), list);
+ LeaveCriticalSection (&data->io_lock);
+ *msg = (char) state->operation;
+ write (data->pipe [1], msg, 1);
+}
+
+static gboolean
+socket_io_filter (MonoObject *target, MonoObject *state)
+{
+ gint op;
+ MonoSocketAsyncResult *sock_res = (MonoSocketAsyncResult *) state;
+ MonoClass *klass;
+
+ if (target == NULL || state == NULL)
+ return FALSE;
+
+ klass = InterlockedCompareExchangePointer ((gpointer *) &socket_async_call_klass, NULL, NULL);
+ if (klass == NULL) {
+ MonoImage *system_assembly = mono_image_loaded ("System");
+
+ if (system_assembly == NULL)
+ return FALSE;
+
+ klass = mono_class_from_name (system_assembly, "System.Net.Sockets", "Socket/SocketAsyncCall");
+ if (klass == NULL) {
+ /* Should never happen... */
+ g_print ("socket_io_filter: SocketAsyncCall class not found.\n");
+ return FALSE;
+ }
+
+ InterlockedCompareExchangePointer ((gpointer *) &socket_async_call_klass, klass, NULL);
+ }
+
+ if (target->vtable->klass != klass)
+ return FALSE;
+
+ op = sock_res->operation;
+ if (op < AIO_FIRST || op >= AIO_LAST)
+ return FALSE;
+
+ return TRUE;
+}
+
static void
mono_async_invoke (MonoAsyncResult *ares)
{
/* notify listeners */
mono_monitor_enter ((MonoObject *) ares);
-
if (ares->handle != NULL) {
ac->wait_event = ((MonoWaitHandle *) ares->handle)->handle;
SetEvent (ac->wait_event);
return;
MONO_GC_REGISTER_ROOT (ares_htable);
+ InitializeCriticalSection (&socket_io_data.io_lock);
InitializeCriticalSection (&ares_lock);
ares_htable = mono_g_hash_table_new (NULL, NULL);
job_added = CreateSemaphore (NULL, 0, 0x7fffffff, NULL);
MonoDomain *domain = mono_domain_get ();
MonoAsyncResult *ares;
ASyncCall *ac;
- int busy, worker;
#ifdef HAVE_BOEHM_GC
ac = GC_MALLOC (sizeof (ASyncCall));
EnterCriticalSection (&ares_lock);
mono_g_hash_table_insert (ares_htable, ares, ares);
LeaveCriticalSection (&ares_lock);
-
+
+ if (socket_io_filter (target, state)) {
+ socket_io_add (ares, (MonoSocketAsyncResult *) state);
+ return ares;
+ }
+
+ start_thread_or_queue (ares);
+ return ares;
+}
+
+static void
+start_thread_or_queue (MonoAsyncResult *ares)
+{
+ int busy, worker;
+ MonoDomain *domain;
+
busy = (int) InterlockedCompareExchange (&busy_worker_threads, 0, -1);
worker = (int) InterlockedCompareExchange (&mono_worker_threads, 0, -1);
if (worker <= ++busy &&
worker < mono_max_worker_threads) {
InterlockedIncrement (&mono_worker_threads);
InterlockedIncrement (&busy_worker_threads);
+ domain = ((MonoObject *) ares)->vtable->domain;
mono_thread_create (domain, async_invoke_thread, ares);
} else {
append_job (ares);
ReleaseSemaphore (job_added, 1, NULL);
}
-
- return ares;
}
MonoObject *
LeaveCriticalSection (&mono_delegate_section);
if (job_added)
ReleaseSemaphore (job_added, release, NULL);
+
+ socket_io_cleanup (&socket_io_data);
}
static void
g_free (overlapped);
}
-MonoBoolean
-ves_icall_System_Threading_ThreadPool_BindHandle (gpointer handle)
-{
- MONO_ARCH_SAVE_REGS;
-
-#ifdef PLATFORM_WIN32
- return FALSE;
-#else
- if (!BindIoCompletionCallback (handle, overlapped_callback, 0)) {
- gint error = GetLastError ();
- MonoException *exc;
- gchar *msg;
-
- if (error == ERROR_INVALID_PARAMETER) {
- exc = mono_get_exception_argument (NULL, "Invalid parameter.");
- } else {
- msg = g_strdup_printf ("Win32 error %d.", error);
- exc = mono_exception_from_name_msg (mono_defaults.corlib,
- "System",
- "ApplicationException", msg);
- g_free (msg);
- }
-
- mono_raise_exception (exc);
- }
-
- return TRUE;
-#endif
-}
-
ves_icall_System_Threading_ThreadPool_SetMinThreads (gint workerThreads,
gint completionPortThreads);
-MonoBoolean
-ves_icall_System_Threading_ThreadPool_BindHandle (gpointer handle);
-
#endif
+2005-04-07 Zoltan Varga <vargaz@freemail.hu>
+
+ * errno.c: Use the GNU version of strerror_r if _GNU_SOURCE is defined
+ (otherwise assume existence of XPG variant). This allows proper
+ compilation under Red Hat 9.
+ * fstab.c: protect against users calling setfsent(), setfsent(), ...
+ endfsent(), which would otherwise leak a FILE handle.
+
2005-04-05 Zoltan Varga <vargaz@freemail.hu>
* mph.h: Apply patch from the freebsd ports collection.
* <errno.h> wrapper functions.
*/
-/* to get XPG's strerror_r declaration */
-#undef _GNU_SOURCE
-#undef _XOPEN_SOURCE
-#define _XOPEN_SOURCE 600
-
#include <errno.h>
#include <string.h>
#include "mph.h"
}
#ifdef HAVE_STRERROR_R
+
+/*
+ * There are two versions of strerror_r:
+ * - the GNU version: char *strerror_r (int errnum, char *buf, size_t n);
+ * - the XPG version: int strerror_r (int errnum, char *buf, size_t n);
+ *
+ * Ideally I could stick with the XPG version, but we need to support
+ * Red Hat 9, which only supports the GNU version.
+ *
+ * Furthermore, I do NOT want to export the GNU version in Mono.Posix.dll,
+ * as that's supposed to contain *standard* function definitions (give or
+ * take a few GNU extensions). Portability trumps all.
+ *
+ * Consequently, we export the functionality of the XPG version.
+ * Internally, we se the GNU version if _GNU_SOURCE is defined, otherwise
+ * we assume that the XPG version is present.
+ */
+
+#ifdef _GNU_SOURCE
+#define mph_min(x,y) ((x) <= (y) ? (x) : (y))
+
+/* If you pass an invalid errno value to glibc 2.3.2's strerror_r, you get
+ * back the string "Unknown error" with the error value appended. */
+static const char mph_unknown[] = "Unknown error ";
+
+/*
+ * Translate the GNU semantics to the XPG semantics.
+ *
+ * From reading the (RH9-using) GLibc 2.3.2 sysdeps/generic/_strerror.c,
+ * we can say the following:
+ * - If errnum is a valid error number, a pointer to a constant string is
+ * returned. Thus, the prototype *lies* (it's not really a char*).
+ * `buf' is unchanged (WTF?).
+ * - If errnum is an *invalid* error number, an error message is copied
+ * into `buf' and `buf' is returned. The error message returned is
+ * "Unknown error %i", where %i is the input errnum.
+ *
+ * Meanwhile, XPG always modifies `buf' if there's enough space, and either
+ * returns 0 (success) or -1 (error) with errno = EINVAL (bad errnum) or
+ * ERANGE (`buf' isn't big enough). Also, GLibc 2.3.3 (which has the XPG
+ * version) first checks the validity of errnum first, then does the copy.
+ *
+ * Assuming that the GNU implementation doesn't change much (ha!), we can
+ * check for EINVAL by comparing the strerror_r return to `buf', OR by
+ * comparing the return value to "Uknown error". (This assumes that
+ * strerror_r will always only return the input buffer for errors.)
+ *
+ * Check for ERANGE by comparing the string length returned by strerror_r to
+ * `n'.
+ *
+ * Then pray that this actually works...
+ */
+gint32
+Mono_Posix_Syscall_strerror_r (int errnum, char *buf, mph_size_t n)
+{
+ char *r;
+ char ebuf [sizeof(mph_unknown)];
+ size_t len;
+ size_t blen;
+
+ mph_return_if_size_t_overflow (n);
+
+ /* first, check for valid errnum */
+ r = strerror_r (errnum, ebuf, sizeof(ebuf));
+ len = strlen (r);
+
+ if (r == ebuf ||
+ strncmp (r, mph_unknown, mph_min (len, sizeof(mph_unknown))) == 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* valid errnum (we hope); is buffer big enough? */
+ blen = (size_t) n;
+ if ((len+1) > blen) {
+ errno = ERANGE;
+ return -1;
+ }
+
+ strncpy (buf, r, len);
+ buf[len] = '\0';
+
+ return 0;
+}
+
+#else /* !def _GNU_SOURCE */
+
gint32
Mono_Posix_Syscall_strerror_r (int errnum, char *buf, mph_size_t n)
{
mph_return_if_size_t_overflow (n);
return strerror_r (errnum, buf, (size_t) n);
}
+
+#endif /* def _GNU_SOURCE */
+
#endif /* def HAVE_STRERROR_R */
G_END_DECLS
static int
setfsent (void)
{
+ /* protect from bad users calling setfsent(), setfsent(), ... endfsent() */
+ if (etc_fstab != NULL)
+ fclose (etc_fstab);
etc_fstab = fopen ("/etc/vfstab", "r");
if (etc_fstab != NULL)
return 1;